Files
incudal/server/prisma/migrations/20260501133000_add_log_instance_id/migration.sql
T
2026-06-20 14:26:29 +08:00

158 lines
4.5 KiB
SQL

ALTER TABLE "logs"
ADD COLUMN "instance_id" INTEGER;
ALTER TABLE "logs"
ADD CONSTRAINT "logs_instance_id_fkey"
FOREIGN KEY ("instance_id") REFERENCES "instances"("id")
ON DELETE SET NULL ON UPDATE CASCADE;
CREATE INDEX "logs_instance_id_idx" ON "logs"("instance_id");
WITH id_matches AS (
SELECT
l."id" AS "log_id",
l."user_id",
(m."match")[1]::integer AS "instance_id"
FROM "logs" l
CROSS JOIN LATERAL regexp_matches(l."content", 'instance[[:space:]]*#([0-9]+)', 'gi') AS m("match")
WHERE l."instance_id" IS NULL
UNION ALL
SELECT
l."id" AS "log_id",
l."user_id",
(m."match")[1]::integer AS "instance_id"
FROM "logs" l
CROSS JOIN LATERAL regexp_matches(l."content", 'instance:[[:space:]]*[^()]*\(#([0-9]+)\)', 'gi') AS m("match")
WHERE l."instance_id" IS NULL
UNION ALL
SELECT
l."id" AS "log_id",
l."user_id",
(m."match")[1]::integer AS "instance_id"
FROM "logs" l
CROSS JOIN LATERAL regexp_matches(l."content", 'new instance ID:[[:space:]]*([0-9]+)', 'gi') AS m("match")
WHERE l."instance_id" IS NULL
),
id_candidates AS (
SELECT
im."log_id",
MIN(im."instance_id") AS "instance_id",
COUNT(DISTINCT im."instance_id") AS "match_count"
FROM id_matches im
JOIN "instances" i
ON i."id" = im."instance_id"
AND (im."user_id" IS NULL OR i."user_id" = im."user_id")
GROUP BY im."log_id"
)
UPDATE "logs" l
SET "instance_id" = c."instance_id"
FROM id_candidates c
WHERE l."id" = c."log_id"
AND c."match_count" = 1;
WITH rename_logs AS (
SELECT
l."id",
l."user_id",
l."created_at",
substring(l."content" from 'Renamed instance from "([^"]+)" to "[^"]+"') AS "old_name",
substring(l."content" from 'Renamed instance from "[^"]+" to "([^"]+)"') AS "new_name"
FROM "logs" l
WHERE l."action" = 'instance.rename'
AND l."instance_id" IS NULL
),
rename_candidates AS (
SELECT
r."id" AS "log_id",
i."id" AS "instance_id",
COUNT(*) OVER (PARTITION BY r."id") AS "match_count"
FROM rename_logs r
JOIN "instances" i
ON i."user_id" = r."user_id"
AND i."name" = r."new_name"
AND i."created_at" <= r."created_at"
WHERE r."old_name" IS NOT NULL
AND r."new_name" IS NOT NULL
)
UPDATE "logs" l
SET "instance_id" = c."instance_id"
FROM rename_candidates c
WHERE l."id" = c."log_id"
AND c."match_count" = 1;
WITH RECURSIVE rename_history AS (
SELECT
l."user_id",
l."instance_id",
i."created_at" AS "instance_created_at",
substring(l."content" from 'Renamed instance from "([^"]+)" to "[^"]+"') AS "old_name",
substring(l."content" from 'Renamed instance from "[^"]+" to "([^"]+)"') AS "new_name",
l."created_at",
1 AS "depth"
FROM "logs" l
JOIN "instances" i
ON i."id" = l."instance_id"
WHERE l."action" = 'instance.rename'
AND l."instance_id" IS NOT NULL
UNION ALL
SELECT
prev."user_id",
rh."instance_id",
rh."instance_created_at",
substring(prev."content" from 'Renamed instance from "([^"]+)" to "[^"]+"') AS "old_name",
substring(prev."content" from 'Renamed instance from "[^"]+" to "([^"]+)"') AS "new_name",
prev."created_at",
rh."depth" + 1 AS "depth"
FROM rename_history rh
JOIN "logs" prev
ON prev."action" = 'instance.rename'
AND prev."user_id" = rh."user_id"
AND prev."created_at" < rh."created_at"
AND substring(prev."content" from 'Renamed instance from "[^"]+" to "([^"]+)"') = rh."old_name"
WHERE rh."depth" < 20
),
old_name_candidates AS (
SELECT
l."id" AS "log_id",
r."instance_id",
COUNT(*) OVER (PARTITION BY l."id") AS "match_count"
FROM "logs" l
JOIN rename_history r
ON r."user_id" = l."user_id"
AND l."created_at" < r."created_at"
AND l."created_at" >= r."instance_created_at"
AND strpos(lower(l."content"), lower('instance "' || r."old_name" || '"')) > 0
WHERE l."instance_id" IS NULL
AND r."old_name" IS NOT NULL
AND r."new_name" IS NOT NULL
)
UPDATE "logs" l
SET "instance_id" = c."instance_id"
FROM old_name_candidates c
WHERE l."id" = c."log_id"
AND c."match_count" = 1;
WITH current_name_candidates AS (
SELECT
l."id" AS "log_id",
i."id" AS "instance_id",
COUNT(*) OVER (PARTITION BY l."id") AS "match_count"
FROM "logs" l
JOIN "instances" i
ON i."user_id" = l."user_id"
AND l."created_at" >= i."created_at"
AND strpos(lower(l."content"), lower('instance "' || i."name" || '"')) > 0
WHERE l."instance_id" IS NULL
)
UPDATE "logs" l
SET "instance_id" = c."instance_id"
FROM current_name_candidates c
WHERE l."id" = c."log_id"
AND c."match_count" = 1;