PotholeIQ / db /schema.sql
Varun10000's picture
PotholeIQ: initial deployable build (Box + Supabase, HF Spaces Docker)
45e997f
Raw
History Blame Contribute Delete
3.03 kB
-- PotholeIQ β€” Supabase schema (PostgreSQL + PostGIS)
-- Run this once in the Supabase SQL editor (Project β†’ SQL Editor β†’ New query β†’ paste β†’ Run).
-- 1. Geospatial extension
create extension if not exists postgis;
-- 2. Cases table. `geom` is a geography point so radius queries are in METERS.
create table if not exists cases (
case_id text primary key,
status text,
submitted_at timestamptz,
resolved_at timestamptz,
address text,
ward text,
district text,
maintenance_zone text,
latitude double precision,
longitude double precision,
geom geography(Point, 4326),
severity_score numeric,
severity_level text,
pothole_size text,
duplicate_status text,
duplicate_count integer default 0,
linked_case_ids text,
weather_risk text,
ai_review_status text,
reporter_contact text,
photo_url text,
box_folder_id text,
-- crew closeout
assigned_crew text,
repair_method text,
materials_used text,
labor_hours numeric,
crew_notes text,
after_photo_url text,
signed_by text,
signed_at timestamptz,
raw jsonb,
created_at timestamptz default now(),
updated_at timestamptz default now()
);
-- 3. Indexes β€” spatial index makes "any pothole within 50m?" an instant lookup
create index if not exists cases_geom_gix on cases using gist (geom);
create index if not exists cases_status_idx on cases (status);
create index if not exists cases_ward_idx on cases (ward);
create index if not exists cases_submitted_idx on cases (submitted_at desc);
-- 4. Keep geom in sync with lat/lng automatically
create or replace function cases_set_geom() returns trigger language plpgsql as $$
begin
if new.latitude is not null and new.longitude is not null then
new.geom := ST_SetSRID(ST_MakePoint(new.longitude, new.latitude), 4326)::geography;
end if;
new.updated_at := now();
return new;
end $$;
drop trigger if exists trg_cases_set_geom on cases;
create trigger trg_cases_set_geom before insert or update on cases
for each row execute function cases_set_geom();
-- 5. Duplicate finder: every case within `radius_m` meters of a point (excluding optional case_id)
create or replace function find_nearby_cases(
p_lat double precision, p_lng double precision,
p_radius_m double precision, p_exclude text default null
) returns table(case_id text, distance_m double precision,
severity_level text, status text, submitted_at timestamptz)
language sql stable as $$
select case_id,
ST_Distance(geom, ST_SetSRID(ST_MakePoint(p_lng, p_lat),4326)::geography) as distance_m,
severity_level, status, submitted_at
from cases
where geom is not null
and (p_exclude is null or case_id <> p_exclude)
and ST_DWithin(geom, ST_SetSRID(ST_MakePoint(p_lng, p_lat),4326)::geography, p_radius_m)
order by distance_m asc;
$$;