83 lines
4.7 KiB
MySQL
83 lines
4.7 KiB
MySQL
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
-- Migration 09 — tracksolid.trips Enrichment
|
||
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
-- The polling endpoint jimi.device.track.mileage does not return start/end
|
||
|
|
-- coordinates, fuel, idle, or trip sequence. This migration adds the columns
|
||
|
|
-- needed to enrich every poll-ingested trip from data we already have:
|
||
|
|
-- • start/end coordinates and full route polyline reconstructed from
|
||
|
|
-- position_history at insert time (see ingest_movement_rev.py::poll_trips)
|
||
|
|
-- • reverse-geocoded human-readable addresses (Nominatim)
|
||
|
|
-- • denormalised vehicle_plate so trip displays don't need a join
|
||
|
|
-- • waypoint count for audit / data-quality checks
|
||
|
|
--
|
||
|
|
-- Adds a v_trips_enriched view exposing daily_seq (Nth trip for IMEI on this
|
||
|
|
-- Africa/Nairobi date) — replaces reliance on the device-supplied trip_seq
|
||
|
|
-- which is only populated when the rarely-firing /pushtripreport webhook
|
||
|
|
-- delivers a payload.
|
||
|
|
--
|
||
|
|
-- Run after migration 08. Safe to re-run (ADD COLUMN IF NOT EXISTS,
|
||
|
|
-- CREATE INDEX IF NOT EXISTS, CREATE OR REPLACE VIEW).
|
||
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
|
||
|
|
BEGIN;
|
||
|
|
|
||
|
|
-- ── 1. New columns on tracksolid.trips ──────────────────────────────────────
|
||
|
|
|
||
|
|
ALTER TABLE tracksolid.trips
|
||
|
|
ADD COLUMN IF NOT EXISTS route_geom geometry(LineString, 4326),
|
||
|
|
ADD COLUMN IF NOT EXISTS start_address TEXT,
|
||
|
|
ADD COLUMN IF NOT EXISTS end_address TEXT,
|
||
|
|
ADD COLUMN IF NOT EXISTS vehicle_plate TEXT,
|
||
|
|
ADD COLUMN IF NOT EXISTS waypoints_count INTEGER;
|
||
|
|
|
||
|
|
COMMENT ON COLUMN tracksolid.trips.route_geom IS
|
||
|
|
'Full GPS route polyline built at ingest from position_history points '
|
||
|
|
'where gps_time BETWEEN start_time AND end_time. NULL when fewer than '
|
||
|
|
'2 fixes are available for the trip window.';
|
||
|
|
COMMENT ON COLUMN tracksolid.trips.start_address IS
|
||
|
|
'Reverse-geocoded human-readable address near start_geom (Nominatim). '
|
||
|
|
'NULL on lookup failure; address is best-effort, not authoritative.';
|
||
|
|
COMMENT ON COLUMN tracksolid.trips.end_address IS
|
||
|
|
'Reverse-geocoded human-readable address near end_geom (Nominatim). '
|
||
|
|
'NULL on lookup failure; address is best-effort, not authoritative.';
|
||
|
|
COMMENT ON COLUMN tracksolid.trips.vehicle_plate IS
|
||
|
|
'Denormalised tracksolid.devices.vehicle_number cached at trip-insert '
|
||
|
|
'time. Avoids a join for trip displays; refreshed only on next ingest.';
|
||
|
|
COMMENT ON COLUMN tracksolid.trips.waypoints_count IS
|
||
|
|
'Number of position_history fixes that contributed to route_geom. '
|
||
|
|
'Audit aid: 0 or 1 means route_geom is NULL or degenerate.';
|
||
|
|
|
||
|
|
-- ── 2. Spatial indexes for replay / map queries ─────────────────────────────
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_trips_route_geom
|
||
|
|
ON tracksolid.trips USING GIST (route_geom);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_trips_start_geom
|
||
|
|
ON tracksolid.trips USING GIST (start_geom);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_trips_end_geom
|
||
|
|
ON tracksolid.trips USING GIST (end_geom);
|
||
|
|
|
||
|
|
-- ── 3. v_trips_enriched view ────────────────────────────────────────────────
|
||
|
|
-- Adds trip_date_eat (Africa/Nairobi local date) and daily_seq (Nth trip on
|
||
|
|
-- that date for the IMEI) without depending on the device-supplied trip_seq.
|
||
|
|
|
||
|
|
CREATE OR REPLACE VIEW tracksolid.v_trips_enriched AS
|
||
|
|
SELECT
|
||
|
|
t.*,
|
||
|
|
(t.start_time AT TIME ZONE 'Africa/Nairobi')::date AS trip_date_eat,
|
||
|
|
ROW_NUMBER() OVER (
|
||
|
|
PARTITION BY t.imei, (t.start_time AT TIME ZONE 'Africa/Nairobi')::date
|
||
|
|
ORDER BY t.start_time
|
||
|
|
) AS daily_seq
|
||
|
|
FROM tracksolid.trips t;
|
||
|
|
|
||
|
|
COMMENT ON VIEW tracksolid.v_trips_enriched IS
|
||
|
|
'tracksolid.trips with computed daily_seq (Nth trip per IMEI per local '
|
||
|
|
'Africa/Nairobi day) and trip_date_eat. Replaces reliance on the '
|
||
|
|
'device-supplied trip_seq column, which is NULL for poll-ingested trips.';
|
||
|
|
|
||
|
|
-- ── 4. Read access for grafana_ro ───────────────────────────────────────────
|
||
|
|
|
||
|
|
GRANT SELECT ON tracksolid.v_trips_enriched TO grafana_ro;
|
||
|
|
|
||
|
|
COMMIT;
|