Merged in feature/remove-query (pull request #201)

remove query from codebase part 1

* remove query

* fix localstack run
This commit is contained in:
Jay Brown
2026-01-14 17:59:04 +00:00
parent ebf47c6013
commit 0ddae4f91e
167 changed files with 1059 additions and 20641 deletions
@@ -0,0 +1,287 @@
-- 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;
@@ -0,0 +1,53 @@
-- Migration to remove query functionality from the database
-- This drops all query-related tables, views, and functions
-- First drop the function that depends on query views
DROP FUNCTION IF EXISTS collectorQueryDependencyTreeByClient;
-- Drop the collector views that depend on query tables (in order of dependencies)
DROP VIEW IF EXISTS collectorQueryDependencyTree;
DROP VIEW IF EXISTS fullActiveCollectors;
DROP VIEW IF EXISTS currentCollectorQueriesJSONAGG;
DROP VIEW IF EXISTS currentCollectorQueries;
-- Drop query views (in order of dependencies)
DROP VIEW IF EXISTS fullActiveQueries;
DROP VIEW IF EXISTS queryActiveDependencies;
DROP VIEW IF EXISTS queryCurrentRequiredIdsAGG;
DROP VIEW IF EXISTS queryCurrentRequiredIds;
DROP VIEW IF EXISTS queryCurrentConfigs;
DROP VIEW IF EXISTS queryLatestVersions;
DROP VIEW IF EXISTS queryCurrentActiveVersions;
-- Drop result tables
DROP TABLE IF EXISTS resultDependencies;
DROP TABLE IF EXISTS results;
-- Drop collectorQueries table (links collectors to queries)
DROP TABLE IF EXISTS collectorQueries;
-- Drop query configuration and dependency tables
DROP TABLE IF EXISTS queryConfigs;
DROP TABLE IF EXISTS requiredQueries;
DROP TABLE IF EXISTS queryActiveVersions;
DROP TABLE IF EXISTS queryVersions;
DROP TABLE IF EXISTS queries;
-- Drop triggers and functions
DROP TRIGGER IF EXISTS setQueryVersionNumberTrigger ON queryVersions;
DROP FUNCTION IF EXISTS setQueryVersionNumber;
DROP TRIGGER IF EXISTS removeQueryConfigTrigger ON queryConfigs;
DROP FUNCTION IF EXISTS removeQueryConfig;
-- Drop the query type enum
DROP TYPE IF EXISTS queryType;
-- Recreate the fullActiveCollectors view without the fields column
CREATE VIEW fullActiveCollectors AS
SELECT DISTINCT av.clientId,
ccv.minCleanVersion, ctv.minTextVersion,
av.activeVersion, lv.latestVersion
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;
+10 -58
View File
@@ -15,6 +15,9 @@ UPDATE clients SET name = $1 WHERE clientId = $2;
INSERT INTO clientCanSync (canSync, clientId) VALUES ($1, $2);
-- name: IsClientSynced :one
-- Query functionality has been removed. A client is considered synced when
-- all documents have completed text extraction (or failed with explicit failure).
-- See remove_query_plan.md for details.
WITH
docs AS (
-- Get all documents for this client
@@ -42,46 +45,6 @@ doc_text_entries AS (
FROM
doc_clean_entries d
LEFT JOIN currentTextEntries cte ON cte.cleanId = d.clean_entry_id
),
required_results AS (
-- All required document-query-version combinations
SELECT
dte.document_id,
cqdt.queryId,
cqdt.queryVersion,
dte.text_entry_id
FROM
doc_text_entries dte
JOIN collectorQueryDependencyTreeByClient($1) cqdt ON cqdt.clientId = dte.client_id
where dte.clean_fail is null and dte.text_entry_id IS NOT NULL
),
existing_results AS (
-- Valid results that exist
SELECT
rr.document_id AS document_id,
r.queryId,
r.id AS result_id
FROM
results r
JOIN required_results rr ON
r.queryId = rr.queryId AND
r.queryVersion = rr.queryVersion AND
r.textEntryId = rr.text_entry_id
),
missing_results AS (
-- Find missing results
SELECT rr.queryId
FROM required_results rr
LEFT JOIN existing_results er on er.queryId = rr.queryId
WHERE er.result_id is null
),
dependency_check AS (
-- Check for missing dependencies
SELECT DISTINCT er.queryId, er.result_id, qcri.queryId, rd.resultId
FROM existing_results er
JOIN queryCurrentRequiredIds qcri on qcri.requiredQueryId = er.queryId
LEFT JOIN resultDependencies rd on rd.requiredResultId = er.result_id
WHERE rd.resultId is null
)
SELECT (
-- No documents means client is synced
@@ -89,22 +52,11 @@ SELECT (
OR
-- Documents with no text entries
(
NOT EXISTS (
SELECT 1 FROM doc_text_entries
where clean_entry_id is null or
(clean_fail is null and text_entry_id is null)
)
and
-- Documents with missing results
NOT EXISTS (SELECT 1 FROM missing_results)
and
-- Documents with missing dependencies
NOT EXISTS (SELECT 1 FROM dependency_check)
)::bool
-- All documents have completed processing (clean entry exists and either
-- text entry exists or clean failed)
NOT EXISTS (
SELECT 1 FROM doc_text_entries
where clean_entry_id is null or
(clean_fail is null and text_entry_id is null)
)
)::bool as is_synced;
-10
View File
@@ -1,7 +1,3 @@
-- name: ListCollectorQueries :many
SELECT clientId, queryId, queryType, queryVersion, requiredIds
FROM collectorQueryDependencyTreeByClient(@clientId);
-- name: GetCollectorByClientID :one
SELECT * FROM fullActiveCollectors WHERE clientId = @clientId LIMIT 1;
@@ -16,9 +12,3 @@ INSERT INTO collectorMinCleanVersions (clientId, addedVersion, versionId) VALUES
-- name: SetCollectorTextVersion :exec
INSERT INTO collectorMinTextVersions (clientId, addedVersion, versionId) VALUES ($1, $2, $3);
-- name: AddCollectorQuery :exec
INSERT INTO collectorQueries (clientId, name, queryId, addedVersion) VALUES ($1, $2, $3, $4);
-- name: RemoveCollectorQuery :exec
UPDATE collectorQueries SET removedVersion = $1 WHERE queryId = $2 and clientId = $3 and removedVersion is null;
+6 -23
View File
@@ -2,30 +2,13 @@
SELECT id, clientId, hash FROM documents WHERE id = $1;
-- name: GetDocumentExternal :one
WITH
docs AS (
SELECT id, hash, clientId
FROM documents
WHERE id = @documentId
),
namedResults AS (
SELECT
q.name,
dd.id,
d.value
FROM currentCollectorQueries AS q
JOIN docs as dd on dd.clientId = q.clientId
LEFT JOIN listValidDocumentResults(@documentId) AS d
ON d.queryId = q.queryId and q.name is not null
)
-- Query functionality has been removed. See remove_query_plan.md for details.
SELECT
d.id,
d.clientId,
d.hash,
COALESCE(jsonb_object_agg(r.name, r.value) FILTER (WHERE r.name IS NOT NULL), '{}') AS fields
FROM docs AS d
LEFT JOIN namedResults AS r ON d.id = r.id
GROUP BY d.id, d.clientId, d.hash;
id,
clientId,
hash
FROM documents
WHERE id = @documentId;
-- name: ListDocumentsByClient :many
SELECT id, hash from documents where clientId = @clientId;
-86
View File
@@ -1,86 +0,0 @@
-- name: GetActiveQueryConfig :one
SELECT config FROM queryCurrentConfigs where queryId = $1;
-- name: GetQuery :one
SELECT * FROM fullActiveQueries WHERE queryId = $1;
-- name: GetQueryWithVersion :one
WITH query as (
SELECT queryId, queryType FROM queries WHERE queryId = @id
),
config as (
SELECT c.queryId, c.config
FROM query AS q
LEFT JOIN queryConfigs AS c ON q.queryId = c.queryId
and isInVersion(@version, c.addedVersion, c.removedVersion)
),
requiredIds as (
SELECT r.queryId,
coalesce(
ARRAY_AGG(DISTINCT r.requiredQueryId)
FILTER (WHERE r.requiredQueryId != '00000000-0000-0000-0000-000000000000')::uuid[],
array[]::uuid[]
)::uuid[] as requiredIds
FROM query AS q
LEFT JOIN requiredQueries AS r ON q.queryId = r.queryId
and isInVersion(@version, r.addedVersion, r.removedVersion)
GROUP BY r.queryId
)
SELECT DISTINCT q.queryId, q.queryType,
av.activeVersion,
lv.latestVersion, c.config,
r.requiredIds
FROM query AS q
JOIN queryCurrentActiveVersions as av on q.queryId = av.queryId
JOIN queryLatestVersions as lv on lv.queryId = q.queryId
LEFT JOIN config AS c ON q.queryId = c.queryId
LEFT JOIN requiredIds AS r ON q.queryId = r.queryId;
-- name: ListQueries :many
SELECT * FROM fullActiveQueries;
-- name: ListQueriesById :many
SELECT * FROM fullActiveQueries WHERE queryId = any($1);
-- name: CreateQuery :one
INSERT INTO queries (queryType) VALUES ($1) RETURNING queryId;
-- name: AddLatestQueryVersion :one
INSERT INTO queryVersions (queryId) VALUES ($1) RETURNING versionId;
-- name: AddActiveQueryVersion :exec
INSERT INTO queryActiveVersions (queryId, versionId) VALUES ($1, $2);
-- name: AddRequiredQuery :exec
INSERT INTO requiredQueries (queryId, requiredQueryId, addedVersion) VALUES ($1, $2, $3);
-- name: RemoveRequiredQuery :exec
UPDATE requiredQueries SET removedVersion = $1 WHERE requiredQueryId = $2 and queryId = $3 and removedVersion is null;
-- name: SetQueryConfig :exec
INSERT INTO queryConfigs (queryId, config, addedVersion) VALUES ($1, $2, $3);
-- name: AllQueriesExist :one
SELECT COUNT(*) = COUNT(DISTINCT queryId) AS all_exist
FROM unnest($1::uuid[]) AS input_id
LEFT JOIN queries ON input_id = queries.queryId;
-- name: IsQueryInDependencyTree :one
SELECT EXISTS (
SELECT 1 FROM queryActiveDependencies
WHERE id = any(@requiredQueryIds)
and requiredQueryId = @queryId
or @queryId = any(@requiredQueryIds)
);
-- name: ListQueryDirectDependentsByDocumentID :many
WITH doc AS (
SELECT clientId FROM documents WHERE id = @documentId
)
SELECT dt.queryId
FROM doc,
LATERAL collectorQueryDependencyTreeByClient(doc.clientId) AS dt
WHERE @queryId = ANY(dt.requiredIds);
-- name: ListQueryClientIDs :many
SELECT clientId FROM collectorQueryDependencyTree WHERE queryId = $1;
-92
View File
@@ -1,92 +0,0 @@
-- name: ListQueryRequirementValues :many
WITH reqQueries as (
SELECT av.queryId, av.activeVersion, q.queryType
FROM requiredQueries as rq
JOIN queryCurrentActiveVersions as av on av.queryId = rq.requiredQueryId
JOIN queries as q on q.queryId = av.queryId
WHERE rq.queryId = @queryId
and isInVersion(@version, rq.addedVersion, rq.removedVersion)
),
docs as (
SELECT id, clientId
FROM documents
WHERE id = @documentId
),
codeVersions as (
SELECT
d.id as documentId,
mcv.minCleanVersion,
mtv.minTextVersion
FROM docs as d
JOIN currentCollectorMinTextVersions as mtv on mtv.clientId = d.clientId
JOIN currentCollectorMinCleanVersions as mcv on mcv.clientId = d.clientId
),
latestVersions AS (
SELECT
r.id,
rq.queryId,
rq.queryType,
r.queryVersion,
r.textEntryId,
r.value,
ROW_NUMBER() OVER (
PARTITION BY r.queryId
ORDER BY r.id DESC
) as rowNumber
FROM reqQueries as rq
JOIN currentTextEntries as cte on cte.documentId = @documentId
LEFT JOIN results as r ON rq.queryId = r.queryId
and r.queryVersion = rq.activeVersion
and cte.id = r.textEntryId
)
SELECT DISTINCT id, queryId, queryType, value
FROM latestVersions
WHERE rowNumber = 1;
-- name: AddResult :one
INSERT INTO results (queryId, value, textEntryId, queryVersion) VALUES ($1, $2, $3, $4) returning id;
-- name: AddResultDependency :exec
INSERT INTO resultDependencies (resultId, requiredResultId) VALUES ($1, $2);
-- name: GetResultValueWithVersion :one
WITH doc as (
SELECT id, clientId
FROM documents
WHERE id = @documentId
)
SELECT r.id, r.value
FROM doc as d
JOIN currentTextEntries as cte on cte.documentId = d.id
LEFT JOIN results as r
on r.queryId = @queryId
and r.queryVersion = @queryVersion
and r.textEntryId = cte.id;
-- name: ListUnsyncedNoDepsQueriesByDocId :many
WITH docs as (
SELECT id, clientId from documents where id = $1
),
dependency_tree as (
select q.queryId, q.requiredIds, q.clientId, q.queryVersion
from docs,
LATERAL collectorQueryDependencyTreeByClient(docs.clientId) AS q
),
text_entries as (
select id, documentId from currentTextEntries where documentId = $1
),
unsyncedQueries AS (
SELECT DISTINCT dt.queryId, dt.requiredIds
from docs as d
JOIN dependency_tree as dt on d.clientId = dt.clientId
JOIN text_entries as cte on cte.documentId = d.id
LEFT JOIN results as r
on r.queryId = dt.queryId
and r.queryVersion = dt.queryVersion
and cte.id = r.textEntryId
where r.value is null
)
SELECT DISTINCT queryId FROM unsyncedQueries as baseuq
WHERE NOT EXISTS (
SELECT 1 FROM unsyncedQueries as uq WHERE uq.queryId = any(baseuq.requiredIds)
);
+17 -117
View File
@@ -85,46 +85,6 @@ doc_text_entries AS (
FROM
doc_clean_entries d
LEFT JOIN currentTextEntries cte ON cte.cleanId = d.clean_entry_id
),
required_results AS (
-- All required document-query-version combinations
SELECT
dte.document_id,
cqdt.queryId,
cqdt.queryVersion,
dte.text_entry_id
FROM
doc_text_entries dte
JOIN collectorQueryDependencyTreeByClient($1) cqdt ON cqdt.clientId = dte.client_id
where dte.clean_fail is null and dte.text_entry_id IS NOT NULL
),
existing_results AS (
-- Valid results that exist
SELECT
rr.document_id AS document_id,
r.queryId,
r.id AS result_id
FROM
results r
JOIN required_results rr ON
r.queryId = rr.queryId AND
r.queryVersion = rr.queryVersion AND
r.textEntryId = rr.text_entry_id
),
missing_results AS (
-- Find missing results
SELECT rr.queryId
FROM required_results rr
LEFT JOIN existing_results er on er.queryId = rr.queryId
WHERE er.result_id is null
),
dependency_check AS (
-- Check for missing dependencies
SELECT DISTINCT er.queryId, er.result_id, qcri.queryId, rd.resultId
FROM existing_results er
JOIN queryCurrentRequiredIds qcri on qcri.requiredQueryId = er.queryId
LEFT JOIN resultDependencies rd on rd.requiredResultId = er.result_id
WHERE rd.resultId is null
)
SELECT (
-- No documents means client is synced
@@ -132,28 +92,19 @@ SELECT (
OR
-- Documents with no text entries
(
NOT EXISTS (
SELECT 1 FROM doc_text_entries
where clean_entry_id is null or
(clean_fail is null and text_entry_id is null)
)
and
-- Documents with missing results
NOT EXISTS (SELECT 1 FROM missing_results)
and
-- Documents with missing dependencies
NOT EXISTS (SELECT 1 FROM dependency_check)
)::bool
-- All documents have completed processing (clean entry exists and either
-- text entry exists or clean failed)
NOT EXISTS (
SELECT 1 FROM doc_text_entries
where clean_entry_id is null or
(clean_fail is null and text_entry_id is null)
)
)::bool as is_synced
`
// IsClientSynced
// Query functionality has been removed. A client is considered synced when
// all documents have completed text extraction (or failed with explicit failure).
// See remove_query_plan.md for details.
//
// WITH
// docs AS (
@@ -182,46 +133,6 @@ SELECT (
// FROM
// doc_clean_entries d
// LEFT JOIN currentTextEntries cte ON cte.cleanId = d.clean_entry_id
// ),
// required_results AS (
// -- All required document-query-version combinations
// SELECT
// dte.document_id,
// cqdt.queryId,
// cqdt.queryVersion,
// dte.text_entry_id
// FROM
// doc_text_entries dte
// JOIN collectorQueryDependencyTreeByClient($1) cqdt ON cqdt.clientId = dte.client_id
// where dte.clean_fail is null and dte.text_entry_id IS NOT NULL
// ),
// existing_results AS (
// -- Valid results that exist
// SELECT
// rr.document_id AS document_id,
// r.queryId,
// r.id AS result_id
// FROM
// results r
// JOIN required_results rr ON
// r.queryId = rr.queryId AND
// r.queryVersion = rr.queryVersion AND
// r.textEntryId = rr.text_entry_id
// ),
// missing_results AS (
// -- Find missing results
// SELECT rr.queryId
// FROM required_results rr
// LEFT JOIN existing_results er on er.queryId = rr.queryId
// WHERE er.result_id is null
// ),
// dependency_check AS (
// -- Check for missing dependencies
// SELECT DISTINCT er.queryId, er.result_id, qcri.queryId, rd.resultId
// FROM existing_results er
// JOIN queryCurrentRequiredIds qcri on qcri.requiredQueryId = er.queryId
// LEFT JOIN resultDependencies rd on rd.requiredResultId = er.result_id
// WHERE rd.resultId is null
// )
// SELECT (
// -- No documents means client is synced
@@ -229,24 +140,13 @@ SELECT (
//
// OR
//
// -- Documents with no text entries
// (
// NOT EXISTS (
// SELECT 1 FROM doc_text_entries
// where clean_entry_id is null or
// (clean_fail is null and text_entry_id is null)
// )
//
// and
//
// -- Documents with missing results
// NOT EXISTS (SELECT 1 FROM missing_results)
//
// and
//
// -- Documents with missing dependencies
// NOT EXISTS (SELECT 1 FROM dependency_check)
// )::bool
// -- All documents have completed processing (clean entry exists and either
// -- text entry exists or clean failed)
// NOT EXISTS (
// SELECT 1 FROM doc_text_entries
// where clean_entry_id is null or
// (clean_fail is null and text_entry_id is null)
// )
// )::bool as is_synced
func (q *Queries) IsClientSynced(ctx context.Context, dollar_1 *string) (bool, error) {
row := q.db.QueryRow(ctx, isClientSynced, dollar_1)
+2 -90
View File
@@ -7,34 +7,8 @@ package repository
import (
"context"
"github.com/google/uuid"
)
const addCollectorQuery = `-- name: AddCollectorQuery :exec
INSERT INTO collectorQueries (clientId, name, queryId, addedVersion) VALUES ($1, $2, $3, $4)
`
type AddCollectorQueryParams struct {
Clientid string `db:"clientid"`
Name string `db:"name"`
Queryid uuid.UUID `db:"queryid"`
Addedversion int32 `db:"addedversion"`
}
// AddCollectorQuery
//
// INSERT INTO collectorQueries (clientId, name, queryId, addedVersion) VALUES ($1, $2, $3, $4)
func (q *Queries) AddCollectorQuery(ctx context.Context, arg *AddCollectorQueryParams) error {
_, err := q.db.Exec(ctx, addCollectorQuery,
arg.Clientid,
arg.Name,
arg.Queryid,
arg.Addedversion,
)
return err
}
const addLatestCollectorVersion = `-- name: AddLatestCollectorVersion :one
INSERT INTO collectorVersions (clientId) VALUES ($1) RETURNING id
`
@@ -50,12 +24,12 @@ func (q *Queries) AddLatestCollectorVersion(ctx context.Context, clientid string
}
const getCollectorByClientID = `-- name: GetCollectorByClientID :one
SELECT clientid, mincleanversion, mintextversion, activeversion, latestversion, fields FROM fullActiveCollectors WHERE clientId = $1 LIMIT 1
SELECT clientid, mincleanversion, mintextversion, activeversion, latestversion FROM fullActiveCollectors WHERE clientId = $1 LIMIT 1
`
// GetCollectorByClientID
//
// SELECT clientid, mincleanversion, mintextversion, activeversion, latestversion, fields FROM fullActiveCollectors WHERE clientId = $1 LIMIT 1
// SELECT clientid, mincleanversion, mintextversion, activeversion, latestversion FROM fullActiveCollectors WHERE clientId = $1 LIMIT 1
func (q *Queries) GetCollectorByClientID(ctx context.Context, clientid string) (*Fullactivecollector, error) {
row := q.db.QueryRow(ctx, getCollectorByClientID, clientid)
var i Fullactivecollector
@@ -65,72 +39,10 @@ func (q *Queries) GetCollectorByClientID(ctx context.Context, clientid string) (
&i.Mintextversion,
&i.Activeversion,
&i.Latestversion,
&i.Fields,
)
return &i, err
}
const listCollectorQueries = `-- name: ListCollectorQueries :many
SELECT clientId, queryId, queryType, queryVersion, requiredIds
FROM collectorQueryDependencyTreeByClient($1)
`
type ListCollectorQueriesRow struct {
Clientid *string `db:"clientid"`
Queryid *uuid.UUID `db:"queryid"`
Querytype NullQuerytype `db:"querytype"`
Queryversion *int32 `db:"queryversion"`
Requiredids []uuid.UUID `db:"requiredids"`
}
// ListCollectorQueries
//
// SELECT clientId, queryId, queryType, queryVersion, requiredIds
// FROM collectorQueryDependencyTreeByClient($1)
func (q *Queries) ListCollectorQueries(ctx context.Context, clientid string) ([]*ListCollectorQueriesRow, error) {
rows, err := q.db.Query(ctx, listCollectorQueries, clientid)
if err != nil {
return nil, err
}
defer rows.Close()
items := []*ListCollectorQueriesRow{}
for rows.Next() {
var i ListCollectorQueriesRow
if err := rows.Scan(
&i.Clientid,
&i.Queryid,
&i.Querytype,
&i.Queryversion,
&i.Requiredids,
); err != nil {
return nil, err
}
items = append(items, &i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const removeCollectorQuery = `-- name: RemoveCollectorQuery :exec
UPDATE collectorQueries SET removedVersion = $1 WHERE queryId = $2 and clientId = $3 and removedVersion is null
`
type RemoveCollectorQueryParams struct {
Removedversion *int32 `db:"removedversion"`
Queryid uuid.UUID `db:"queryid"`
Clientid string `db:"clientid"`
}
// RemoveCollectorQuery
//
// UPDATE collectorQueries SET removedVersion = $1 WHERE queryId = $2 and clientId = $3 and removedVersion is null
func (q *Queries) RemoveCollectorQuery(ctx context.Context, arg *RemoveCollectorQueryParams) error {
_, err := q.db.Exec(ctx, removeCollectorQuery, arg.Removedversion, arg.Queryid, arg.Clientid)
return err
}
const setActiveCollectorVersion = `-- name: SetActiveCollectorVersion :exec
INSERT INTO collectorActiveVersions (clientId, versionId) VALUES ($1, $2)
`
@@ -1,263 +0,0 @@
package repository_test
import (
"fmt"
"testing"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/serviceconfig"
"queryorchestration/internal/test"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCollector(t *testing.T) {
t.Parallel()
if testing.Short() {
t.SkipNow()
}
ctx := t.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(t, cfg)
queries := cfg.GetDBQueries()
contextId, err := queries.CreateQuery(ctx, repository.QuerytypeContextFull)
require.NoError(t, err)
jsonId, err := queries.CreateQuery(ctx, repository.QuerytypeJsonExtractor)
require.NoError(t, err)
version, err := queries.AddLatestQueryVersion(ctx, jsonId)
require.NoError(t, err)
err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{
Queryid: jsonId,
Versionid: version,
})
require.NoError(t, err)
assert.Equal(t, int32(1), version)
err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{
Queryid: jsonId,
Requiredqueryid: contextId,
Addedversion: version,
})
require.NoError(t, err)
clientId := "EXAMPLE"
err = queries.CreateClient(ctx, &repository.CreateClientParams{
Name: "example_client",
Clientid: clientId,
})
require.NoError(t, err)
minCleanVersion := int64(2)
minTextVersion := int64(4)
coll, err := queries.GetCollectorByClientID(ctx, clientId)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivecollector{
Clientid: clientId,
Mincleanversion: 0,
Mintextversion: 0,
Activeversion: 0,
Latestversion: 0,
}, coll)
version, err = queries.AddLatestCollectorVersion(ctx, clientId)
require.NoError(t, err)
assert.Equal(t, int32(1), version)
coll, err = queries.GetCollectorByClientID(ctx, clientId)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivecollector{
Clientid: clientId,
Mincleanversion: 0,
Mintextversion: 0,
Activeversion: 0,
Latestversion: 1,
}, coll)
err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{
Versionid: 1,
Clientid: clientId,
})
require.NoError(t, err)
coll, err = queries.GetCollectorByClientID(ctx, clientId)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivecollector{
Clientid: clientId,
Mincleanversion: 0,
Mintextversion: 0,
Activeversion: 1,
Latestversion: 1,
}, coll)
err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{
Clientid: clientId,
Queryid: jsonId,
Addedversion: 1,
Name: "example_key",
})
require.NoError(t, err)
err = queries.SetCollectorTextVersion(ctx, &repository.SetCollectorTextVersionParams{
Clientid: clientId,
Addedversion: 1,
Versionid: minTextVersion,
})
require.NoError(t, err)
coll, err = queries.GetCollectorByClientID(ctx, clientId)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivecollector{
Clientid: clientId,
Mincleanversion: 0,
Mintextversion: minTextVersion,
Activeversion: 1,
Latestversion: 1,
Fields: []byte(fmt.Sprintf("{\"example_key\": \"%s\"}", jsonId.String())),
}, coll)
err = queries.SetCollectorCleanVersion(ctx, &repository.SetCollectorCleanVersionParams{
Clientid: clientId,
Addedversion: 1,
Versionid: minCleanVersion,
})
require.NoError(t, err)
coll, err = queries.GetCollectorByClientID(ctx, clientId)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivecollector{
Clientid: clientId,
Mincleanversion: minCleanVersion,
Mintextversion: minTextVersion,
Activeversion: 1,
Latestversion: 1,
Fields: []byte(fmt.Sprintf("{\"example_key\": \"%s\"}", jsonId.String())),
}, coll)
qs, err := queries.ListCollectorQueries(ctx, clientId)
require.NoError(t, err)
assert.Len(t, qs, 2)
jsonV := int32(1)
contextV := int32(0)
assert.ElementsMatch(t, []*repository.ListCollectorQueriesRow{
{
Clientid: &clientId,
Queryid: &jsonId,
Queryversion: &jsonV,
Querytype: repository.NullQuerytype{
Querytype: repository.QuerytypeJsonExtractor,
Valid: true,
},
Requiredids: []uuid.UUID{contextId},
},
{
Clientid: &clientId,
Queryid: &contextId,
Queryversion: &contextV,
Querytype: repository.NullQuerytype{
Querytype: repository.QuerytypeContextFull,
Valid: true,
},
Requiredids: []uuid.UUID{},
},
}, qs)
version, err = queries.AddLatestCollectorVersion(ctx, clientId)
require.NoError(t, err)
assert.Equal(t, int32(2), version)
err = queries.RemoveCollectorQuery(ctx, &repository.RemoveCollectorQueryParams{
Clientid: clientId,
Queryid: jsonId,
Removedversion: &version,
})
require.NoError(t, err)
err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{
Versionid: 2,
Clientid: clientId,
})
require.NoError(t, err)
err = queries.SetCollectorTextVersion(ctx, &repository.SetCollectorTextVersionParams{
Clientid: clientId,
Versionid: minTextVersion + 1,
Addedversion: version,
})
require.NoError(t, err)
coll, err = queries.GetCollectorByClientID(ctx, clientId)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivecollector{
Clientid: clientId,
Mincleanversion: minCleanVersion,
Mintextversion: minTextVersion + 1,
Activeversion: 2,
Latestversion: 2,
Fields: nil,
}, coll)
err = queries.SetCollectorCleanVersion(ctx, &repository.SetCollectorCleanVersionParams{
Clientid: clientId,
Versionid: minCleanVersion + 1,
Addedversion: version,
})
require.NoError(t, err)
coll, err = queries.GetCollectorByClientID(ctx, clientId)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivecollector{
Clientid: clientId,
Mincleanversion: minCleanVersion + 1,
Mintextversion: minTextVersion + 1,
Activeversion: 2,
Latestversion: 2,
Fields: nil,
}, coll)
}
func BenchmarkListCollectorQueries(b *testing.B) {
ctx := b.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(b, cfg)
queries := cfg.GetDBQueries()
clientId := "EXAMPLE"
err := queries.CreateClient(ctx, &repository.CreateClientParams{
Name: "example_client",
Clientid: clientId,
})
require.NoError(b, err)
b.ResetTimer()
for b.Loop() {
_, _ = queries.ListCollectorQueries(ctx, clientId)
}
}
func BenchmarkGetCollectorByClientID(b *testing.B) {
ctx := b.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(b, cfg)
queries := cfg.GetDBQueries()
clientId := "EXAMPLE"
err := queries.CreateClient(ctx, &repository.CreateClientParams{
Name: "example_client",
Clientid: clientId,
})
require.NoError(b, err)
b.ResetTimer()
for b.Loop() {
_, _ = queries.GetCollectorByClientID(ctx, clientId)
}
}
+12 -54
View File
@@ -167,74 +167,32 @@ func (q *Queries) GetDocumentEntry(ctx context.Context, documentid uuid.UUID) (*
}
const getDocumentExternal = `-- name: GetDocumentExternal :one
WITH
docs AS (
SELECT id, hash, clientId
FROM documents
WHERE id = $1
),
namedResults AS (
SELECT
q.name,
dd.id,
d.value
FROM currentCollectorQueries AS q
JOIN docs as dd on dd.clientId = q.clientId
LEFT JOIN listValidDocumentResults($1) AS d
ON d.queryId = q.queryId and q.name is not null
)
SELECT
d.id,
d.clientId,
d.hash,
COALESCE(jsonb_object_agg(r.name, r.value) FILTER (WHERE r.name IS NOT NULL), '{}') AS fields
FROM docs AS d
LEFT JOIN namedResults AS r ON d.id = r.id
GROUP BY d.id, d.clientId, d.hash
id,
clientId,
hash
FROM documents
WHERE id = $1
`
type GetDocumentExternalRow struct {
ID uuid.UUID `db:"id"`
Clientid string `db:"clientid"`
Hash string `db:"hash"`
Fields []byte `db:"fields"`
}
// GetDocumentExternal
// Query functionality has been removed. See remove_query_plan.md for details.
//
// WITH
// docs AS (
// SELECT id, hash, clientId
// FROM documents
// WHERE id = $1
// ),
// namedResults AS (
// SELECT
// q.name,
// dd.id,
// d.value
// FROM currentCollectorQueries AS q
// JOIN docs as dd on dd.clientId = q.clientId
// LEFT JOIN listValidDocumentResults($1) AS d
// ON d.queryId = q.queryId and q.name is not null
// )
// SELECT
// d.id,
// d.clientId,
// d.hash,
// COALESCE(jsonb_object_agg(r.name, r.value) FILTER (WHERE r.name IS NOT NULL), '{}') AS fields
// FROM docs AS d
// LEFT JOIN namedResults AS r ON d.id = r.id
// GROUP BY d.id, d.clientId, d.hash
// id,
// clientId,
// hash
// FROM documents
// WHERE id = $1
func (q *Queries) GetDocumentExternal(ctx context.Context, documentid uuid.UUID) (*GetDocumentExternalRow, error) {
row := q.db.QueryRow(ctx, getDocumentExternal, documentid)
var i GetDocumentExternalRow
err := row.Scan(
&i.ID,
&i.Clientid,
&i.Hash,
&i.Fields,
)
err := row.Scan(&i.ID, &i.Clientid, &i.Hash)
return &i, err
}
@@ -218,7 +218,6 @@ func TestDocument(t *testing.T) {
ID: id,
Clientid: clientId,
Hash: hash,
Fields: []byte("{}"),
}, docext)
})
t.Run("doc id by hash", func(t *testing.T) {
-165
View File
@@ -181,57 +181,6 @@ func (e Cleanmimetype) Valid() bool {
return false
}
type Querytype string
const (
QuerytypeContextFull Querytype = "context_full"
QuerytypeJsonExtractor Querytype = "json_extractor"
)
func (e *Querytype) Scan(src interface{}) error {
switch s := src.(type) {
case []byte:
*e = Querytype(s)
case string:
*e = Querytype(s)
default:
return fmt.Errorf("unsupported scan type for Querytype: %T", src)
}
return nil
}
type NullQuerytype struct {
Querytype Querytype
Valid bool // Valid is true if Querytype is not NULL
}
// Scan implements the Scanner interface.
func (ns *NullQuerytype) Scan(value interface{}) error {
if value == nil {
ns.Querytype, ns.Valid = "", false
return nil
}
ns.Valid = true
return ns.Querytype.Scan(value)
}
// Value implements the driver Valuer interface.
func (ns NullQuerytype) Value() (driver.Value, error) {
if !ns.Valid {
return nil, nil
}
return string(ns.Querytype), nil
}
func (e Querytype) Valid() bool {
switch e {
case QuerytypeContextFull,
QuerytypeJsonExtractor:
return true
}
return false
}
type BatchUpload struct {
ID uuid.UUID `db:"id"`
ClientID string `db:"client_id"`
@@ -293,23 +242,6 @@ type Collectormintextversion struct {
Removedversion *int32 `db:"removedversion"`
}
type Collectorquery struct {
ID uuid.UUID `db:"id"`
Clientid string `db:"clientid"`
Name string `db:"name"`
Queryid uuid.UUID `db:"queryid"`
Addedversion int32 `db:"addedversion"`
Removedversion *int32 `db:"removedversion"`
}
type Collectorquerydependencytree struct {
Clientid string `db:"clientid"`
Queryid *uuid.UUID `db:"queryid"`
Querytype Querytype `db:"querytype"`
Queryversion int32 `db:"queryversion"`
Requiredids []uuid.UUID `db:"requiredids"`
}
type Collectorversion struct {
Clientid string `db:"clientid"`
ID int32 `db:"id"`
@@ -343,17 +275,6 @@ type Currentcollectormintextversion struct {
Mintextversion int64 `db:"mintextversion"`
}
type Currentcollectorqueriesjsonagg struct {
Clientid string `db:"clientid"`
Fields []byte `db:"fields"`
}
type Currentcollectorquery struct {
Clientid string `db:"clientid"`
Name *string `db:"name"`
Queryid *uuid.UUID `db:"queryid"`
}
type Currentfieldextraction struct {
ID uuid.UUID `db:"id"`
Documentid uuid.UUID `db:"documentid"`
@@ -659,16 +580,6 @@ type Fullactivecollector struct {
Mintextversion int64 `db:"mintextversion"`
Activeversion int32 `db:"activeversion"`
Latestversion int32 `db:"latestversion"`
Fields []byte `db:"fields"`
}
type Fullactivequery struct {
Queryid uuid.UUID `db:"queryid"`
Querytype Querytype `db:"querytype"`
Activeversion int32 `db:"activeversion"`
Latestversion int32 `db:"latestversion"`
Config []byte `db:"config"`
Requiredids []uuid.UUID `db:"requiredids"`
}
type Fullclient struct {
@@ -681,79 +592,3 @@ type Label struct {
Label string `db:"label"`
Description string `db:"description"`
}
type Query struct {
Queryid uuid.UUID `db:"queryid"`
Querytype Querytype `db:"querytype"`
}
type Queryactivedependency struct {
ID uuid.UUID `db:"id"`
Requiredqueryid *uuid.UUID `db:"requiredqueryid"`
}
type Queryactiveversion struct {
Activeversionentryid uuid.UUID `db:"activeversionentryid"`
Queryid uuid.UUID `db:"queryid"`
Versionid int32 `db:"versionid"`
}
type Queryconfig struct {
Configid uuid.UUID `db:"configid"`
Queryid uuid.UUID `db:"queryid"`
Config []byte `db:"config"`
Addedversion int32 `db:"addedversion"`
Removedversion *int32 `db:"removedversion"`
}
type Querycurrentactiveversion struct {
Queryid uuid.UUID `db:"queryid"`
Activeversion int32 `db:"activeversion"`
}
type Querycurrentconfig struct {
Queryid uuid.UUID `db:"queryid"`
Config []byte `db:"config"`
}
type Querycurrentrequiredid struct {
Queryid uuid.UUID `db:"queryid"`
Requiredqueryid *uuid.UUID `db:"requiredqueryid"`
}
type Querycurrentrequiredidsagg struct {
Queryid uuid.UUID `db:"queryid"`
Requiredids []uuid.UUID `db:"requiredids"`
}
type Querylatestversion struct {
Queryid uuid.UUID `db:"queryid"`
Latestversion int32 `db:"latestversion"`
}
type Queryversion struct {
Queryid uuid.UUID `db:"queryid"`
Versionid int32 `db:"versionid"`
Addedat pgtype.Timestamp `db:"addedat"`
}
type Requiredquery struct {
Requiredqueryentryid uuid.UUID `db:"requiredqueryentryid"`
Queryid uuid.UUID `db:"queryid"`
Requiredqueryid uuid.UUID `db:"requiredqueryid"`
Addedversion int32 `db:"addedversion"`
Removedversion *int32 `db:"removedversion"`
}
type Result struct {
ID uuid.UUID `db:"id"`
Textentryid uuid.UUID `db:"textentryid"`
Queryid uuid.UUID `db:"queryid"`
Value string `db:"value"`
Queryversion int32 `db:"queryversion"`
}
type Resultdependency struct {
Resultid uuid.UUID `db:"resultid"`
Requiredresultid uuid.UUID `db:"requiredresultid"`
}
-425
View File
@@ -1,425 +0,0 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// source: query.sql
package repository
import (
"context"
"github.com/google/uuid"
)
const addActiveQueryVersion = `-- name: AddActiveQueryVersion :exec
INSERT INTO queryActiveVersions (queryId, versionId) VALUES ($1, $2)
`
type AddActiveQueryVersionParams struct {
Queryid uuid.UUID `db:"queryid"`
Versionid int32 `db:"versionid"`
}
// AddActiveQueryVersion
//
// INSERT INTO queryActiveVersions (queryId, versionId) VALUES ($1, $2)
func (q *Queries) AddActiveQueryVersion(ctx context.Context, arg *AddActiveQueryVersionParams) error {
_, err := q.db.Exec(ctx, addActiveQueryVersion, arg.Queryid, arg.Versionid)
return err
}
const addLatestQueryVersion = `-- name: AddLatestQueryVersion :one
INSERT INTO queryVersions (queryId) VALUES ($1) RETURNING versionId
`
// AddLatestQueryVersion
//
// INSERT INTO queryVersions (queryId) VALUES ($1) RETURNING versionId
func (q *Queries) AddLatestQueryVersion(ctx context.Context, queryid uuid.UUID) (int32, error) {
row := q.db.QueryRow(ctx, addLatestQueryVersion, queryid)
var versionid int32
err := row.Scan(&versionid)
return versionid, err
}
const addRequiredQuery = `-- name: AddRequiredQuery :exec
INSERT INTO requiredQueries (queryId, requiredQueryId, addedVersion) VALUES ($1, $2, $3)
`
type AddRequiredQueryParams struct {
Queryid uuid.UUID `db:"queryid"`
Requiredqueryid uuid.UUID `db:"requiredqueryid"`
Addedversion int32 `db:"addedversion"`
}
// AddRequiredQuery
//
// INSERT INTO requiredQueries (queryId, requiredQueryId, addedVersion) VALUES ($1, $2, $3)
func (q *Queries) AddRequiredQuery(ctx context.Context, arg *AddRequiredQueryParams) error {
_, err := q.db.Exec(ctx, addRequiredQuery, arg.Queryid, arg.Requiredqueryid, arg.Addedversion)
return err
}
const allQueriesExist = `-- name: AllQueriesExist :one
SELECT COUNT(*) = COUNT(DISTINCT queryId) AS all_exist
FROM unnest($1::uuid[]) AS input_id
LEFT JOIN queries ON input_id = queries.queryId
`
// AllQueriesExist
//
// SELECT COUNT(*) = COUNT(DISTINCT queryId) AS all_exist
// FROM unnest($1::uuid[]) AS input_id
// LEFT JOIN queries ON input_id = queries.queryId
func (q *Queries) AllQueriesExist(ctx context.Context, dollar_1 []uuid.UUID) (bool, error) {
row := q.db.QueryRow(ctx, allQueriesExist, dollar_1)
var all_exist bool
err := row.Scan(&all_exist)
return all_exist, err
}
const createQuery = `-- name: CreateQuery :one
INSERT INTO queries (queryType) VALUES ($1) RETURNING queryId
`
// CreateQuery
//
// INSERT INTO queries (queryType) VALUES ($1) RETURNING queryId
func (q *Queries) CreateQuery(ctx context.Context, querytype Querytype) (uuid.UUID, error) {
row := q.db.QueryRow(ctx, createQuery, querytype)
var queryid uuid.UUID
err := row.Scan(&queryid)
return queryid, err
}
const getActiveQueryConfig = `-- name: GetActiveQueryConfig :one
SELECT config FROM queryCurrentConfigs where queryId = $1
`
// GetActiveQueryConfig
//
// SELECT config FROM queryCurrentConfigs where queryId = $1
func (q *Queries) GetActiveQueryConfig(ctx context.Context, queryid uuid.UUID) ([]byte, error) {
row := q.db.QueryRow(ctx, getActiveQueryConfig, queryid)
var config []byte
err := row.Scan(&config)
return config, err
}
const getQuery = `-- name: GetQuery :one
SELECT queryid, querytype, activeversion, latestversion, config, requiredids FROM fullActiveQueries WHERE queryId = $1
`
// GetQuery
//
// SELECT queryid, querytype, activeversion, latestversion, config, requiredids FROM fullActiveQueries WHERE queryId = $1
func (q *Queries) GetQuery(ctx context.Context, queryid uuid.UUID) (*Fullactivequery, error) {
row := q.db.QueryRow(ctx, getQuery, queryid)
var i Fullactivequery
err := row.Scan(
&i.Queryid,
&i.Querytype,
&i.Activeversion,
&i.Latestversion,
&i.Config,
&i.Requiredids,
)
return &i, err
}
const getQueryWithVersion = `-- name: GetQueryWithVersion :one
WITH query as (
SELECT queryId, queryType FROM queries WHERE queryId = $1
),
config as (
SELECT c.queryId, c.config
FROM query AS q
LEFT JOIN queryConfigs AS c ON q.queryId = c.queryId
and isInVersion($2, c.addedVersion, c.removedVersion)
),
requiredIds as (
SELECT r.queryId,
coalesce(
ARRAY_AGG(DISTINCT r.requiredQueryId)
FILTER (WHERE r.requiredQueryId != '00000000-0000-0000-0000-000000000000')::uuid[],
array[]::uuid[]
)::uuid[] as requiredIds
FROM query AS q
LEFT JOIN requiredQueries AS r ON q.queryId = r.queryId
and isInVersion($2, r.addedVersion, r.removedVersion)
GROUP BY r.queryId
)
SELECT DISTINCT q.queryId, q.queryType,
av.activeVersion,
lv.latestVersion, c.config,
r.requiredIds
FROM query AS q
JOIN queryCurrentActiveVersions as av on q.queryId = av.queryId
JOIN queryLatestVersions as lv on lv.queryId = q.queryId
LEFT JOIN config AS c ON q.queryId = c.queryId
LEFT JOIN requiredIds AS r ON q.queryId = r.queryId
`
type GetQueryWithVersionParams struct {
ID *uuid.UUID `db:"id"`
Version *int32 `db:"version"`
}
type GetQueryWithVersionRow struct {
Queryid uuid.UUID `db:"queryid"`
Querytype Querytype `db:"querytype"`
Activeversion int32 `db:"activeversion"`
Latestversion int32 `db:"latestversion"`
Config []byte `db:"config"`
Requiredids []uuid.UUID `db:"requiredids"`
}
// GetQueryWithVersion
//
// WITH query as (
// SELECT queryId, queryType FROM queries WHERE queryId = $1
// ),
// config as (
// SELECT c.queryId, c.config
// FROM query AS q
// LEFT JOIN queryConfigs AS c ON q.queryId = c.queryId
// and isInVersion($2, c.addedVersion, c.removedVersion)
// ),
// requiredIds as (
// SELECT r.queryId,
// coalesce(
// ARRAY_AGG(DISTINCT r.requiredQueryId)
// FILTER (WHERE r.requiredQueryId != '00000000-0000-0000-0000-000000000000')::uuid[],
// array[]::uuid[]
// )::uuid[] as requiredIds
// FROM query AS q
// LEFT JOIN requiredQueries AS r ON q.queryId = r.queryId
// and isInVersion($2, r.addedVersion, r.removedVersion)
// GROUP BY r.queryId
// )
// SELECT DISTINCT q.queryId, q.queryType,
// av.activeVersion,
// lv.latestVersion, c.config,
// r.requiredIds
// FROM query AS q
// JOIN queryCurrentActiveVersions as av on q.queryId = av.queryId
// JOIN queryLatestVersions as lv on lv.queryId = q.queryId
// LEFT JOIN config AS c ON q.queryId = c.queryId
// LEFT JOIN requiredIds AS r ON q.queryId = r.queryId
func (q *Queries) GetQueryWithVersion(ctx context.Context, arg *GetQueryWithVersionParams) (*GetQueryWithVersionRow, error) {
row := q.db.QueryRow(ctx, getQueryWithVersion, arg.ID, arg.Version)
var i GetQueryWithVersionRow
err := row.Scan(
&i.Queryid,
&i.Querytype,
&i.Activeversion,
&i.Latestversion,
&i.Config,
&i.Requiredids,
)
return &i, err
}
const isQueryInDependencyTree = `-- name: IsQueryInDependencyTree :one
SELECT EXISTS (
SELECT 1 FROM queryActiveDependencies
WHERE id = any($1)
and requiredQueryId = $2
or $2 = any($1)
)
`
type IsQueryInDependencyTreeParams struct {
Requiredqueryids []uuid.UUID `db:"requiredqueryids"`
Queryid *uuid.UUID `db:"queryid"`
}
// IsQueryInDependencyTree
//
// SELECT EXISTS (
// SELECT 1 FROM queryActiveDependencies
// WHERE id = any($1)
// and requiredQueryId = $2
// or $2 = any($1)
// )
func (q *Queries) IsQueryInDependencyTree(ctx context.Context, arg *IsQueryInDependencyTreeParams) (bool, error) {
row := q.db.QueryRow(ctx, isQueryInDependencyTree, arg.Requiredqueryids, arg.Queryid)
var exists bool
err := row.Scan(&exists)
return exists, err
}
const listQueries = `-- name: ListQueries :many
SELECT queryid, querytype, activeversion, latestversion, config, requiredids FROM fullActiveQueries
`
// ListQueries
//
// SELECT queryid, querytype, activeversion, latestversion, config, requiredids FROM fullActiveQueries
func (q *Queries) ListQueries(ctx context.Context) ([]*Fullactivequery, error) {
rows, err := q.db.Query(ctx, listQueries)
if err != nil {
return nil, err
}
defer rows.Close()
items := []*Fullactivequery{}
for rows.Next() {
var i Fullactivequery
if err := rows.Scan(
&i.Queryid,
&i.Querytype,
&i.Activeversion,
&i.Latestversion,
&i.Config,
&i.Requiredids,
); err != nil {
return nil, err
}
items = append(items, &i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listQueriesById = `-- name: ListQueriesById :many
SELECT queryid, querytype, activeversion, latestversion, config, requiredids FROM fullActiveQueries WHERE queryId = any($1)
`
// ListQueriesById
//
// SELECT queryid, querytype, activeversion, latestversion, config, requiredids FROM fullActiveQueries WHERE queryId = any($1)
func (q *Queries) ListQueriesById(ctx context.Context, queryid []uuid.UUID) ([]*Fullactivequery, error) {
rows, err := q.db.Query(ctx, listQueriesById, queryid)
if err != nil {
return nil, err
}
defer rows.Close()
items := []*Fullactivequery{}
for rows.Next() {
var i Fullactivequery
if err := rows.Scan(
&i.Queryid,
&i.Querytype,
&i.Activeversion,
&i.Latestversion,
&i.Config,
&i.Requiredids,
); err != nil {
return nil, err
}
items = append(items, &i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listQueryClientIDs = `-- name: ListQueryClientIDs :many
SELECT clientId FROM collectorQueryDependencyTree WHERE queryId = $1
`
// ListQueryClientIDs
//
// SELECT clientId FROM collectorQueryDependencyTree WHERE queryId = $1
func (q *Queries) ListQueryClientIDs(ctx context.Context, queryid *uuid.UUID) ([]string, error) {
rows, err := q.db.Query(ctx, listQueryClientIDs, queryid)
if err != nil {
return nil, err
}
defer rows.Close()
items := []string{}
for rows.Next() {
var clientid string
if err := rows.Scan(&clientid); err != nil {
return nil, err
}
items = append(items, clientid)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listQueryDirectDependentsByDocumentID = `-- name: ListQueryDirectDependentsByDocumentID :many
WITH doc AS (
SELECT clientId FROM documents WHERE id = $2
)
SELECT dt.queryId
FROM doc,
LATERAL collectorQueryDependencyTreeByClient(doc.clientId) AS dt
WHERE $1 = ANY(dt.requiredIds)
`
type ListQueryDirectDependentsByDocumentIDParams struct {
Queryid *uuid.UUID `db:"queryid"`
Documentid *uuid.UUID `db:"documentid"`
}
// ListQueryDirectDependentsByDocumentID
//
// WITH doc AS (
// SELECT clientId FROM documents WHERE id = $2
// )
// SELECT dt.queryId
// FROM doc,
// LATERAL collectorQueryDependencyTreeByClient(doc.clientId) AS dt
// WHERE $1 = ANY(dt.requiredIds)
func (q *Queries) ListQueryDirectDependentsByDocumentID(ctx context.Context, arg *ListQueryDirectDependentsByDocumentIDParams) ([]*uuid.UUID, error) {
rows, err := q.db.Query(ctx, listQueryDirectDependentsByDocumentID, arg.Queryid, arg.Documentid)
if err != nil {
return nil, err
}
defer rows.Close()
items := []*uuid.UUID{}
for rows.Next() {
var queryid *uuid.UUID
if err := rows.Scan(&queryid); err != nil {
return nil, err
}
items = append(items, queryid)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const removeRequiredQuery = `-- name: RemoveRequiredQuery :exec
UPDATE requiredQueries SET removedVersion = $1 WHERE requiredQueryId = $2 and queryId = $3 and removedVersion is null
`
type RemoveRequiredQueryParams struct {
Removedversion *int32 `db:"removedversion"`
Requiredqueryid uuid.UUID `db:"requiredqueryid"`
Queryid uuid.UUID `db:"queryid"`
}
// RemoveRequiredQuery
//
// UPDATE requiredQueries SET removedVersion = $1 WHERE requiredQueryId = $2 and queryId = $3 and removedVersion is null
func (q *Queries) RemoveRequiredQuery(ctx context.Context, arg *RemoveRequiredQueryParams) error {
_, err := q.db.Exec(ctx, removeRequiredQuery, arg.Removedversion, arg.Requiredqueryid, arg.Queryid)
return err
}
const setQueryConfig = `-- name: SetQueryConfig :exec
INSERT INTO queryConfigs (queryId, config, addedVersion) VALUES ($1, $2, $3)
`
type SetQueryConfigParams struct {
Queryid uuid.UUID `db:"queryid"`
Config []byte `db:"config"`
Addedversion int32 `db:"addedversion"`
}
// SetQueryConfig
//
// INSERT INTO queryConfigs (queryId, config, addedVersion) VALUES ($1, $2, $3)
func (q *Queries) SetQueryConfig(ctx context.Context, arg *SetQueryConfigParams) error {
_, err := q.db.Exec(ctx, setQueryConfig, arg.Queryid, arg.Config, arg.Addedversion)
return err
}
-622
View File
@@ -1,622 +0,0 @@
package repository_test
import (
"testing"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/serviceconfig"
"queryorchestration/internal/test"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestQueries(t *testing.T) {
t.Parallel()
if testing.Short() {
t.SkipNow()
}
ctx := t.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(t, cfg)
queries := cfg.GetDBQueries()
contextQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull))
require.NoError(t, err)
contextQuery, err := queries.GetQuery(ctx, contextQueryID)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivequery{
Queryid: contextQueryID,
Querytype: repository.QuerytypeContextFull,
Activeversion: 0,
Latestversion: 0,
Config: nil,
Requiredids: []uuid.UUID{},
}, contextQuery)
ctxVersion, err := queries.AddLatestQueryVersion(ctx, contextQueryID)
require.NoError(t, err)
assert.Equal(t, int32(1), ctxVersion)
contextQuery, err = queries.GetQuery(ctx, contextQueryID)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivequery{
Queryid: contextQueryID,
Querytype: repository.QuerytypeContextFull,
Activeversion: 0,
Latestversion: 1,
Config: nil,
Requiredids: []uuid.UUID{},
}, contextQuery)
jsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor))
require.NoError(t, err)
jsonQuery, err := queries.GetQuery(ctx, jsonQueryID)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivequery{
Queryid: jsonQueryID,
Querytype: repository.QuerytypeJsonExtractor,
Activeversion: 0,
Latestversion: 0,
Config: nil,
Requiredids: []uuid.UUID{},
}, jsonQuery)
jsonVersion, err := queries.AddLatestQueryVersion(ctx, jsonQueryID)
require.NoError(t, err)
assert.Equal(t, int32(1), jsonVersion)
jsonQuery, err = queries.GetQuery(ctx, jsonQueryID)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivequery{
Queryid: jsonQueryID,
Querytype: repository.QuerytypeJsonExtractor,
Activeversion: 0,
Latestversion: 1,
Config: nil,
Requiredids: []uuid.UUID{},
}, jsonQuery)
err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{
Versionid: 1,
Queryid: jsonQueryID,
})
require.NoError(t, err)
jsonQuery, err = queries.GetQuery(ctx, jsonQueryID)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivequery{
Queryid: jsonQueryID,
Querytype: repository.QuerytypeJsonExtractor,
Activeversion: 1,
Latestversion: 1,
Config: nil,
Requiredids: []uuid.UUID{},
}, jsonQuery)
jsonConfig := []byte("{\"path\": \"example_path\"}")
err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{
Queryid: jsonQueryID,
Requiredqueryid: contextQueryID,
Addedversion: 1,
})
require.NoError(t, err)
jsonQuery, err = queries.GetQuery(ctx, jsonQueryID)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivequery{
Queryid: jsonQueryID,
Querytype: repository.QuerytypeJsonExtractor,
Activeversion: 1,
Latestversion: 1,
Config: nil,
Requiredids: []uuid.UUID{contextQueryID},
}, jsonQuery)
jsonVersion, err = queries.AddLatestQueryVersion(ctx, jsonQueryID)
require.NoError(t, err)
assert.Equal(t, int32(2), jsonVersion)
jsonQuery, err = queries.GetQuery(ctx, jsonQueryID)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivequery{
Queryid: jsonQueryID,
Querytype: repository.QuerytypeJsonExtractor,
Activeversion: 1,
Latestversion: 2,
Config: nil,
Requiredids: []uuid.UUID{contextQueryID},
}, jsonQuery)
removeV := int32(2)
err = queries.RemoveRequiredQuery(ctx, &repository.RemoveRequiredQueryParams{
Queryid: jsonQueryID,
Requiredqueryid: contextQueryID,
Removedversion: &removeV,
})
require.NoError(t, err)
err = queries.SetQueryConfig(ctx, &repository.SetQueryConfigParams{
Queryid: jsonQueryID,
Config: jsonConfig,
Addedversion: 1,
})
require.NoError(t, err)
jsonQueryConfig, err := queries.GetActiveQueryConfig(ctx, jsonQueryID)
require.NoError(t, err)
assert.Equal(t, jsonConfig, jsonQueryConfig)
err = queries.SetQueryConfig(ctx, &repository.SetQueryConfigParams{
Queryid: jsonQueryID,
Config: []byte(`{"second":"key"}`),
Addedversion: 2,
})
require.NoError(t, err)
jsonQueryConfig, err = queries.GetActiveQueryConfig(ctx, jsonQueryID)
require.NoError(t, err)
assert.Equal(t, jsonConfig, jsonQueryConfig)
err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{
Queryid: jsonQueryID,
Versionid: 2,
})
require.NoError(t, err)
jsonQueryConfig, err = queries.GetActiveQueryConfig(ctx, jsonQueryID)
require.NoError(t, err)
assert.Equal(t, []byte(`{"second": "key"}`), jsonQueryConfig)
jsonQuery, err = queries.GetQuery(ctx, jsonQueryID)
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.Fullactivequery{
Queryid: jsonQueryID,
Querytype: repository.QuerytypeJsonExtractor,
Activeversion: 2,
Latestversion: 2,
Config: jsonQueryConfig,
Requiredids: []uuid.UUID{},
}, jsonQuery)
v := int32(1)
versionedQuery, err := queries.GetQueryWithVersion(ctx, &repository.GetQueryWithVersionParams{
ID: &jsonQueryID,
Version: &v,
})
require.NoError(t, err)
assert.EqualExportedValues(t, &repository.GetQueryWithVersionRow{
Queryid: jsonQueryID,
Querytype: repository.QuerytypeJsonExtractor,
Activeversion: 2,
Latestversion: 2,
Config: jsonConfig,
Requiredids: []uuid.UUID{contextQueryID},
}, versionedQuery)
all_exist, err := queries.AllQueriesExist(ctx, []uuid.UUID{})
require.NoError(t, err)
assert.True(t, all_exist)
all_exist, err = queries.AllQueriesExist(ctx, []uuid.UUID{uuid.New()})
require.NoError(t, err)
assert.False(t, all_exist)
all_exist, err = queries.AllQueriesExist(ctx, []uuid.UUID{jsonQueryID})
require.NoError(t, err)
assert.True(t, all_exist)
all_exist, err = queries.AllQueriesExist(ctx, []uuid.UUID{jsonQueryID, contextQueryID})
require.NoError(t, err)
assert.True(t, all_exist)
all_exist, err = queries.AllQueriesExist(ctx, []uuid.UUID{jsonQueryID, uuid.New()})
require.NoError(t, err)
assert.False(t, all_exist)
}
func TestQueryDependencyTree(t *testing.T) {
t.Parallel()
if testing.Short() {
t.SkipNow()
}
ctx := t.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(t, cfg)
queries := cfg.GetDBQueries()
clientID := "EXAMPLE"
err := queries.CreateClient(ctx, &repository.CreateClientParams{
Name: "example_client",
Clientid: clientID,
})
require.NoError(t, err)
version, err := queries.AddLatestCollectorVersion(ctx, clientID)
require.NoError(t, err)
err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{
Clientid: clientID,
Versionid: version,
})
require.NoError(t, err)
docID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{
Clientid: clientID,
Hash: "sample",
BatchID: nil,
})
require.NoError(t, err)
contextQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull))
require.NoError(t, err)
_, err = queries.AddLatestQueryVersion(ctx, contextQueryID)
require.NoError(t, err)
err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{
Queryid: contextQueryID,
Versionid: 1,
})
require.NoError(t, err)
dependents, err := queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &contextQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []uuid.UUID{}, dependents)
jsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor))
require.NoError(t, err)
_, err = queries.AddLatestQueryVersion(ctx, jsonQueryID)
require.NoError(t, err)
err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{
Queryid: jsonQueryID,
Versionid: 1,
})
require.NoError(t, err)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &jsonQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []uuid.UUID{}, dependents)
err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{
Queryid: jsonQueryID,
Requiredqueryid: contextQueryID,
Addedversion: 1,
})
require.NoError(t, err)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &jsonQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []uuid.UUID{}, dependents)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &contextQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []uuid.UUID{}, dependents)
err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{
Clientid: clientID,
Name: "example_name'",
Queryid: jsonQueryID,
Addedversion: 1,
})
require.NoError(t, err)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &jsonQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []*uuid.UUID{}, dependents)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &contextQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []*uuid.UUID{&jsonQueryID}, dependents)
secondJsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor))
require.NoError(t, err)
_, err = queries.AddLatestQueryVersion(ctx, secondJsonQueryID)
require.NoError(t, err)
err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{
Queryid: secondJsonQueryID,
Versionid: 1,
})
require.NoError(t, err)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &jsonQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []*uuid.UUID{}, dependents)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &contextQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []*uuid.UUID{&jsonQueryID}, dependents)
err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{
Queryid: secondJsonQueryID,
Requiredqueryid: jsonQueryID,
Addedversion: 1,
})
require.NoError(t, err)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &secondJsonQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []*uuid.UUID{}, dependents)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &jsonQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []*uuid.UUID{}, dependents)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &contextQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []*uuid.UUID{&jsonQueryID}, dependents)
err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{
Clientid: clientID,
Name: "example_name'",
Queryid: secondJsonQueryID,
Addedversion: 1,
})
require.NoError(t, err)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &secondJsonQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []*uuid.UUID{}, dependents)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &jsonQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []*uuid.UUID{&secondJsonQueryID}, dependents)
dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &contextQueryID,
})
require.NoError(t, err)
assert.ElementsMatch(t, []*uuid.UUID{&jsonQueryID}, dependents)
isdependent, err := queries.IsQueryInDependencyTree(ctx, &repository.IsQueryInDependencyTreeParams{
Queryid: &jsonQueryID,
Requiredqueryids: []uuid.UUID{contextQueryID},
})
require.NoError(t, err)
assert.False(t, isdependent)
isdependent, err = queries.IsQueryInDependencyTree(ctx, &repository.IsQueryInDependencyTreeParams{
Queryid: &jsonQueryID,
Requiredqueryids: []uuid.UUID{secondJsonQueryID},
})
require.NoError(t, err)
assert.True(t, isdependent)
isdependent, err = queries.IsQueryInDependencyTree(ctx, &repository.IsQueryInDependencyTreeParams{
Queryid: &jsonQueryID,
Requiredqueryids: []uuid.UUID{jsonQueryID},
})
require.NoError(t, err)
assert.True(t, isdependent)
isdependent, err = queries.IsQueryInDependencyTree(ctx, &repository.IsQueryInDependencyTreeParams{
Queryid: &secondJsonQueryID,
Requiredqueryids: []uuid.UUID{jsonQueryID, contextQueryID},
})
require.NoError(t, err)
assert.False(t, isdependent)
isdependent, err = queries.IsQueryInDependencyTree(ctx, &repository.IsQueryInDependencyTreeParams{
Queryid: &contextQueryID,
Requiredqueryids: []uuid.UUID{jsonQueryID, secondJsonQueryID},
})
require.NoError(t, err)
assert.True(t, isdependent)
}
func TestQueriesList(t *testing.T) {
t.Parallel()
if testing.Short() {
t.SkipNow()
}
ctx := t.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(t, cfg)
queries := cfg.GetDBQueries()
contextQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull))
require.NoError(t, err)
jsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor))
require.NoError(t, err)
qs, err := queries.ListQueries(ctx)
require.NoError(t, err)
assert.Len(t, qs, 2)
assert.ElementsMatch(t, []*repository.Fullactivequery{
{
Queryid: jsonQueryID,
Querytype: repository.QuerytypeJsonExtractor,
Activeversion: 0,
Latestversion: 0,
Config: nil,
Requiredids: []uuid.UUID{},
},
{
Queryid: contextQueryID,
Querytype: repository.QuerytypeContextFull,
Activeversion: 0,
Latestversion: 0,
Config: nil,
Requiredids: []uuid.UUID{},
},
}, qs)
qs, err = queries.ListQueriesById(ctx, []uuid.UUID{jsonQueryID})
require.NoError(t, err)
assert.Len(t, qs, 1)
assert.ElementsMatch(t, []*repository.Fullactivequery{
{
Queryid: jsonQueryID,
Querytype: repository.QuerytypeJsonExtractor,
Activeversion: 0,
Latestversion: 0,
Config: nil,
Requiredids: []uuid.UUID{},
},
}, qs)
}
func TestListQueryClients(t *testing.T) {
t.Parallel()
if testing.Short() {
t.SkipNow()
}
ctx := t.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(t, cfg)
queries := cfg.GetDBQueries()
contextID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull))
require.NoError(t, err)
clients, err := queries.ListQueryClientIDs(ctx, &contextID)
require.NoError(t, err)
assert.ElementsMatch(t, []uuid.UUID{}, clients)
clientOneID := "EXAMPLE"
err = queries.CreateClient(ctx, &repository.CreateClientParams{
Name: "example_client",
Clientid: clientOneID,
})
require.NoError(t, err)
versionOne, err := queries.AddLatestCollectorVersion(ctx, clientOneID)
require.NoError(t, err)
err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{
Clientid: clientOneID,
Versionid: versionOne,
})
require.NoError(t, err)
err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{
Clientid: clientOneID,
Queryid: contextID,
Addedversion: 1,
Name: "example_key",
})
require.NoError(t, err)
clients, err = queries.ListQueryClientIDs(ctx, &contextID)
require.NoError(t, err)
assert.ElementsMatch(t, []string{clientOneID}, clients)
clientTwoID := "EXAMPLE_DOS"
err = queries.CreateClient(ctx, &repository.CreateClientParams{
Name: "example_client_dos",
Clientid: clientTwoID,
})
require.NoError(t, err)
versionTwo, err := queries.AddLatestCollectorVersion(ctx, clientTwoID)
require.NoError(t, err)
err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{
Clientid: clientTwoID,
Versionid: versionTwo,
})
require.NoError(t, err)
err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{
Clientid: clientTwoID,
Queryid: contextID,
Addedversion: 1,
Name: "example_key",
})
require.NoError(t, err)
clients, err = queries.ListQueryClientIDs(ctx, &contextID)
require.NoError(t, err)
assert.ElementsMatch(t, []string{clientOneID, clientTwoID}, clients)
jsonID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor))
require.NoError(t, err)
_, err = queries.AddLatestQueryVersion(ctx, jsonID)
require.NoError(t, err)
err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{
Queryid: jsonID,
Requiredqueryid: contextID,
Addedversion: 1,
})
require.NoError(t, err)
err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{
Clientid: clientOneID,
Queryid: jsonID,
Addedversion: 1,
Name: "example_key",
})
require.NoError(t, err)
clients, err = queries.ListQueryClientIDs(ctx, &jsonID)
require.NoError(t, err)
assert.ElementsMatch(t, []string{clientOneID}, clients)
}
func BenchmarkListQueryDirectDependentsByDocId(b *testing.B) {
ctx := b.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(b, cfg)
queries := cfg.GetDBQueries()
clientID := "EXAMPLE"
err := queries.CreateClient(ctx, &repository.CreateClientParams{
Name: "example_client",
Clientid: clientID,
})
require.NoError(b, err)
docID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{
Clientid: clientID,
Hash: "sample",
BatchID: nil,
})
require.NoError(b, err)
contextQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull))
require.NoError(b, err)
b.ResetTimer()
for b.Loop() {
_, _ = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{
Documentid: &docID,
Queryid: &contextQueryID,
})
}
}
@@ -1,43 +0,0 @@
package repository_test
import (
"fmt"
"testing"
"queryorchestration/internal/database/repository"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestQueryTypeScan(t *testing.T) {
qType := repository.Querytype(fmt.Sprint(0))
stringType := "context_full"
err := qType.Scan(stringType)
require.NoError(t, err)
}
func TestNullQueryTypeScan(t *testing.T) {
qType := repository.NullQuerytype{}
stringType := "context_full"
err := qType.Scan(stringType)
require.NoError(t, err)
}
func TestNullQueryTypeValue(t *testing.T) {
qType := repository.NullQuerytype{}
stringType := "context_full"
err := qType.Scan(stringType)
require.NoError(t, err)
val, err := qType.Value()
require.NoError(t, err)
assert.Equal(t, stringType, val)
}
func TestQueryTypeValid(t *testing.T) {
assert.True(t, repository.QuerytypeContextFull.Valid())
}
-308
View File
@@ -1,308 +0,0 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// source: result.sql
package repository
import (
"context"
"github.com/google/uuid"
)
const addResult = `-- name: AddResult :one
INSERT INTO results (queryId, value, textEntryId, queryVersion) VALUES ($1, $2, $3, $4) returning id
`
type AddResultParams struct {
Queryid uuid.UUID `db:"queryid"`
Value string `db:"value"`
Textentryid uuid.UUID `db:"textentryid"`
Queryversion int32 `db:"queryversion"`
}
// AddResult
//
// INSERT INTO results (queryId, value, textEntryId, queryVersion) VALUES ($1, $2, $3, $4) returning id
func (q *Queries) AddResult(ctx context.Context, arg *AddResultParams) (uuid.UUID, error) {
row := q.db.QueryRow(ctx, addResult,
arg.Queryid,
arg.Value,
arg.Textentryid,
arg.Queryversion,
)
var id uuid.UUID
err := row.Scan(&id)
return id, err
}
const addResultDependency = `-- name: AddResultDependency :exec
INSERT INTO resultDependencies (resultId, requiredResultId) VALUES ($1, $2)
`
type AddResultDependencyParams struct {
Resultid uuid.UUID `db:"resultid"`
Requiredresultid uuid.UUID `db:"requiredresultid"`
}
// AddResultDependency
//
// INSERT INTO resultDependencies (resultId, requiredResultId) VALUES ($1, $2)
func (q *Queries) AddResultDependency(ctx context.Context, arg *AddResultDependencyParams) error {
_, err := q.db.Exec(ctx, addResultDependency, arg.Resultid, arg.Requiredresultid)
return err
}
const getResultValueWithVersion = `-- name: GetResultValueWithVersion :one
WITH doc as (
SELECT id, clientId
FROM documents
WHERE id = $3
)
SELECT r.id, r.value
FROM doc as d
JOIN currentTextEntries as cte on cte.documentId = d.id
LEFT JOIN results as r
on r.queryId = $1
and r.queryVersion = $2
and r.textEntryId = cte.id
`
type GetResultValueWithVersionParams struct {
Queryid *uuid.UUID `db:"queryid"`
Queryversion *int32 `db:"queryversion"`
Documentid *uuid.UUID `db:"documentid"`
}
type GetResultValueWithVersionRow struct {
ID *uuid.UUID `db:"id"`
Value *string `db:"value"`
}
// GetResultValueWithVersion
//
// WITH doc as (
// SELECT id, clientId
// FROM documents
// WHERE id = $3
// )
// SELECT r.id, r.value
// FROM doc as d
// JOIN currentTextEntries as cte on cte.documentId = d.id
// LEFT JOIN results as r
// on r.queryId = $1
// and r.queryVersion = $2
// and r.textEntryId = cte.id
func (q *Queries) GetResultValueWithVersion(ctx context.Context, arg *GetResultValueWithVersionParams) (*GetResultValueWithVersionRow, error) {
row := q.db.QueryRow(ctx, getResultValueWithVersion, arg.Queryid, arg.Queryversion, arg.Documentid)
var i GetResultValueWithVersionRow
err := row.Scan(&i.ID, &i.Value)
return &i, err
}
const listQueryRequirementValues = `-- name: ListQueryRequirementValues :many
WITH reqQueries as (
SELECT av.queryId, av.activeVersion, q.queryType
FROM requiredQueries as rq
JOIN queryCurrentActiveVersions as av on av.queryId = rq.requiredQueryId
JOIN queries as q on q.queryId = av.queryId
WHERE rq.queryId = $1
and isInVersion($2, rq.addedVersion, rq.removedVersion)
),
docs as (
SELECT id, clientId
FROM documents
WHERE id = $3
),
codeVersions as (
SELECT
d.id as documentId,
mcv.minCleanVersion,
mtv.minTextVersion
FROM docs as d
JOIN currentCollectorMinTextVersions as mtv on mtv.clientId = d.clientId
JOIN currentCollectorMinCleanVersions as mcv on mcv.clientId = d.clientId
),
latestVersions AS (
SELECT
r.id,
rq.queryId,
rq.queryType,
r.queryVersion,
r.textEntryId,
r.value,
ROW_NUMBER() OVER (
PARTITION BY r.queryId
ORDER BY r.id DESC
) as rowNumber
FROM reqQueries as rq
JOIN currentTextEntries as cte on cte.documentId = $3
LEFT JOIN results as r ON rq.queryId = r.queryId
and r.queryVersion = rq.activeVersion
and cte.id = r.textEntryId
)
SELECT DISTINCT id, queryId, queryType, value
FROM latestVersions
WHERE rowNumber = 1
`
type ListQueryRequirementValuesParams struct {
Queryid *uuid.UUID `db:"queryid"`
Version *int32 `db:"version"`
Documentid *uuid.UUID `db:"documentid"`
}
type ListQueryRequirementValuesRow struct {
ID *uuid.UUID `db:"id"`
Queryid uuid.UUID `db:"queryid"`
Querytype Querytype `db:"querytype"`
Value *string `db:"value"`
}
// ListQueryRequirementValues
//
// WITH reqQueries as (
// SELECT av.queryId, av.activeVersion, q.queryType
// FROM requiredQueries as rq
// JOIN queryCurrentActiveVersions as av on av.queryId = rq.requiredQueryId
// JOIN queries as q on q.queryId = av.queryId
// WHERE rq.queryId = $1
// and isInVersion($2, rq.addedVersion, rq.removedVersion)
// ),
// docs as (
// SELECT id, clientId
// FROM documents
// WHERE id = $3
// ),
// codeVersions as (
// SELECT
// d.id as documentId,
// mcv.minCleanVersion,
// mtv.minTextVersion
// FROM docs as d
// JOIN currentCollectorMinTextVersions as mtv on mtv.clientId = d.clientId
// JOIN currentCollectorMinCleanVersions as mcv on mcv.clientId = d.clientId
// ),
// latestVersions AS (
// SELECT
// r.id,
// rq.queryId,
// rq.queryType,
// r.queryVersion,
// r.textEntryId,
// r.value,
// ROW_NUMBER() OVER (
// PARTITION BY r.queryId
// ORDER BY r.id DESC
// ) as rowNumber
// FROM reqQueries as rq
// JOIN currentTextEntries as cte on cte.documentId = $3
// LEFT JOIN results as r ON rq.queryId = r.queryId
// and r.queryVersion = rq.activeVersion
// and cte.id = r.textEntryId
// )
// SELECT DISTINCT id, queryId, queryType, value
// FROM latestVersions
// WHERE rowNumber = 1
func (q *Queries) ListQueryRequirementValues(ctx context.Context, arg *ListQueryRequirementValuesParams) ([]*ListQueryRequirementValuesRow, error) {
rows, err := q.db.Query(ctx, listQueryRequirementValues, arg.Queryid, arg.Version, arg.Documentid)
if err != nil {
return nil, err
}
defer rows.Close()
items := []*ListQueryRequirementValuesRow{}
for rows.Next() {
var i ListQueryRequirementValuesRow
if err := rows.Scan(
&i.ID,
&i.Queryid,
&i.Querytype,
&i.Value,
); err != nil {
return nil, err
}
items = append(items, &i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listUnsyncedNoDepsQueriesByDocId = `-- name: ListUnsyncedNoDepsQueriesByDocId :many
WITH docs as (
SELECT id, clientId from documents where id = $1
),
dependency_tree as (
select q.queryId, q.requiredIds, q.clientId, q.queryVersion
from docs,
LATERAL collectorQueryDependencyTreeByClient(docs.clientId) AS q
),
text_entries as (
select id, documentId from currentTextEntries where documentId = $1
),
unsyncedQueries AS (
SELECT DISTINCT dt.queryId, dt.requiredIds
from docs as d
JOIN dependency_tree as dt on d.clientId = dt.clientId
JOIN text_entries as cte on cte.documentId = d.id
LEFT JOIN results as r
on r.queryId = dt.queryId
and r.queryVersion = dt.queryVersion
and cte.id = r.textEntryId
where r.value is null
)
SELECT DISTINCT queryId FROM unsyncedQueries as baseuq
WHERE NOT EXISTS (
SELECT 1 FROM unsyncedQueries as uq WHERE uq.queryId = any(baseuq.requiredIds)
)
`
// ListUnsyncedNoDepsQueriesByDocId
//
// WITH docs as (
// SELECT id, clientId from documents where id = $1
// ),
// dependency_tree as (
// select q.queryId, q.requiredIds, q.clientId, q.queryVersion
// from docs,
// LATERAL collectorQueryDependencyTreeByClient(docs.clientId) AS q
// ),
// text_entries as (
// select id, documentId from currentTextEntries where documentId = $1
// ),
// unsyncedQueries AS (
// SELECT DISTINCT dt.queryId, dt.requiredIds
// from docs as d
// JOIN dependency_tree as dt on d.clientId = dt.clientId
// JOIN text_entries as cte on cte.documentId = d.id
// LEFT JOIN results as r
// on r.queryId = dt.queryId
// and r.queryVersion = dt.queryVersion
// and cte.id = r.textEntryId
// where r.value is null
// )
// SELECT DISTINCT queryId FROM unsyncedQueries as baseuq
// WHERE NOT EXISTS (
// SELECT 1 FROM unsyncedQueries as uq WHERE uq.queryId = any(baseuq.requiredIds)
// )
func (q *Queries) ListUnsyncedNoDepsQueriesByDocId(ctx context.Context, dollar_1 *uuid.UUID) ([]*uuid.UUID, error) {
rows, err := q.db.Query(ctx, listUnsyncedNoDepsQueriesByDocId, dollar_1)
if err != nil {
return nil, err
}
defer rows.Close()
items := []*uuid.UUID{}
for rows.Next() {
var queryid *uuid.UUID
if err := rows.Scan(&queryid); err != nil {
return nil, err
}
items = append(items, queryid)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
-533
View File
@@ -1,533 +0,0 @@
package repository_test
import (
"testing"
"time"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/serviceconfig"
"queryorchestration/internal/test"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestResults(t *testing.T) {
t.Parallel()
if testing.Short() {
t.SkipNow()
}
ctx := t.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(t, cfg)
queries := cfg.GetDBQueries()
queryId := createQuery(t, queries, repository.QuerytypeContextFull)
clientId := createClientWithCollector(t, queries)
documentID, _, _ := createDocumentWithCollectorAndResult(t, queries, clientId, queryId)
qv := int32(1)
res, err := queries.GetResultValueWithVersion(ctx, &repository.GetResultValueWithVersionParams{
Queryid: &queryId,
Queryversion: &qv,
Documentid: &documentID,
})
require.NoError(t, err)
assert.NotNil(t, res.Value)
assert.Equal(t, "json_value", *res.Value)
}
func TestResultValues(t *testing.T) {
t.Parallel()
if testing.Short() {
t.SkipNow()
}
ctx := t.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(t, cfg)
queries := cfg.GetDBQueries()
jsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor))
require.NoError(t, err)
clientId := "EXAMPLE"
err = queries.CreateClient(ctx, &repository.CreateClientParams{
Name: "example_client",
Clientid: clientId,
})
require.NoError(t, err)
documentID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{
Clientid: clientId,
Hash: "example_hash",
BatchID: nil,
})
require.NoError(t, err)
documentTwoID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{
Clientid: clientId,
Hash: "example_hash_two",
BatchID: nil,
})
require.NoError(t, err)
contextQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull))
require.NoError(t, err)
_, err = queries.AddLatestQueryVersion(ctx, jsonQueryID)
require.NoError(t, err)
err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{
Queryid: jsonQueryID,
Versionid: 1,
})
require.NoError(t, err)
_, err = queries.AddLatestQueryVersion(ctx, contextQueryID)
require.NoError(t, err)
_, err = queries.AddLatestQueryVersion(ctx, contextQueryID)
require.NoError(t, err)
err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{
Queryid: contextQueryID,
Versionid: 2,
})
require.NoError(t, err)
jsonVersion := int32(1)
err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{
Queryid: jsonQueryID,
Requiredqueryid: contextQueryID,
Addedversion: jsonVersion,
})
require.NoError(t, err)
contextQuery, err := queries.GetQuery(ctx, contextQueryID)
require.NoError(t, err)
qResults, err := queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{
Queryid: &jsonQueryID,
Documentid: &documentID,
Version: &jsonVersion,
})
require.NoError(t, err)
assert.Len(t, qResults, 0)
qResults, err = queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{
Queryid: &jsonQueryID,
Documentid: &documentTwoID,
Version: &jsonVersion,
})
require.NoError(t, err)
assert.Len(t, qResults, 0)
version, err := queries.AddLatestCollectorVersion(ctx, clientId)
require.NoError(t, err)
err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{
Versionid: version,
Clientid: clientId,
})
require.NoError(t, err)
bucket := "example_bucket"
key := "example_key"
hash := "hash"
cleanid, err := queries.AddDocumentClean(ctx, &repository.AddDocumentCleanParams{
Documentid: documentID,
Bucket: &bucket,
Key: &key,
Hash: &hash,
Mimetype: repository.NullCleanmimetype{
Valid: true,
Cleanmimetype: repository.CleanmimetypeApplicationPdf,
},
})
require.NoError(t, err)
err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{
Cleanid: cleanid,
Version: 1,
})
require.NoError(t, err)
textId, err := queries.AddDocumentText(ctx, &repository.AddDocumentTextParams{
Cleanid: cleanid,
Bucket: "hi",
Key: "hello",
Hash: "example",
Part: 0,
Createdat: pgtype.Timestamp{
Time: time.Now().UTC(),
Valid: true,
},
})
require.NoError(t, err)
err = queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{
Version: 1,
Textid: textId,
})
require.NoError(t, err)
result := repository.AddResultParams{
Queryid: contextQueryID,
Value: "context_value_1",
Textentryid: textId,
Queryversion: contextQuery.Activeversion,
}
_, err = queries.AddResult(ctx, &result)
require.NoError(t, err)
qResults, err = queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{
Queryid: &jsonQueryID,
Documentid: &documentID,
Version: &jsonVersion,
})
require.NoError(t, err)
assert.Len(t, qResults, 1)
assert.Equal(t, contextQueryID, qResults[0].Queryid)
assert.Equal(t, repository.QuerytypeContextFull, qResults[0].Querytype)
assert.Equal(t, "context_value_1", *qResults[0].Value)
assert.NotEqual(t, uuid.UUID{}, qResults[0].ID)
qResults, err = queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{
Queryid: &jsonQueryID,
Documentid: &documentTwoID,
Version: &jsonVersion,
})
require.NoError(t, err)
assert.Len(t, qResults, 0)
_, err = queries.AddResult(ctx, &repository.AddResultParams{
Queryid: contextQueryID,
Value: "context_value_2",
Textentryid: textId,
Queryversion: contextQuery.Activeversion - 1,
})
require.NoError(t, err)
qResults, err = queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{
Queryid: &jsonQueryID,
Documentid: &documentID,
Version: &jsonVersion,
})
require.NoError(t, err)
assert.Len(t, qResults, 1)
assert.Equal(t, contextQueryID, qResults[0].Queryid)
assert.Equal(t, repository.QuerytypeContextFull, qResults[0].Querytype)
assert.Equal(t, "context_value_1", *qResults[0].Value)
assert.NotEqual(t, uuid.UUID{}, qResults[0].ID)
_, err = queries.AddResult(ctx, &repository.AddResultParams{
Queryid: contextQueryID,
Value: "context_value_3",
Textentryid: textId,
Queryversion: contextQuery.Activeversion,
})
require.NoError(t, err)
qResults, err = queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{
Queryid: &jsonQueryID,
Documentid: &documentID,
Version: &jsonVersion,
})
require.NoError(t, err)
assert.Len(t, qResults, 1)
assert.Equal(t, contextQueryID, qResults[0].Queryid)
assert.Equal(t, repository.QuerytypeContextFull, qResults[0].Querytype)
assert.Equal(t, "context_value_3", *qResults[0].Value)
assert.NotEqual(t, uuid.UUID{}, qResults[0].ID)
_, err = queries.AddResult(ctx, &repository.AddResultParams{
Queryid: jsonQueryID,
Value: "json_value_1",
Textentryid: textId,
Queryversion: jsonVersion,
})
require.NoError(t, err)
qResults, err = queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{
Queryid: &jsonQueryID,
Documentid: &documentID,
Version: &jsonVersion,
})
require.NoError(t, err)
assert.Len(t, qResults, 1)
assert.Equal(t, contextQueryID, qResults[0].Queryid)
assert.Equal(t, repository.QuerytypeContextFull, qResults[0].Querytype)
assert.Equal(t, "context_value_3", *qResults[0].Value)
assert.NotEqual(t, uuid.UUID{}, qResults[0].ID)
}
func TestUnsyncedNoDepsQueries(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
t.Run("single document", func(t *testing.T) {
t.Parallel()
ctx := t.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(t, cfg)
queries := cfg.GetDBQueries()
clientId := createClientWithCollector(t, queries)
contextQueryID, jsonQueryID := createDependentQueries(t, ctx, queries)
err := queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{
Clientid: clientId,
Name: "example_name",
Queryid: jsonQueryID,
Addedversion: 1,
})
require.NoError(t, err)
documentID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{
Clientid: clientId,
Hash: "example_hash",
})
require.NoError(t, err)
qs, err := queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentID)
require.NoError(t, err)
assert.Len(t, qs, 0)
bucket := "example_bucket"
key := "example_key"
hash := "hahs"
cleanid, err := queries.AddDocumentClean(ctx, &repository.AddDocumentCleanParams{
Documentid: documentID,
Bucket: &bucket,
Key: &key,
Hash: &hash,
Mimetype: repository.NullCleanmimetype{
Valid: true,
Cleanmimetype: repository.CleanmimetypeApplicationPdf,
},
})
require.NoError(t, err)
err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{
Cleanid: cleanid,
Version: 1,
})
require.NoError(t, err)
qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentID)
require.NoError(t, err)
assert.Len(t, qs, 0)
textId, err := queries.AddDocumentText(ctx, &repository.AddDocumentTextParams{
Cleanid: cleanid,
Bucket: "hi",
Key: "hello",
Part: 0,
Createdat: pgtype.Timestamp{
Time: time.Now().UTC(),
Valid: true,
},
})
require.NoError(t, err)
err = queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{
Version: 1,
Textid: textId,
})
require.NoError(t, err)
qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentID)
require.NoError(t, err)
assert.Len(t, qs, 1)
assert.ElementsMatch(t, []*uuid.UUID{&contextQueryID}, qs)
_, err = queries.AddResult(ctx, &repository.AddResultParams{
Queryid: contextQueryID,
Value: "context_value",
Textentryid: textId,
Queryversion: 1,
})
require.NoError(t, err)
qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentID)
require.NoError(t, err)
assert.Len(t, qs, 1)
assert.ElementsMatch(t, []*uuid.UUID{&jsonQueryID}, qs)
_, err = queries.AddResult(ctx, &repository.AddResultParams{
Queryid: jsonQueryID,
Value: "context_value",
Textentryid: textId,
Queryversion: 1,
})
require.NoError(t, err)
qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentID)
require.NoError(t, err)
assert.Len(t, qs, 0)
_, err = queries.AddLatestQueryVersion(ctx, jsonQueryID)
require.NoError(t, err)
err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{
Queryid: jsonQueryID,
Versionid: 2,
})
require.NoError(t, err)
qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentID)
require.NoError(t, err)
assert.Len(t, qs, 1)
assert.ElementsMatch(t, []*uuid.UUID{&jsonQueryID}, qs)
})
t.Run("two files", func(t *testing.T) {
t.Parallel()
ctx := t.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(t, cfg)
queries := cfg.GetDBQueries()
clientId := createClientWithCollector(t, queries)
contextQueryID, jsonQueryID := createDependentQueries(t, ctx, queries)
documentID, _, _ := createDocumentWithCollectorAndResults(t, queries, clientId, contextQueryID, jsonQueryID)
documentTwoID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{
Clientid: clientId,
Hash: "example_hash_two",
})
require.NoError(t, err)
bucket := "example_bucket"
key := "example_key"
hash := "hahs"
cleantwoid, err := queries.AddDocumentClean(ctx, &repository.AddDocumentCleanParams{
Documentid: documentTwoID,
Bucket: &bucket,
Key: &key,
Hash: &hash,
Mimetype: repository.NullCleanmimetype{
Valid: true,
Cleanmimetype: repository.CleanmimetypeApplicationPdf,
},
})
require.NoError(t, err)
err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{
Cleanid: cleantwoid,
Version: 1,
})
require.NoError(t, err)
qs, err := queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentID)
require.NoError(t, err)
assert.Len(t, qs, 0)
qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentTwoID)
require.NoError(t, err)
assert.Len(t, qs, 0)
textTwoId, err := queries.AddDocumentText(ctx, &repository.AddDocumentTextParams{
Cleanid: cleantwoid,
Bucket: "hi",
Key: "hello",
Part: 0,
Createdat: pgtype.Timestamp{
Time: time.Now().UTC(),
Valid: true,
},
})
require.NoError(t, err)
err = queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{
Version: 1,
Textid: textTwoId,
})
require.NoError(t, err)
_, err = queries.AddResult(ctx, &repository.AddResultParams{
Queryid: contextQueryID,
Value: "context_value",
Textentryid: textTwoId,
Queryversion: 1,
})
require.NoError(t, err)
qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentID)
require.NoError(t, err)
assert.Len(t, qs, 0)
qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentTwoID)
require.NoError(t, err)
assert.Len(t, qs, 1)
assert.ElementsMatch(t, []*uuid.UUID{&jsonQueryID}, qs)
_, err = queries.AddResult(ctx, &repository.AddResultParams{
Queryid: jsonQueryID,
Value: "context_value",
Textentryid: textTwoId,
Queryversion: 1,
})
require.NoError(t, err)
qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentID)
require.NoError(t, err)
assert.Len(t, qs, 0)
qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentTwoID)
require.NoError(t, err)
assert.Len(t, qs, 0)
})
t.Run("update query", func(t *testing.T) {
t.Parallel()
ctx := t.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(t, cfg)
queries := cfg.GetDBQueries()
clientId := createClientWithCollector(t, queries)
contextQueryID, jsonQueryID := createDependentQueries(t, ctx, queries)
documentID, _, _ := createDocumentWithCollectorAndResults(t, queries, clientId, contextQueryID, jsonQueryID)
_, err := queries.AddLatestQueryVersion(ctx, jsonQueryID)
require.NoError(t, err)
err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{
Queryid: jsonQueryID,
Versionid: 2,
})
require.NoError(t, err)
qs, err := queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentID)
require.NoError(t, err)
assert.Len(t, qs, 1)
assert.ElementsMatch(t, []*uuid.UUID{&jsonQueryID}, qs)
})
}
func BenchmarkListUnsynced(b *testing.B) {
ctx := b.Context()
cfg := &serviceconfig.BaseConfig{}
test.CreateDB(b, cfg)
queries := cfg.GetDBQueries()
clientId := createClientWithCollector(b, queries)
_, jsonQueryID := createDependentQueries(b, ctx, queries)
err := queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{
Clientid: clientId,
Name: "example_name",
Queryid: jsonQueryID,
Addedversion: 1,
})
require.NoError(b, err)
documentID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{
Clientid: clientId,
Hash: "example_hash",
BatchID: nil,
})
require.NoError(b, err)
b.ResetTimer()
for b.Loop() {
_, _ = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, &documentID)
}
}
File diff suppressed because it is too large Load Diff