-- 227_drop_position_in_serp.sql -- listings_snapshots.position_in_serp — DROP, шаг 2 из 2 (#2697, продолжение #2674). -- -- Dependencies: 217_position_in_serp_unexpressible.sql (диагноз + COMMENT на колонке). -- Apply after: 224_houses_house_type_canon.sql -- Идемпотентно: DROP COLUMN IF EXISTS. -- -- ── ПОЧЕМУ УДАЛЯЕМ, А НЕ ПОДКЛЮЧАЕМ ────────────────────────────────────────── -- Полный разбор — в 217. Кратко: позиция есть свойство пары (объявление, конкретный -- прогон выдачи с конкретными фильтрами), а PRIMARY KEY (listing_id, snapshot_date) -- держит одну строку на объявление в сутки — при том что за 2026-08-03 по этому ключу -- писали 13 разных run_id и четыре SERP-источника, а внутри одного city_sweep -- объявление приезжает с разным индексом от перекрывающихся гео-якорей. Значение -- оседало бы от последнего писателя дня и читалось бы как факт. Честное хранение — -- отдельная таблица с ключом (run_id, listing_id) и сохранёнными фильтрами прогона, -- то есть НЕ возврат этой колонки. -- -- ── ПРЕДУСЛОВИЕ ПРОВЕРЕНО ПЕРЕД МЕРЖЕМ (2026-08-06) ────────────────────────── -- Окно «SQL применяется ДО перезапуска контейнеров» закрыто тем, что правка кода -- (#2694) уже живёт на проде — проверено ПО КОДУ В КОНТЕЙНЕРАХ, не по зелёному -- деплою: grep по /app в tradein-scraper и tradein-backend находит имя колонки -- ровно в четырёх строках docstring'а snapshot_writer.py (18/34/37/76) и ни в одном -- SQL; inspect.signature(upsert_listing_snapshot) колонку не содержит. -- Оба живых писателя перечисляют колонки явно и этой в списке не имеют: -- * scraper_kit/snapshot_writer.py::upsert_listing_snapshot (весь скрейп-путь), -- * app/tasks/deactivate_stale_avito.py::_STALE_SNAPSHOT_TAIL (TTL-снимки 'stale'). -- -- ── ЧИТАТЕЛЕЙ НЕТ ──────────────────────────────────────────────────────────── -- На проде: 0 непустых значений из 397 217 строк; 0 view/matview зависят от колонки -- (pg_depend → pg_rewrite); индексов и триггеров на ней нет; foreign table над -- listings_snapshots не существует (FDW-обёртки только над gendesign-таблицами); -- в information_schema.columns имя встречается ровно в этой таблице. В коде: ни -- одного SELECT-читателя (`SELECT *` по таблице нигде нет), фронт/экспортёры/админка -- колонку не упоминают. Единственный сторож — tests/test_snapshot_writer.py, он -- проверяет отсутствие колонки у писателя и после DROP остаётся валиден. BEGIN; ALTER TABLE listings_snapshots DROP COLUMN IF EXISTS position_in_serp; COMMIT;