use sqlx::{Postgres, Transaction}; use crate::traits::{DbObj, FromSeptaJson}; use crate::septa_json; use libseptastic::route::{Route, RouteType}; impl DbObj for Route { async fn create_table(tx: &mut Transaction<'_, Postgres>) -> anyhow::Result<()> { sqlx::query(" CREATE TYPE septa_route_type AS ENUM ( 'trolley', 'subway_elevated', 'regional_rail', 'bus', 'trackless_trolley' ); ") .execute(&mut **tx) .await?; sqlx::query(" CREATE TYPE septa_direction_type AS ENUM ( 'northbound', 'southbound', 'eastbound', 'westbound', 'inbound', 'outbound', 'loop' ); ") .execute(&mut **tx) .await?; sqlx::query(" CREATE TABLE IF NOT EXISTS septa_routes ( id VARCHAR(8) PRIMARY KEY, name VARCHAR(64) NOT NULL, short_name VARCHAR(32) NOT NULL, color_hex VARCHAR(6) NOT NULL, route_type septa_route_type NOT NULL ); ") .execute(&mut **tx) .await?; Ok(()) } async fn insert_many(routes: Vec, tx: &mut Transaction<'_, Postgres>) -> anyhow::Result<()> { let mut names = Vec::new(); let mut short_names = Vec::new(); let mut color_hexes = Vec::new(); let mut route_types: Vec = Vec::new(); let mut ids = Vec::new(); for route in routes { ids.push(route.id); names.push(route.name); short_names.push(route.short_name); color_hexes.push(route.color_hex); route_types.push(route.route_type); } sqlx::query(" INSERT INTO septa_routes ( id, name, short_name, color_hex, route_type ) SELECT * FROM UNNEST( $1::text[], $2::text[], $3::text[], $4::text[], $5::septa_route_type[] ); ") .bind(&ids) .bind(&names) .bind(&short_names) .bind(&color_hexes) .bind(&route_types) .execute(&mut **tx) .await?; Ok(()) } async fn insert(&self, tx: &mut Transaction<'_, Postgres>) -> anyhow::Result<()> { Self::insert_many(vec![self.clone()], tx).await?; Ok(()) } } impl FromSeptaJson for RouteType { fn from_septa_json(json_rt: septa_json::route::RouteType) -> ::anyhow::Result> { Ok(Box::new(match json_rt { septa_json::route::RouteType::Trolley => RouteType::Trolley, septa_json::route::RouteType::SubwayElevated => RouteType::SubwayElevated, septa_json::route::RouteType::RegionalRail => RouteType::RegionalRail, septa_json::route::RouteType::Bus => RouteType::Bus, septa_json::route::RouteType::TracklessTrolley => RouteType::TracklessTrolley, })) } } impl FromSeptaJson for Route { fn from_septa_json(json_route: septa_json::route::Route) -> ::anyhow::Result> { Ok(Box::new(Route { name: json_route.route_long_name, short_name: json_route.route_short_name, color_hex: json_route.route_color, route_type: *RouteType::from_septa_json(json_route.route_type)?, id: json_route.route_id, // FIXME: Actually get direction })) } }