use sqlx::{Postgres, Transaction}; use crate::traits::{DbObj, FromSeptaJson}; use crate::septa_json; use libseptastic::stop::{Stop, StopType}; impl DbObj for Stop { async fn create_table(tx: &mut Transaction<'_, Postgres>) -> anyhow::Result<()> { sqlx::query(" CREATE TYPE septa_stop_type AS ENUM ( 'far_side', 'middle_block_near_side', 'normal' ); ") .execute(&mut **tx) .await?; sqlx::query(" CREATE TABLE IF NOT EXISTS septa_stops ( id BIGINT PRIMARY KEY, name VARCHAR(128) NOT NULL, lat DOUBLE PRECISION NOT NULL, lng DOUBLE PRECISION NOT NULL, stop_type septa_stop_type NOT NULL ); ") .execute(&mut **tx) .await?; Ok(()) } async fn insert_many(stations: Vec, tx: &mut Transaction<'_, Postgres>) -> anyhow::Result<()> { let mut ids: Vec = Vec::new(); let mut names: Vec = Vec::new(); let mut lats: Vec = Vec::new(); let mut lngs: Vec = Vec::new(); let mut stop_types: Vec = Vec::new(); for station in stations { ids.push(station.id); names.push(station.name); lats.push(station.lat); lngs.push(station.lng); stop_types.push(station.stop_type); } sqlx::query(" INSERT INTO septa_stops ( id, name, lat, lng, stop_type ) SELECT * FROM UNNEST( $1::bigint[], $2::text[], $3::double precision[], $4::double precision[], $5::septa_stop_type[] ) ON CONFLICT DO NOTHING ; ") .bind(&ids[..]) .bind(&names[..]) .bind(&lats[..]) .bind(&lngs[..]) .bind(&stop_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 Stop { fn from_septa_json(json_station: septa_json::route_stop::RouteStop) -> ::anyhow::Result> { let mut name = json_station.stop_name; let mut stop_type = StopType::Normal; if let Some(new_name) = name.strip_suffix("- MNBS") { stop_type = StopType::MiddleBlockNearSide; name = new_name.to_string(); } if let Some(new_name) = name.strip_suffix("- FS") { stop_type = StopType::FarSide; name = new_name.to_string(); } Ok(Box::new(Stop { name, id: json_station.stop_id, lat: json_station.stop_lat, lng: json_station.stop_lon, stop_type })) } }