diff --git a/api/alembic/versions/sql/0060_cell_formula.sql b/api/alembic/versions/sql/0060_cell_formula.sql index 6cac185..c10f4af 100644 --- a/api/alembic/versions/sql/0060_cell_formula.sql +++ b/api/alembic/versions/sql/0060_cell_formula.sql @@ -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$; diff --git a/api/tests/integration/test_cell_formula_sql.py b/api/tests/integration/test_cell_formula_sql.py index 08d01da..d333497 100644 --- a/api/tests/integration/test_cell_formula_sql.py +++ b/api/tests/integration/test_cell_formula_sql.py @@ -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)