fix(sf): ST_MakeValid genplan geom + backfill 881 invalid polygons (#1156) #1157
3 changed files with 29 additions and 3 deletions
|
|
@ -7,7 +7,8 @@
|
|||
• SessionLocal() + try/finally close; logger (не print).
|
||||
• SAVEPOINT per-row (``with db.begin_nested():``) — одна битая фича не валит батч.
|
||||
• CAST(:x AS type) — НИКОГДА :x::type (psycopg v3).
|
||||
• Геометрия: ST_SetSRID(ST_GeomFromGeoJSON, 4326) — без transform (уже 4326).
|
||||
• Геометрия: ST_MakeValid(ST_SetSRID(ST_GeomFromGeoJSON, 4326)) — без transform (уже 4326);
|
||||
ST_MakeValid исправляет self-intersecting/ring-order дефекты геопортала (#1156).
|
||||
• ON CONFLICT (globalid) DO UPDATE: обновляет все поля кроме id/fetched_at (latest wins).
|
||||
• commit один раз в конце.
|
||||
|
||||
|
|
@ -31,7 +32,9 @@ from app.workers.celery_app import celery_app
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# UPSERT одной фичи. geom = ST_SetSRID(ST_GeomFromGeoJSON, 4326) — данные уже в 4326.
|
||||
# UPSERT одной фичи. geom = ST_MakeValid(ST_SetSRID(ST_GeomFromGeoJSON, 4326)) —
|
||||
# ST_MakeValid оборачивает результат чтобы исправить self-intersecting/ring-order
|
||||
# дефекты из источника геопортала (881/6436 полигонов имели ST_IsValid=false, #1156).
|
||||
# ON CONFLICT обновляет все аналитические поля; fetched_at = excluded (latest wins).
|
||||
# CAST(:x AS type) — psycopg v3 (НИКОГДА :x::type).
|
||||
_UPSERT_SQL = text(
|
||||
|
|
@ -46,7 +49,7 @@ _UPSERT_SQL = text(
|
|||
CAST(:status AS text),
|
||||
CAST(:area_ha AS numeric),
|
||||
CAST(:doc_ref AS text),
|
||||
ST_SetSRID(ST_GeomFromGeoJSON(CAST(:geojson AS text)), 4326),
|
||||
ST_MakeValid(ST_SetSRID(ST_GeomFromGeoJSON(CAST(:geojson AS text)), 4326)),
|
||||
CAST(:raw_props AS jsonb),
|
||||
CAST(:fetched_at AS timestamptz)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -199,3 +199,15 @@ def test_sync_empty_wfs_response(monkeypatch: Any) -> None:
|
|||
assert result == {"zones": 0}
|
||||
assert db.committed is True
|
||||
assert db.closed is True
|
||||
|
||||
|
||||
def test_upsert_sql_wraps_geom_with_st_makevalid() -> None:
|
||||
"""_UPSERT_SQL содержит ST_MakeValid вокруг ST_SetSRID (#1156).
|
||||
|
||||
Лёгкая проверка без PostGIS: строковое представление compiled SQL
|
||||
должно включать ST_MakeValid — гарантирует что backfill-логика
|
||||
присутствует в тексте запроса.
|
||||
"""
|
||||
sql_text = str(genplan_zones_sync._UPSERT_SQL)
|
||||
assert "ST_MakeValid" in sql_text
|
||||
assert "ST_SetSRID" in sql_text
|
||||
|
|
|
|||
11
data/sql/143_genplan_makevalid_backfill.sql
Normal file
11
data/sql/143_genplan_makevalid_backfill.sql
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
-- 143_genplan_makevalid_backfill.sql
|
||||
-- Одноразовый backfill: исправить невалидные геометрии генплан-зон (#1156).
|
||||
-- 881/6436 полигонов имели ST_IsValid=false (self-intersecting rings из геопортала).
|
||||
-- Идемпотентно: повторный прогон no-op (WHERE NOT ST_IsValid).
|
||||
BEGIN;
|
||||
|
||||
UPDATE ekb_genplan_functional_zone
|
||||
SET geom = ST_MakeValid(geom)
|
||||
WHERE NOT ST_IsValid(geom);
|
||||
|
||||
COMMIT;
|
||||
Loading…
Add table
Reference in a new issue