Merge branch '28-db-lib' into develop

pull/35/head
Jef Roosens 2021-04-17 23:29:26 +02:00
commit 5b0e595253
Signed by: Jef Roosens
GPG Key ID: B580B976584B5F30
14 changed files with 72 additions and 12 deletions

View File

@ -19,6 +19,14 @@ test = true
bench = true bench = true
doc = true doc = true
doctest = true doctest = true
[[bin]]
name = "populate_ivago"
path = "src/populate_ivago.rs"
test = false
bench = false
doc = false
doctest = false
[dependencies] [dependencies]
rocket = "0.4.7" rocket = "0.4.7"

View File

@ -2,4 +2,4 @@
# see diesel.rs/guides/configuring-diesel-cli # see diesel.rs/guides/configuring-diesel-cli
[print_schema] [print_schema]
file = "src/schema.rs" file = "src/fej/schema.rs"

View File

@ -1,2 +1,2 @@
-- This file should undo anything in `up.sql` -- This file should undo anything in `up.sql`
DROP SCHEMA ivago CASCADE; DROP table ivago_streets;

View File

@ -1,7 +1,4 @@
-- Your SQL goes here CREATE TABLE ivago_streets (
CREATE SCHEMA ivago;
CREATE TABLE ivago.streets (
name TEXT NOT NULL, name TEXT NOT NULL,
city TEXT NOT NULL, city TEXT NOT NULL,

View File

@ -8,6 +8,7 @@ use rocket::http::Status;
pub enum FejError { pub enum FejError {
InvalidArgument, InvalidArgument,
FailedRequest, FailedRequest,
DatabaseError,
} }
// I'd love to move this over to the server binary, but right now, error E0117 is making that // I'd love to move this over to the server binary, but right now, error E0117 is making that
@ -17,6 +18,7 @@ impl From<FejError> for Status {
match err { match err {
FejError::InvalidArgument => Status::BadRequest, FejError::InvalidArgument => Status::BadRequest,
FejError::FailedRequest => Status::InternalServerError, FejError::FailedRequest => Status::InternalServerError,
FejError::DatabaseError => Status::InternalServerError,
} }
} }
} }
@ -33,3 +35,9 @@ impl From<chrono::ParseError> for FejError {
FejError::InvalidArgument FejError::InvalidArgument
} }
} }
impl From<diesel::result::Error> for FejError {
fn from(_: diesel::result::Error) -> FejError {
FejError::DatabaseError
}
}

View File

@ -0,0 +1,12 @@
use super::Street;
use crate::errors::FejError;
use crate::schema::ivago_streets::dsl::*;
use diesel::prelude::*;
use diesel::PgConnection;
pub fn search_streets(db_con: &PgConnection, search_term: &str) -> Result<Vec<Street>, FejError> {
Ok(ivago_streets
.filter(name.ilike(format!("%{}%", search_term)))
.or_filter(city.ilike(format!("%{}%", search_term)))
.load(db_con)?)
}

View File

@ -6,6 +6,7 @@ use std::collections::HashMap;
use std::convert::{From, TryFrom}; use std::convert::{From, TryFrom};
mod basic_date; mod basic_date;
pub mod db;
mod pickup_time; mod pickup_time;
mod street; mod street;

View File

@ -1,3 +1,5 @@
use crate::schema::ivago_streets;
use diesel::{Insertable, Queryable};
use regex::Regex; use regex::Regex;
use rocket::http::RawStr; use rocket::http::RawStr;
use rocket::request::FromFormValue; use rocket::request::FromFormValue;
@ -5,6 +7,8 @@ use serde::ser::{Serialize, SerializeStruct, Serializer};
use std::convert::TryFrom; use std::convert::TryFrom;
/// Represents a street in a given city /// Represents a street in a given city
#[derive(Queryable, Insertable)]
#[table_name = "ivago_streets"]
pub struct Street { pub struct Street {
name: String, name: String,
city: String, city: String,

View File

@ -1,7 +1,10 @@
#![feature(proc_macro_hygiene, decl_macro)] #[macro_use]
extern crate diesel;
// Route modules // Route modules
pub mod ivago; pub mod ivago;
// Helper modules // Helper modules
pub mod errors; pub mod errors;
pub mod schema;

View File

@ -0,0 +1,6 @@
table! {
ivago_streets (name, city) {
name -> Text,
city -> Text,
}
}

View File

@ -0,0 +1,19 @@
use diesel::{insert_into, Connection, PgConnection, RunQueryDsl};
use fej::ivago::search_streets;
use fej::schema::ivago_streets::dsl::*;
const ABC: &str = "abcdefghijklmnopqrstuvwxyz";
fn main() {
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let db_conn = PgConnection::establish(&database_url)
.expect(&format!("Error connecting to {}", database_url));
// Doing this linearly is good enough I'd say
for c in ABC.chars() {
if let Ok(streets) = search_streets(&c.to_string()) {
insert_into(ivago_streets).values(streets).execute(&db_conn);
}
}
}

View File

View File

@ -47,7 +47,7 @@ embed_migrations!();
// This defines a connection to the database // This defines a connection to the database
#[database("postgres_fej")] #[database("postgres_fej")]
struct FejDbConn(diesel::PgConnection); pub struct FejDbConn(diesel::PgConnection);
// I'd like to thank Stackoverflow for helping me with this // I'd like to thank Stackoverflow for helping me with this
// https://stackoverflow.com/questions/61047355/how-to-run-diesel-migration-with-rocket-in-production // https://stackoverflow.com/questions/61047355/how-to-run-diesel-migration-with-rocket-in-production
@ -55,7 +55,7 @@ fn run_db_migrations(rocket: Rocket) -> Result<Rocket, Rocket> {
let conn = FejDbConn::get_one(&rocket).expect("database connection"); let conn = FejDbConn::get_one(&rocket).expect("database connection");
match embedded_migrations::run(&*conn) { match embedded_migrations::run(&*conn) {
Ok(()) => Ok(rocket), Ok(()) => Ok(rocket),
Err(e) => Err(rocket), Err(_) => Err(rocket),
} }
} }

View File

@ -1,4 +1,6 @@
use fej::ivago::{get_pickup_times, search_streets, BasicDate, PickupTime, Street}; use crate::FejDbConn;
use fej::ivago::db::search_streets;
use fej::ivago::{get_pickup_times, BasicDate, PickupTime, Street};
use rocket::http::Status; use rocket::http::Status;
use rocket_contrib::json::Json; use rocket_contrib::json::Json;
@ -9,8 +11,8 @@ use rocket_contrib::json::Json;
/// ///
/// * `search_term` - Search term to use to look for streets /// * `search_term` - Search term to use to look for streets
#[get("/search?<q>")] #[get("/search?<q>")]
pub fn route_search_streets(q: String) -> Result<Json<Vec<Street>>, Status> { pub fn route_search_streets(db_conn: FejDbConn, q: String) -> Result<Json<Vec<Street>>, Status> {
Ok(Json(search_streets(q.as_str())?)) Ok(Json(search_streets(&db_conn.0, q.as_str())?))
} }
/// Handles returning of pickup times for a specific address. It returns a list /// Handles returning of pickup times for a specific address. It returns a list