perf(formulas): равенство по владельцу вместо IS NOT DISTINCT FROM, отказ на Infinity (AURORA-1896, M-1, M-2, M-3)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andrey Epifancev 2026-11-11 21:06:53 +04:00
parent e569d18624
commit e107fa418d
2 changed files with 54 additions and 28 deletions

View File

@ -85,12 +85,20 @@ BEGIN
END IF;
IF v_expr = '' THEN
DELETE FROM v3.cell_formula cf
WHERE cf.sheet = p_sheet
AND cf.line_id = v_line
AND cf.column_key = v_column
AND cf.budget_form_id IS NOT DISTINCT FROM p_budget_form_id
AND cf.rf_project_report_id IS NOT DISTINCT FROM p_report_id;
-- равенство по владельцу в отдельных ветках: так планировщик берёт частичные уникальные индексы
IF p_budget_form_id IS NOT NULL THEN
DELETE FROM v3.cell_formula cf
WHERE cf.budget_form_id = p_budget_form_id
AND cf.sheet = p_sheet
AND cf.line_id = v_line
AND cf.column_key = v_column;
ELSE
DELETE FROM v3.cell_formula cf
WHERE cf.rf_project_report_id = p_report_id
AND cf.sheet = p_sheet
AND cf.line_id = v_line
AND cf.column_key = v_column;
END IF;
CONTINUE;
END IF;
@ -106,7 +114,7 @@ BEGIN
EXCEPTION WHEN others THEN
RAISE EXCEPTION 'invalid_formula: value';
END;
IF v_value IS NULL OR v_value = 'NaN'::numeric THEN
IF v_value IS NULL OR v_value::text IN ('NaN', 'Infinity', '-Infinity') THEN
RAISE EXCEPTION 'invalid_formula: value';
END IF;
@ -117,6 +125,16 @@ BEGIN
ON CONFLICT (budget_form_id, sheet, line_id, column_key) WHERE budget_form_id IS NOT NULL
DO UPDATE SET expression = EXCLUDED.expression, value = EXCLUDED.value,
updated_by = EXCLUDED.updated_by, updated_at = EXCLUDED.updated_at;
RETURN QUERY
SELECT cf.line_id, cf.column_key, cf.expression, cf.value, cf.updated_by,
u.full_name::text, cf.updated_at
FROM v3.cell_formula cf
LEFT JOIN v3.app_user u ON u.id = cf.updated_by
WHERE cf.budget_form_id = p_budget_form_id
AND cf.sheet = p_sheet
AND cf.line_id = v_line
AND cf.column_key = v_column;
ELSE
INSERT INTO v3.cell_formula AS cf
(rf_project_report_id, sheet, line_id, column_key, expression, value, updated_by, updated_at)
@ -124,18 +142,16 @@ BEGIN
ON CONFLICT (rf_project_report_id, sheet, line_id, column_key) WHERE rf_project_report_id IS NOT NULL
DO UPDATE SET expression = EXCLUDED.expression, value = EXCLUDED.value,
updated_by = EXCLUDED.updated_by, updated_at = EXCLUDED.updated_at;
RETURN QUERY
SELECT cf.line_id, cf.column_key, cf.expression, cf.value, cf.updated_by,
u.full_name::text, cf.updated_at
FROM v3.cell_formula cf
LEFT JOIN v3.app_user u ON u.id = cf.updated_by
WHERE cf.rf_project_report_id = p_report_id
AND cf.sheet = p_sheet
AND cf.line_id = v_line
AND cf.column_key = v_column;
END IF;
RETURN QUERY
SELECT cf.line_id, cf.column_key, cf.expression, cf.value, cf.updated_by,
u.full_name::text, cf.updated_at
FROM v3.cell_formula cf
LEFT JOIN v3.app_user u ON u.id = cf.updated_by
WHERE cf.sheet = p_sheet
AND cf.line_id = v_line
AND cf.column_key = v_column
AND cf.budget_form_id IS NOT DISTINCT FROM p_budget_form_id
AND cf.rf_project_report_id IS NOT DISTINCT FROM p_report_id;
END LOOP;
END;
$function$;
@ -163,15 +179,25 @@ BEGIN
RAISE EXCEPTION 'invalid_formula: owner';
END IF;
RETURN QUERY
SELECT cf.line_id, cf.column_key, cf.expression, cf.value, cf.updated_by,
u.full_name::text, cf.updated_at
FROM v3.cell_formula cf
LEFT JOIN v3.app_user u ON u.id = cf.updated_by
WHERE cf.sheet = p_sheet
AND cf.budget_form_id IS NOT DISTINCT FROM p_budget_form_id
AND cf.rf_project_report_id IS NOT DISTINCT FROM p_report_id
ORDER BY cf.line_id, cf.column_key;
IF p_budget_form_id IS NOT NULL THEN
RETURN QUERY
SELECT cf.line_id, cf.column_key, cf.expression, cf.value, cf.updated_by,
u.full_name::text, cf.updated_at
FROM v3.cell_formula cf
LEFT JOIN v3.app_user u ON u.id = cf.updated_by
WHERE cf.budget_form_id = p_budget_form_id
AND cf.sheet = p_sheet
ORDER BY cf.line_id, cf.column_key;
ELSE
RETURN QUERY
SELECT cf.line_id, cf.column_key, cf.expression, cf.value, cf.updated_by,
u.full_name::text, cf.updated_at
FROM v3.cell_formula cf
LEFT JOIN v3.app_user u ON u.id = cf.updated_by
WHERE cf.rf_project_report_id = p_report_id
AND cf.sheet = p_sheet
ORDER BY cf.line_id, cf.column_key;
END IF;
END;
$function$;

View File

@ -87,7 +87,7 @@ def test_empty_after_normalization_is_no_formula(svod2_sql):
@pytest.mark.parametrize(
"formula,value",
[("drop table", 1), ("1" * 501, 1), ("1+1", None), ("1+1", "abc"), ("1+1", "NaN")],
[("drop table", 1), ("1" * 501, 1), ("1+1", None), ("1+1", "abc"), ("1+1", "NaN"), ("1+1", "Infinity"), ("1+1", "-Infinity")],
)
def test_invalid_formula_raises(svod2_sql, formula, value):
admin, line = _admin(svod2_sql), _line(svod2_sql)