use sqlx::{Postgres, Transaction}; use crate::traits::{DbObj, FromSeptaJson}; use crate::septa_json; use libseptastic::stop_schedule::StopSchedule; impl DbObj for StopSchedule { async fn create_table(tx: &mut Transaction<'_, Postgres>) -> anyhow::Result<()> { sqlx::query(" CREATE TABLE IF NOT EXISTS septa_stop_schedules ( route_id TEXT NOT NULL, trip_id TEXT NOT NULL, service_id TEXT NOT NULL, direction_id BIGINT NOT NULL, arrival_time BIGINT NOT NULL, stop_id BIGINT NOT NULL, stop_sequence BIGINT NOT NULL, PRIMARY KEY (trip_id, stop_id), FOREIGN KEY (route_id) REFERENCES septa_routes(id) ON DELETE CASCADE, FOREIGN KEY (stop_id) REFERENCES septa_stops(id) ON DELETE CASCADE ); ") //FOREIGN KEY (route_id, direction_id) REFERENCES septa_directions(route_id, direction_id) ON DELETE CASCADE, .execute(&mut **tx) .await?; sqlx::query(" CREATE INDEX septa_stop_schedule_trip_id_idx ON septa_stop_schedules (trip_id); ").execute(&mut **tx).await?; sqlx::query(" CREATE INDEX septa_stop_schedule_service_id_idx ON septa_stop_schedules (service_id); ").execute(&mut **tx).await?; Ok(()) } async fn insert_many(scheds: Vec, tx: &mut Transaction<'_, Postgres>) -> anyhow::Result<()> { let mut route_ids: Vec = Vec::new(); let mut trip_ids: Vec = Vec::new(); let mut service_ids: Vec = Vec::new(); let mut direction_ids: Vec = Vec::new(); let mut arrival_times: Vec = Vec::new(); let mut stop_ids: Vec = Vec::new(); let mut stop_sequences: Vec = Vec::new(); for sched in scheds { route_ids.push(sched.route_id); trip_ids.push(sched.trip_id); service_ids.push(sched.service_id); direction_ids.push(sched.direction_id); arrival_times.push(sched.arrival_time); stop_ids.push(sched.stop_id); stop_sequences.push(sched.stop_sequence); } sqlx::query(" INSERT INTO septa_stop_schedules ( route_id, trip_id, service_id, direction_id, arrival_time, stop_id, stop_sequence ) SELECT * FROM UNNEST( $1::text[], $2::text[], $3::text[], $4::bigint[], $5::bigint[], $6::bigint[], $7::bigint[] ) ON CONFLICT DO NOTHING ; ") .bind(&route_ids[..]) .bind(&trip_ids[..]) .bind(&service_ids[..]) .bind(&direction_ids[..]) .bind(&arrival_times[..]) .bind(&stop_ids[..]) .bind(&stop_sequences[..]) .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 StopSchedule { fn from_septa_json(json_sched: septa_json::stop_schedule::StopSchedule) -> ::anyhow::Result> { let time_parts: Vec<&str> = json_sched.arrival_time.split(":").collect(); let arrival_time: i64 = { let hour: i64 = time_parts[0].parse::()?; let minute: i64 = time_parts[1].parse::()?; let second: i64 = time_parts[2].parse::()?; (hour*3600) + (minute * 60) + second }; Ok(Box::new(StopSchedule { route_id: json_sched.route_id, trip_id: match json_sched.trip_id{ septa_json::stop_schedule::TripId::RegionalRail(x) => x, septa_json::stop_schedule::TripId::Other(y) => y.to_string() }, stop_name: String::from(""), service_id: json_sched.service_id, // FIXME: Actually get direction direction_id: json_sched.direction_id, arrival_time, stop_id: json_sched.stop_id, stop_sequence: json_sched.stop_sequence })) } }