66 lines
2 KiB
MySQL
66 lines
2 KiB
MySQL
|
|
-- 004_trips_for_range_rpc.sql
|
||
|
|
-- Multi-day variant of trips_for_day. The 14-day cap is enforced here in SQL
|
||
|
|
-- so PostgREST can't be tricked into asking for an absurd range via direct RPC.
|
||
|
|
|
||
|
|
CREATE OR REPLACE FUNCTION public.trips_for_range(
|
||
|
|
p_start date,
|
||
|
|
p_end date,
|
||
|
|
p_cost_centres text[] DEFAULT NULL
|
||
|
|
) RETURNS TABLE (
|
||
|
|
trip_id bigint,
|
||
|
|
imei text,
|
||
|
|
vehicle_name text,
|
||
|
|
vehicle_number text,
|
||
|
|
cost_centre text,
|
||
|
|
start_time timestamptz,
|
||
|
|
end_time timestamptz,
|
||
|
|
distance_km numeric,
|
||
|
|
path_geojson json,
|
||
|
|
timestamps_rel int[]
|
||
|
|
)
|
||
|
|
LANGUAGE plpgsql STABLE
|
||
|
|
SECURITY DEFINER
|
||
|
|
SET search_path = public, tracksolid
|
||
|
|
AS $$
|
||
|
|
BEGIN
|
||
|
|
IF p_start IS NULL OR p_end IS NULL OR p_end < p_start THEN
|
||
|
|
RAISE EXCEPTION 'Invalid date range: p_start=%, p_end=%', p_start, p_end;
|
||
|
|
END IF;
|
||
|
|
IF (p_end - p_start) > 13 THEN
|
||
|
|
RAISE EXCEPTION 'Range too large: max 14 days, got %', (p_end - p_start + 1);
|
||
|
|
END IF;
|
||
|
|
|
||
|
|
RETURN QUERY
|
||
|
|
WITH range_trips AS (
|
||
|
|
SELECT v.*
|
||
|
|
FROM public.trips_viz_v1 v
|
||
|
|
WHERE v.start_time::date BETWEEN p_start AND p_end
|
||
|
|
AND (p_cost_centres IS NULL OR v.cost_centre = ANY(p_cost_centres))
|
||
|
|
)
|
||
|
|
SELECT
|
||
|
|
rt.trip_id,
|
||
|
|
rt.imei,
|
||
|
|
rt.vehicle_name,
|
||
|
|
rt.vehicle_number,
|
||
|
|
rt.cost_centre,
|
||
|
|
rt.start_time,
|
||
|
|
rt.end_time,
|
||
|
|
rt.distance_km,
|
||
|
|
ST_AsGeoJSON(ST_MakeLine(ph.geom ORDER BY ph.gps_time))::json AS path_geojson,
|
||
|
|
array_agg(
|
||
|
|
EXTRACT(EPOCH FROM ph.gps_time - rt.start_time)::int
|
||
|
|
ORDER BY ph.gps_time
|
||
|
|
) AS timestamps_rel
|
||
|
|
FROM range_trips rt
|
||
|
|
JOIN tracksolid.position_history ph
|
||
|
|
ON ph.imei = rt.imei
|
||
|
|
AND ph.gps_time BETWEEN rt.start_time AND rt.end_time
|
||
|
|
AND ph.geom IS NOT NULL
|
||
|
|
GROUP BY rt.trip_id, rt.imei, rt.vehicle_name, rt.vehicle_number,
|
||
|
|
rt.cost_centre, rt.start_time, rt.end_time, rt.distance_km
|
||
|
|
HAVING count(ph.geom) >= 2;
|
||
|
|
END;
|
||
|
|
$$;
|
||
|
|
|
||
|
|
GRANT EXECUTE ON FUNCTION public.trips_for_range(date, date, text[]) TO viz_anon;
|