-- -- Status tracking: view_generated_at on sources and stacks -- Cleared by triggers when definitions change; set by API when views are generated. -- SET search_path TO dataflow, public; -- Add view_generated_at columns ALTER TABLE dataflow.sources ADD COLUMN IF NOT EXISTS view_generated_at TIMESTAMPTZ; ALTER TABLE dataflow.stacks ADD COLUMN IF NOT EXISTS view_generated_at TIMESTAMPTZ; ------------------------------------------------------ -- Trigger: clear source view_generated_at when rules change ------------------------------------------------------ CREATE OR REPLACE FUNCTION dataflow.rules_changed() RETURNS TRIGGER AS $$ BEGIN UPDATE dataflow.sources SET view_generated_at = NULL WHERE name = COALESCE(NEW.source_name, OLD.source_name); RETURN NULL; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS trg_rules_changed ON dataflow.rules; CREATE TRIGGER trg_rules_changed AFTER INSERT OR UPDATE OR DELETE ON dataflow.rules FOR EACH ROW EXECUTE FUNCTION dataflow.rules_changed(); ------------------------------------------------------ -- Trigger: clear source view_generated_at when mappings change ------------------------------------------------------ CREATE OR REPLACE FUNCTION dataflow.mappings_changed() RETURNS TRIGGER AS $$ BEGIN UPDATE dataflow.sources SET view_generated_at = NULL WHERE name = COALESCE(NEW.source_name, OLD.source_name); RETURN NULL; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS trg_mappings_changed ON dataflow.mappings; CREATE TRIGGER trg_mappings_changed AFTER INSERT OR UPDATE OR DELETE ON dataflow.mappings FOR EACH ROW EXECUTE FUNCTION dataflow.mappings_changed(); ------------------------------------------------------ -- Trigger: clear stack view_generated_at when sources change ------------------------------------------------------ CREATE OR REPLACE FUNCTION dataflow.stack_sources_changed() RETURNS TRIGGER AS $$ BEGIN UPDATE dataflow.stacks SET view_generated_at = NULL WHERE name = COALESCE(NEW.stack_name, OLD.stack_name); RETURN NULL; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS trg_stack_sources_changed ON dataflow.stack_sources; CREATE TRIGGER trg_stack_sources_changed AFTER INSERT OR UPDATE OR DELETE ON dataflow.stack_sources FOR EACH ROW EXECUTE FUNCTION dataflow.stack_sources_changed(); ------------------------------------------------------ -- Function: get_status -- Returns sources and stacks whose view is stale (null or never generated) ------------------------------------------------------ CREATE OR REPLACE FUNCTION get_status() RETURNS JSON AS $$ DECLARE v_sources JSON; v_stacks JSON; BEGIN SELECT COALESCE(json_agg(json_build_object('name', name, 'view_generated_at', view_generated_at) ORDER BY name), '[]'::json) INTO v_sources FROM dataflow.sources WHERE view_generated_at IS NULL; SELECT COALESCE(json_agg(json_build_object('name', name, 'view_generated_at', view_generated_at) ORDER BY name), '[]'::json) INTO v_stacks FROM dataflow.stacks WHERE view_generated_at IS NULL; RETURN json_build_object('stale_sources', v_sources, 'stale_stacks', v_stacks); END; $$ LANGUAGE plpgsql STABLE;