dataflow/database/queries/records.sql
Paul Trowbridge e5b95e7112 Add bulk override: DB function, API route, UI select bar
- bulk_set_record_overrides() DB function merges overrides into multiple
  records at once using a CTE with RETURNING for accurate count
- POST /records/bulk-overrides calls the function (consistent with rest
  of API — no raw SQL in routes)
- UI: regex input on loaded rows selects rows for bulk override; labeled
  "Bulk select:" / "DB query:" to distinguish from server-side filters

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 10:55:59 -04:00

91 lines
3.4 KiB
PL/PgSQL

--
-- Records queries
-- All SQL for api/routes/records.js
--
SET search_path TO dataflow, public;
-- ── Read ──────────────────────────────────────────────────────────────────────
CREATE OR REPLACE FUNCTION list_records(
p_source_name TEXT,
p_limit INT DEFAULT 100,
p_offset INT DEFAULT 0,
p_transformed_only BOOLEAN DEFAULT FALSE
)
RETURNS SETOF dataflow.records AS $$
SELECT * FROM dataflow.records
WHERE source_name = p_source_name
AND (NOT p_transformed_only OR transformed IS NOT NULL)
ORDER BY id DESC
LIMIT p_limit OFFSET p_offset;
$$ LANGUAGE sql STABLE;
CREATE OR REPLACE FUNCTION get_record(p_id BIGINT)
RETURNS dataflow.records AS $$
SELECT * FROM dataflow.records WHERE id = p_id;
$$ LANGUAGE sql STABLE;
CREATE OR REPLACE FUNCTION search_records(
p_source_name TEXT,
p_query JSONB,
p_limit INT DEFAULT 100
)
RETURNS SETOF dataflow.records AS $$
SELECT * FROM dataflow.records
WHERE source_name = p_source_name
AND (data @> p_query OR transformed @> p_query)
ORDER BY id DESC
LIMIT p_limit;
$$ LANGUAGE sql STABLE;
-- ── Overrides ─────────────────────────────────────────────────────────────────
-- Store manual overrides and immediately merge into transformed
CREATE OR REPLACE FUNCTION set_record_overrides(p_id INT, p_overrides JSONB)
RETURNS dataflow.records AS $$
UPDATE dataflow.records
SET overrides = CASE WHEN p_overrides = '{}'::jsonb THEN NULL ELSE p_overrides END,
transformed = COALESCE(transformed, data) || COALESCE(p_overrides, '{}'::jsonb)
WHERE id = p_id
RETURNING *;
$$ LANGUAGE sql;
-- Merge overrides into multiple records at once; returns actual updated count
CREATE OR REPLACE FUNCTION bulk_set_record_overrides(p_source_name TEXT, p_ids INT[], p_overrides JSONB)
RETURNS BIGINT AS $$
WITH updated AS (
UPDATE dataflow.records
SET overrides = COALESCE(overrides, '{}'::jsonb) || p_overrides,
transformed = COALESCE(transformed, data) || p_overrides
WHERE id = ANY(p_ids)
AND source_name = p_source_name
RETURNING id
)
SELECT count(*) FROM updated;
$$ LANGUAGE sql;
-- Clear overrides; caller should reprocess to restore computed transformed value
CREATE OR REPLACE FUNCTION clear_record_overrides(p_id INT)
RETURNS dataflow.records AS $$
UPDATE dataflow.records
SET overrides = NULL
WHERE id = p_id
RETURNING *;
$$ LANGUAGE sql;
-- ── Delete ────────────────────────────────────────────────────────────────────
CREATE OR REPLACE FUNCTION delete_record(p_id BIGINT)
RETURNS TABLE (id BIGINT) AS $$
DELETE FROM dataflow.records WHERE id = p_id RETURNING id;
$$ LANGUAGE sql;
CREATE OR REPLACE FUNCTION delete_source_records(p_source_name TEXT)
RETURNS TABLE (deleted_count BIGINT) AS $$
WITH deleted AS (
DELETE FROM dataflow.records WHERE source_name = p_source_name RETURNING id
)
SELECT count(*) AS deleted_count FROM deleted;
$$ LANGUAGE sql;