From 0c62d0b0c3be6eabf3eb51ea46c896da7f72161a Mon Sep 17 00:00:00 2001 From: Light1YT Date: Sat, 13 Jun 2026 12:43:28 +0500 Subject: [PATCH] =?UTF-8?q?fix(site-finder):=20=D1=81=D0=BA=D0=BB=D0=B5?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D1=80=D0=B0=D0=B7=D0=BE=D1=80=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B9=20regex=20=D0=B2=20=5FPLANNING=5FNO=5F?= =?UTF-8?q?MATCH=5FSQL=20(#1230)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Литерал regex был разорван переносом строки внутри одной пары '...': ветки 'Донбасской\\n' и 'Лумумбы\\n' содержали NL+8 пробелов и никогда не матчили однострочные planning_projects.full_name (PG ~ — POSIX ARE без (?x)). Geom-only КРТ-fallback молча терял ППТ по этим двум топонимам. Patch: вынес паттерн в _KRT_TOPONYM_REGEX через Python adjacent-literal concat, склеил в SQL через +. Все 17 веток в одной строке. 9 krt_lookup тестов зелёные. Closes #1230 --- .../app/services/site_finder/krt_lookup.py | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/backend/app/services/site_finder/krt_lookup.py b/backend/app/services/site_finder/krt_lookup.py index 5d37c9b4..054af74b 100644 --- a/backend/app/services/site_finder/krt_lookup.py +++ b/backend/app/services/site_finder/krt_lookup.py @@ -64,6 +64,20 @@ _PLANNING_KRT_SQL = text( # Вторичный запрос: planning_projects без матча с ekb_krt_sites — geom-only без реквизитов. # Запускается только если первый не дал результатов, чтобы не путать пользователя # двумя overlapping-источниками. +# +# Regex-топонимы для geom-only КРТ-fallback — собран как ОДИН непрерывный паттерн. +# Раньше literal был разорван переносом строки внутри ОДНОЙ пары '...' внутри SQL, +# и ветки 'Донбасской\n ' / 'Лумумбы\n ' содержали NL+8 пробелов отступа, +# никогда не матчили однострочные full_name (PG `~` — POSIX ARE без (?x)) — #1230. +# Python склеивает соседние строковые литералы на этапе парсинга, поэтому regex попадает +# в SQL одной строкой. Не SQL-injection: статическая константа, без user input. +# При добавлении новых топонимов держим строки <100 chars и НЕ ломаем regex переносом. +_KRT_TOPONYM_REGEX = ( + "[кК][рР][тТ]|комплексн.*развити|Краснофлотцев|Донбасской|Шефской|Азина" + "|Черкасской|Кварцевой|Летчиков|Вилонова|Лумумбы|Студенческой|Васильева" + "|Гурзуфск|Бакинских|Шадринский|Бабушкина" +) + _PLANNING_NO_MATCH_SQL = text( """ SELECT @@ -76,9 +90,9 @@ _PLANNING_NO_MATCH_SQL = text( pp.geom, ST_GeomFromText(CAST(:parcel_wkt AS text), 4326) ) - AND pp.full_name ~ '[кК][рР][тТ]|комплексн.*развити|Краснофлотцев|Донбасской - |Шефской|Азина|Черкасской|Кварцевой|Летчиков|Вилонова|Лумумбы - |Студенческой|Васильева|Гурзуфск|Бакинских|Шадринский|Бабушкина' + AND pp.full_name ~ '""" + + _KRT_TOPONYM_REGEX + + """' ORDER BY pp.dmd_actual_year DESC """ ) -- 2.45.3