perf(sql): _form_affected_rows собирает только затронутое поддерево (AURORA-1850)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andrey Epifancev 2026-10-29 00:06:52 +04:00
parent eb43c0fa69
commit 66b8b8a8e0

View File

@ -2626,3 +2626,117 @@ BEGIN
END;
$function$
;
CREATE OR REPLACE FUNCTION v3._form_affected_rows(p_form_id integer, p_sheet character varying, p_ids integer[], p_direction character varying DEFAULT NULL::character varying, p_sections text[] DEFAULT NULL::text[])
RETURNS TABLE(row_type character varying, depth integer, sort_order bigint, data jsonb)
LANGUAGE plpgsql
STABLE
AS $function$
DECLARE
v_form_type VARCHAR;
v_strip TEXT[] := ARRAY[]::TEXT[];
v_lc_path INT[];
v_eid_set INT[];
v_ei_path INT[];
BEGIN
SELECT bf.form_type_code INTO v_form_type
FROM v3.budget_form bf
WHERE bf.id = p_form_id;
IF p_sections IS NOT NULL THEN
SELECT COALESCE(array_agg(k), ARRAY[]::TEXT[])
INTO v_strip
FROM unnest(ARRAY['plan','seq_dfip','seq_ssp','approved','contract','booking',
'contract_summary','allocation','collegial','ckk',
'sequestration','reserve','contract_detail',
'q1','q2','q3','q4','totals',
'fact_q1','fact_q2','fact_q3','fact_q4']) AS k
WHERE NOT (k = ANY(p_sections));
END IF;
IF v_form_type = 'FORM_1' AND p_sheet IN ('AHR','CAP','OPER') THEN
RETURN QUERY
SELECT v.row_type, v.depth, v.sort_order, v.data - v_strip
FROM v3.v_form1_view(p_form_id, p_sheet, p_sections, p_direction, COALESCE(p_ids, '{}'::INT[])) v
ORDER BY v.sort_order;
RETURN;
ELSIF v_form_type = 'FORM_2' AND p_sheet IN ('AHR','CAP','OPER','AHR_RENT','AHR_UTILITY','AHR_SECURITY','AHR_LIMIT','OTCH9F') THEN
RETURN QUERY
SELECT v.row_type, v.depth, v.sort_order, v.data - v_strip
FROM v3.v_form2_view(p_form_id, p_sheet, p_sections, COALESCE(p_ids, '{}'::INT[])) v
ORDER BY v.sort_order;
RETURN;
END IF;
IF p_sheet IN ('AHR_RENT','AHR_UTILITY','AHR_SECURITY') THEN
RETURN QUERY
SELECT v.row_type, v.depth, v.sort_order, v.data - v_strip
FROM v3.v_form_view(p_form_id, p_sheet, p_sections, p_direction) v
WHERE v.row_type = 'INPUT' AND (v.data->>'id')::INT = ANY(p_ids)
ORDER BY v.sort_order;
ELSIF p_sheet = 'AHR_LIMIT' THEN
v_lc_path := v3._limit_template_path_set(p_ids);
RETURN QUERY
SELECT v.row_type, v.depth, v.sort_order, v.data - v_strip
FROM v3.v_form_view(p_form_id, p_sheet, p_sections, p_direction) v
WHERE (v.data->>'id')::INT = ANY(v_lc_path)
ORDER BY v.sort_order;
ELSIF p_sheet = 'OTCH9F' THEN
RETURN QUERY
SELECT v.row_type, v.depth, v.sort_order, v.data - v_strip
FROM v3.v_form_view(p_form_id, p_sheet, p_sections, p_direction) v
WHERE EXISTS (
SELECT 1 FROM v3.fixed_asset_report far
WHERE far.id = ANY(p_ids)
AND far.expense_item_id = (v.data->>'expense_item_id')::INT
AND far.equipment_name IS NOT DISTINCT FROM (v.data->>'equipment_name'))
ORDER BY v.sort_order;
ELSE
SELECT array_agg(DISTINCT bl.expense_item_id)
INTO v_eid_set
FROM v3.budget_line bl
WHERE bl.id = ANY(p_ids);
v_ei_path := v3._expense_item_path_set(v_eid_set);
IF v_form_type = 'FORM_4' THEN
RETURN QUERY
WITH vv AS MATERIALIZED (
SELECT f.row_type, f.depth, f.sort_order, f.data
FROM v3.v_form_view(p_form_id, p_sheet, p_sections, p_direction) f
WHERE f.row_type <> 'META'
),
chg AS (
SELECT DISTINCT (x.data->'header'->>'program_id')::INT AS program_id,
(x.data->'header'->>'project_id')::INT AS project_id
FROM vv x
WHERE x.row_type = 'INPUT' AND (x.data->>'line_id')::INT = ANY(p_ids)
)
SELECT v.row_type, v.depth, v.sort_order, v.data - v_strip
FROM vv v
WHERE (v.row_type = 'INPUT' AND (v.data->>'line_id')::INT = ANY(p_ids))
OR (v.row_type = 'ROOT'
AND (v.data->'header'->>'expense_item_id')::INT = ANY(v_ei_path))
OR (v.row_type = 'GROUP'
AND (v.data->'header'->>'expense_item_id')::INT = ANY(v_ei_path)
AND (v.data->'header'->>'program_id')::INT IN (SELECT c.program_id FROM chg c))
OR (v.row_type = 'ITEM'
AND (v.data->'header'->>'expense_item_id')::INT = ANY(v_ei_path)
AND (v.data->'header'->>'project_id')::INT IN (SELECT c.project_id FROM chg c))
ORDER BY v.sort_order;
ELSE
RETURN QUERY
SELECT v.row_type, v.depth, v.sort_order, v.data - v_strip
FROM v3.v_form_view(p_form_id, p_sheet, p_sections, p_direction) v
WHERE (v.row_type IN ('ROOT','GROUP','ITEM','SUB_ITEM','SUB_SUB_ITEM')
AND (v.data->'header'->>'expense_item_id')::INT = ANY(v_ei_path))
OR (v.row_type = 'INPUT'
AND (v.data->>'line_id')::INT = ANY(p_ids))
ORDER BY v.sort_order;
END IF;
END IF;
END;
$function$
;