-- 034_trade_in_estimates_geom.sql -- Purpose: schema-consistency debt — add PostGIS geom column + GIST index + trigger -- to trade_in_estimates (table currently has lat/lon but no geom). -- Dependencies: 001_trade_in_estimates.sql (table must exist) -- Deploy order: any time after 001. -- -- Why: rule `.claude/rules/sql.md` — any table with lat/lon should have geom + GIST -- for future spatial queries. Currently estimator does not query trade_in_estimates -- spatially, but views/audits will. Trigger keeps geom in sync with lat/lon writes. -- -- Idempotent: ADD COLUMN/INDEX IF NOT EXISTS; CREATE OR REPLACE FUNCTION; DROP+CREATE TRIGGER. BEGIN; ALTER TABLE trade_in_estimates ADD COLUMN IF NOT EXISTS geom geometry(Point, 4326); -- Backfill from existing lat/lon (idempotent — only rows where geom is currently NULL). UPDATE trade_in_estimates SET geom = ST_SetSRID(ST_MakePoint(lon, lat), 4326) WHERE geom IS NULL AND lat IS NOT NULL AND lon IS NOT NULL; CREATE INDEX IF NOT EXISTS trade_in_estimates_geom_idx ON trade_in_estimates USING GIST (geom); CREATE OR REPLACE FUNCTION trade_in_estimates_set_geom() RETURNS trigger AS $$ BEGIN IF NEW.lat IS NOT NULL AND NEW.lon IS NOT NULL THEN NEW.geom := ST_SetSRID(ST_MakePoint(NEW.lon, NEW.lat), 4326); ELSE NEW.geom := NULL; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS trade_in_estimates_set_geom_trg ON trade_in_estimates; CREATE TRIGGER trade_in_estimates_set_geom_trg BEFORE INSERT OR UPDATE OF lat, lon ON trade_in_estimates FOR EACH ROW EXECUTE FUNCTION trade_in_estimates_set_geom(); COMMIT;