From 2b23a4b24b54b2248de5fe6ca5257bc93be05f47 Mon Sep 17 00:00:00 2001 From: Light1YT Date: Sat, 13 Jun 2026 08:59:45 +0500 Subject: [PATCH] =?UTF-8?q?fix(parcels):=20rename=20CTE=20overlaps=20?= =?UTF-8?q?=E2=86=92=20overlap=5Frows=20(#1196=20regression=20of=20#1195)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `OVERLAPS` — это PostgreSQL keyword (binary operator для time-periods — `(start1,end1) OVERLAPS (start2,end2)`). Парсер ругается на `overlaps AS (...)` в WITH-блоке с ERROR: syntax error at or near "overlaps" → exception → транзакция в aborted state → весь analyze пайплайн ниже получает InFailedSqlTransaction (ird_overlays, persist, ird block) → фронт видит data_available=False, neighbors=[]. Воспроизводится на КАЖДОМ /analyze с момента мерджа PR #1195. Mock-БД в pytest tests/api/v1/ синтаксис не проверяет — отсюда регрессия прошла CI. Прямой psql-replay на проде: WITH neighbors AS (...), overlaps AS (...) → syntax error WITH neighbors AS (...), overlap_rows AS (...) → ok Минимальная переименование CTE alias (4 строки: 2 в SQL + 1 в SELECT column alias + 1 в Python `row["overlap_rows"]`). Семантика идентична PR #1195. Memory: future-proofing — добавить интеграционный тест с реальной PG для analyze hot-path (отдельный issue, не блокер этого hotfix). Refs #1196 --- backend/app/api/v1/parcels.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/app/api/v1/parcels.py b/backend/app/api/v1/parcels.py index 0c5c1d0a..8999bc17 100644 --- a/backend/app/api/v1/parcels.py +++ b/backend/app/api/v1/parcels.py @@ -620,7 +620,7 @@ def _neighbors_summary(db: Session, geom_wkt: str, our_cad_num: str) -> dict[str ORDER BY distance_m ASC LIMIT 30 ), - overlaps AS ( + overlap_rows AS ( SELECT cad_num, building_name, floors, @@ -637,6 +637,8 @@ def _neighbors_summary(db: Session, geom_wkt: str, our_cad_num: str) -> dict[str ORDER BY overlap_m2 DESC NULLS LAST LIMIT 5 ) + -- CTE name `overlap_rows` (НЕ `overlaps`): `OVERLAPS` — PG keyword + -- (binary operator для time-periods), парсер ругается на `overlaps AS (`. SELECT COALESCE( (SELECT json_agg(row_to_json(n) ORDER BY n.distance_m ASC) @@ -645,9 +647,9 @@ def _neighbors_summary(db: Session, geom_wkt: str, our_cad_num: str) -> dict[str ) AS neighbors, COALESCE( (SELECT json_agg(row_to_json(o) ORDER BY o.overlap_m2 DESC NULLS LAST) - FROM overlaps o), + FROM overlap_rows o), '[]'::json - ) AS overlaps + ) AS overlap_rows """), {"wkt": geom_wkt, "our_cad": our_cad_num}, ) @@ -655,7 +657,7 @@ def _neighbors_summary(db: Session, geom_wkt: str, our_cad_num: str) -> dict[str .first() ) neighbor_rows: list[dict[str, Any]] = list(row["neighbors"]) if row else [] - overlap_row: list[dict[str, Any]] = list(row["overlaps"]) if row else [] + overlap_row: list[dict[str, Any]] = list(row["overlap_rows"]) if row else [] except Exception as e: logger.warning("neighbors query failed: %s", e) return {"data_available": False, "note": f"neighbors query failed: {e}"} -- 2.45.3