c10fa98d0a
Restore original migrations (001-120) to fix schema_migrations version mismatch * Restore original migrations (001-120) to fix schema_migrations version mismatch The previous migration collapse broke deployed databases because: - Dev database was at version 120 (the real remove_text_extraction migration) - Main had collapsed migrations (001-012) + stub files (119_stub, 120_stub) - The migrate tool couldn't find version 119/120 with matching content This commit restores the original 27 migrations (versions 001-120) from before the collapse, ensuring backward compatibility with existing databases.
288 lines
9.9 KiB
PL/PgSQL
288 lines
9.9 KiB
PL/PgSQL
-- Down migration to restore query functionality
|
|
-- This recreates all query-related tables, views, and functions
|
|
|
|
-- Drop the simplified fullActiveCollectors view
|
|
DROP VIEW IF EXISTS fullActiveCollectors;
|
|
|
|
-- Recreate query type enum
|
|
CREATE TYPE queryType AS ENUM ('context_full', 'json_extractor');
|
|
|
|
-- Recreate queries table
|
|
CREATE TABLE queries (
|
|
queryId uuid primary key DEFAULT uuid_generate_v7(),
|
|
queryType queryType not null
|
|
);
|
|
|
|
-- Recreate queryVersions table
|
|
CREATE TABLE queryVersions (
|
|
queryId uuid not null,
|
|
versionId int not null,
|
|
addedAt timestamp not null default current_timestamp,
|
|
primary key (versionId, queryId),
|
|
foreign key (queryId) references queries(queryId)
|
|
);
|
|
|
|
-- Recreate version number function and trigger
|
|
CREATE OR REPLACE FUNCTION setQueryVersionNumber()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
SELECT COALESCE(MAX(versionId), 0) + 1
|
|
INTO NEW.versionId
|
|
FROM queryVersions
|
|
WHERE queryId = NEW.queryId;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER setQueryVersionNumberTrigger
|
|
BEFORE INSERT ON queryVersions
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION setQueryVersionNumber();
|
|
|
|
-- Recreate queryActiveVersions table
|
|
CREATE TABLE queryActiveVersions (
|
|
activeVersionEntryId uuid primary key DEFAULT uuid_generate_v7(),
|
|
queryId uuid not null,
|
|
versionId int not null,
|
|
foreign key (queryId, versionId) references queryVersions(queryId, versionId)
|
|
);
|
|
|
|
-- Recreate requiredQueries table
|
|
CREATE TABLE requiredQueries (
|
|
requiredQueryEntryId uuid primary key DEFAULT uuid_generate_v7(),
|
|
queryId uuid not null,
|
|
requiredQueryId uuid not null,
|
|
addedVersion int not null,
|
|
removedVersion int,
|
|
foreign key (queryId) references queries(queryId),
|
|
foreign key (requiredQueryId) references queries(queryId),
|
|
foreign key (queryId, addedVersion) references queryVersions(queryId, versionId),
|
|
foreign key (queryId, removedVersion) references queryVersions(queryId, versionId),
|
|
unique (queryId, requiredQueryId, removedVersion)
|
|
);
|
|
|
|
-- Recreate queryConfigs table
|
|
CREATE TABLE queryConfigs (
|
|
configId uuid primary key DEFAULT uuid_generate_v7(),
|
|
queryId uuid not null,
|
|
config jsonb not null,
|
|
addedVersion int not null,
|
|
removedVersion int,
|
|
foreign key (queryId) references queries(queryId),
|
|
foreign key (queryId, addedVersion) references queryVersions(queryId, versionId),
|
|
foreign key (queryId, removedVersion) references queryVersions(queryId, versionId),
|
|
unique (queryId, removedVersion)
|
|
);
|
|
|
|
-- Recreate removeQueryConfig function and trigger
|
|
CREATE OR REPLACE FUNCTION removeQueryConfig()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
UPDATE queryConfigs
|
|
SET removedVersion = NEW.addedVersion
|
|
WHERE queryId = NEW.queryId and removedVersion is null;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER removeQueryConfigTrigger
|
|
BEFORE INSERT ON queryConfigs
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION removeQueryConfig();
|
|
|
|
-- Recreate collectorQueries table
|
|
CREATE TABLE collectorQueries (
|
|
id uuid primary key DEFAULT uuid_generate_v7(),
|
|
clientId varchar(255) not null,
|
|
name varchar(255) not null,
|
|
queryId uuid not null,
|
|
addedVersion int not null,
|
|
removedVersion int,
|
|
foreign key (queryId) references queries(queryId),
|
|
foreign key (clientId) references clients(clientId),
|
|
foreign key (clientId, addedVersion) references collectorVersions(clientId, id),
|
|
foreign key (clientId, removedVersion) references collectorVersions(clientId, id),
|
|
unique (clientId, name, removedVersion)
|
|
);
|
|
|
|
-- Recreate results table
|
|
CREATE TABLE results (
|
|
id uuid primary key DEFAULT uuid_generate_v7(),
|
|
textEntryId uuid not null,
|
|
queryId uuid not null,
|
|
value TEXT not null,
|
|
queryVersion int not null,
|
|
foreign key (queryId) references queries(queryId),
|
|
foreign key (textEntryId) references documentTextExtractions(id),
|
|
foreign key (queryId, queryVersion) references queryVersions(queryId, versionId)
|
|
);
|
|
|
|
-- Recreate resultDependencies table
|
|
CREATE TABLE resultDependencies (
|
|
resultId uuid not null,
|
|
requiredResultId uuid not null,
|
|
foreign key (resultId) references results(id),
|
|
foreign key (requiredResultId) references results(id),
|
|
CONSTRAINT result_not_self_dependent CHECK (resultId != requiredResultId)
|
|
);
|
|
|
|
-- Recreate query views
|
|
CREATE VIEW queryCurrentActiveVersions as
|
|
SELECT DISTINCT
|
|
q.queryId,
|
|
coalesce(
|
|
(FIRST_VALUE(av.versionId) OVER (PARTITION BY q.queryId ORDER BY av.activeVersionEntryId DESC)),
|
|
0
|
|
)::int as activeVersion
|
|
FROM queries AS q
|
|
LEFT JOIN queryActiveVersions as av on av.queryId = q.queryId;
|
|
|
|
CREATE VIEW queryLatestVersions as
|
|
SELECT
|
|
q.queryId,
|
|
coalesce(max(v.versionId), 0)::int as latestVersion
|
|
FROM queries AS q
|
|
LEFT JOIN queryVersions as v on v.queryId = q.queryId
|
|
GROUP BY q.queryId;
|
|
|
|
CREATE VIEW queryCurrentConfigs as
|
|
SELECT av.queryId, c.config
|
|
FROM queryCurrentActiveVersions as av
|
|
LEFT JOIN queryConfigs AS c ON av.queryId = c.queryId
|
|
and isInVersion(av.activeVersion, c.addedVersion, c.removedVersion);
|
|
|
|
CREATE VIEW queryCurrentRequiredIds as
|
|
SELECT DISTINCT av.queryId, r.requiredQueryId
|
|
FROM queryCurrentActiveVersions as av
|
|
LEFT JOIN requiredQueries AS r ON av.queryId = r.queryId
|
|
and isInVersion(av.activeVersion, r.addedVersion, r.removedVersion);
|
|
|
|
CREATE VIEW queryCurrentRequiredIdsAGG as
|
|
SELECT queryId,
|
|
coalesce(
|
|
ARRAY_AGG(DISTINCT requiredQueryId)
|
|
FILTER (WHERE requiredQueryId != '00000000-0000-0000-0000-000000000000')::uuid[],
|
|
array[]::uuid[]
|
|
)::uuid[] as requiredIds
|
|
FROM queryCurrentRequiredIds
|
|
GROUP BY queryId;
|
|
|
|
CREATE VIEW fullActiveQueries AS
|
|
SELECT DISTINCT q.queryId, q.queryType, av.activeVersion, lv.latestVersion, c.config, r.requiredIds
|
|
FROM queries AS q
|
|
JOIN queryCurrentActiveVersions as av on q.queryId = av.queryId
|
|
JOIN queryLatestVersions as lv on lv.queryId = q.queryId
|
|
JOIN queryCurrentConfigs AS c ON q.queryId = c.queryId
|
|
JOIN queryCurrentRequiredIdsAGG AS r ON q.queryId = r.queryId;
|
|
|
|
CREATE VIEW queryActiveDependencies AS
|
|
WITH RECURSIVE queryActiveDependencies(queryId, requiredQueryId, path, cycle) AS (
|
|
SELECT
|
|
queryId,
|
|
requiredQueryId,
|
|
ARRAY[queryId, requiredQueryId]::uuid[] AS path,
|
|
false AS cycle
|
|
FROM queryCurrentRequiredIds
|
|
|
|
UNION ALL
|
|
|
|
SELECT
|
|
q.queryId,
|
|
qd.requiredQueryId,
|
|
path || qd.requiredQueryId,
|
|
qd.requiredQueryId = ANY(path) AS cycle
|
|
FROM queryCurrentRequiredIds as q
|
|
JOIN queryActiveDependencies as qd ON q.queryId = qd.requiredQueryId
|
|
WHERE NOT qd.cycle
|
|
)
|
|
SELECT DISTINCT queryId as id, requiredQueryId
|
|
FROM queryActiveDependencies
|
|
WHERE NOT cycle;
|
|
|
|
-- Recreate collector views that depend on queries
|
|
CREATE VIEW currentCollectorQueries as
|
|
SELECT DISTINCT
|
|
av.clientId,
|
|
q.name,
|
|
q.queryId
|
|
FROM collectorCurrentActiveVersions as av
|
|
LEFT JOIN collectorQueries AS q ON av.clientId = q.clientId
|
|
and isInVersion(av.activeVersion, q.addedVersion, q.removedVersion);
|
|
|
|
CREATE VIEW currentCollectorQueriesJSONAGG as
|
|
SELECT DISTINCT
|
|
clientId,
|
|
jsonb_object_agg(name, queryId) FILTER (WHERE name is not null) AS fields
|
|
FROM currentCollectorQueries
|
|
GROUP BY clientId;
|
|
|
|
CREATE VIEW fullActiveCollectors AS
|
|
SELECT DISTINCT av.clientId,
|
|
ccv.minCleanVersion, ctv.minTextVersion,
|
|
av.activeVersion, lv.latestVersion,
|
|
q.fields
|
|
FROM collectorCurrentActiveVersions as av
|
|
JOIN collectorLatestVersions as lv on lv.clientId = av.clientId
|
|
JOIN currentCollectorMinCleanVersions AS ccv ON av.clientId = ccv.clientId
|
|
JOIN currentCollectorMinTextVersions AS ctv ON av.clientId = ctv.clientId
|
|
JOIN currentCollectorQueriesJSONAGG AS q ON av.clientId = q.clientId;
|
|
|
|
CREATE VIEW collectorQueryDependencyTree AS
|
|
WITH RECURSIVE collectorQueryDependencyTree AS (
|
|
SELECT cq.clientId, cq.queryId, ri.requiredIds
|
|
FROM currentCollectorQueries as cq
|
|
JOIN queryCurrentRequiredIdsAGG as ri on cq.queryId = ri.queryId
|
|
|
|
UNION ALL
|
|
|
|
SELECT acq.clientId, q.queryId, q.requiredIds
|
|
FROM queryCurrentRequiredIdsAGG as q
|
|
JOIN collectorQueryDependencyTree as acq on q.queryId = ANY(acq.requiredIds)
|
|
)
|
|
SELECT DISTINCT ct.clientId, ct.queryId, q.queryType, av.activeVersion as queryVersion, ct.requiredIds
|
|
FROM collectorQueryDependencyTree as ct
|
|
JOIN queryCurrentActiveVersions as av on ct.queryId = av.queryId
|
|
JOIN queries as q on q.queryId = ct.queryId;
|
|
|
|
CREATE OR REPLACE FUNCTION collectorQueryDependencyTreeByClient(
|
|
_clientId varchar(255)
|
|
)
|
|
RETURNS TABLE (
|
|
clientId varchar(255),
|
|
queryId uuid,
|
|
queryType queryType,
|
|
queryVersion int,
|
|
requiredIds uuid[]
|
|
) AS $$
|
|
BEGIN
|
|
RETURN QUERY
|
|
WITH clientQueries as (
|
|
SELECT q.clientId, q.queryId
|
|
FROM currentCollectorQueries as q
|
|
WHERE q.clientId = _clientId
|
|
),
|
|
dependencyTree as (
|
|
WITH RECURSIVE collectorQueryDependencyTree AS (
|
|
SELECT cq.clientId, cq.queryId, ri.requiredIds
|
|
FROM clientQueries as cq
|
|
JOIN queryCurrentRequiredIdsAGG as ri on cq.queryId = ri.queryId
|
|
|
|
UNION ALL
|
|
|
|
SELECT acq.clientId, q.queryId, q.requiredIds
|
|
FROM queryCurrentRequiredIdsAGG as q
|
|
JOIN collectorQueryDependencyTree as acq on q.queryId = ANY(acq.requiredIds)
|
|
)
|
|
SELECT DISTINCT ct.clientId, ct.queryId, q.queryType, av.activeVersion as queryVersion, ct.requiredIds
|
|
FROM collectorQueryDependencyTree as ct
|
|
JOIN queryCurrentActiveVersions as av on ct.queryId = av.queryId
|
|
JOIN queries as q on q.queryId = ct.queryId
|
|
)
|
|
SELECT t.clientId, t.queryId, t.queryType, t.queryVersion, t.requiredIds
|
|
FROM dependencyTree as t
|
|
WHERE t.clientID is not null;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|