From 4ab9b1f1a69d60a970c1b640b01aa8e0db231399 Mon Sep 17 00:00:00 2001 From: Kaiser Dandangi Date: Sun, 10 Nov 2019 23:46:39 -0500 Subject: [PATCH 1/8] scaffolding for query endpoint --- metrix/src/main.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/metrix/src/main.rs b/metrix/src/main.rs index a4f786c..0ad9cc8 100644 --- a/metrix/src/main.rs +++ b/metrix/src/main.rs @@ -27,7 +27,6 @@ fn ping() -> &'static str { "pong" } - #[post("/", data = "")] fn create_metric_route(metric_body: Json) -> Json { let new_metric: NewMetric = metric_body.into_inner(); @@ -41,6 +40,23 @@ fn create_metric_route(metric_body: Json) -> Json { Json(result) } + +use rocket::http::RawStr; + +#[get("/?")] +fn query_metric_route(offset: Option<&RawStr>) -> Json> { + let db_conn = establish_connection(); + let metric_id = offset; + + let results = metrics::table.filter(metrics::id.eq(9)) + .order(metrics::id) + .limit(10) + .load::(&db_conn) + .expect("Error loading metrics"); + + Json(results) +} + fn main() { println!("### Enter the Metrix ###"); let db_conn = establish_connection(); @@ -51,6 +67,6 @@ fn main() { rocket::ignite() .mount("/ping", routes![ping]) - .mount("/metrics", routes![create_metric_route]) + .mount("/metrics", routes![create_metric_route, query_metric_route]) .launch(); } From 3e92b97a07b17e035fa9f926119b2867c9153609 Mon Sep 17 00:00:00 2001 From: Kaiser Dandangi Date: Mon, 11 Nov 2019 00:03:16 -0500 Subject: [PATCH 2/8] filter by greater than id value for offset --- metrix/src/main.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/metrix/src/main.rs b/metrix/src/main.rs index 0ad9cc8..c801dda 100644 --- a/metrix/src/main.rs +++ b/metrix/src/main.rs @@ -21,6 +21,8 @@ use lib::establish_connection; use schema::metrics; use models::*; use rocket_contrib::json::Json; +use rocket::http::RawStr; + #[get("/")] fn ping() -> &'static str { @@ -40,15 +42,17 @@ fn create_metric_route(metric_body: Json) -> Json { Json(result) } - -use rocket::http::RawStr; - #[get("/?")] fn query_metric_route(offset: Option<&RawStr>) -> Json> { let db_conn = establish_connection(); - let metric_id = offset; + let metric_id: i32 = 0; + + // if offset.is_some() { + // metric_id = offset.unwrap().url_decode(); + // } + // https://api.rocket.rs/v0.3/rocket/http/struct.RawStr.html - let results = metrics::table.filter(metrics::id.eq(9)) + let results = metrics::table.filter(metrics::id.gt(metric_id)) .order(metrics::id) .limit(10) .load::(&db_conn) From a23f2c2cb0e461e4da4cb26da4f0592d4ba2c7b2 Mon Sep 17 00:00:00 2001 From: Kaiser Dandangi Date: Mon, 11 Nov 2019 00:09:13 -0500 Subject: [PATCH 3/8] added offset based pagination --- metrix/src/main.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/metrix/src/main.rs b/metrix/src/main.rs index c801dda..a22fd2f 100644 --- a/metrix/src/main.rs +++ b/metrix/src/main.rs @@ -45,12 +45,15 @@ fn create_metric_route(metric_body: Json) -> Json { #[get("/?")] fn query_metric_route(offset: Option<&RawStr>) -> Json> { let db_conn = establish_connection(); - let metric_id: i32 = 0; - - // if offset.is_some() { - // metric_id = offset.unwrap().url_decode(); - // } - // https://api.rocket.rs/v0.3/rocket/http/struct.RawStr.html + let mut metric_id: i32 = 0; + + if offset.is_some() { + let result = offset.unwrap().url_decode(); + // https://api.rocket.rs/v0.3/rocket/http/struct.RawStr.html + if result.is_ok() { + metric_id = result.ok().unwrap().parse().unwrap(); + } + } let results = metrics::table.filter(metrics::id.gt(metric_id)) .order(metrics::id) From 5a4f35e0b24567203f23179a46c98aef1ce0933d Mon Sep 17 00:00:00 2001 From: Kaiser Dandangi Date: Mon, 11 Nov 2019 23:30:23 -0500 Subject: [PATCH 4/8] step 1 for making dynamic query segments --- metrix/src/main.rs | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/metrix/src/main.rs b/metrix/src/main.rs index a22fd2f..a6afcac 100644 --- a/metrix/src/main.rs +++ b/metrix/src/main.rs @@ -22,6 +22,7 @@ use schema::metrics; use models::*; use rocket_contrib::json::Json; use rocket::http::RawStr; +use chrono::naive::NaiveDateTime; #[get("/")] @@ -42,20 +43,45 @@ fn create_metric_route(metric_body: Json) -> Json { Json(result) } -#[get("/?")] -fn query_metric_route(offset: Option<&RawStr>) -> Json> { +#[get("/?&&")] +fn query_metric_route( + offset: Option<&RawStr>, + start_datetime: Option<&RawStr>, + end_datetime: Option<&RawStr>, +) -> Json> { let db_conn = establish_connection(); - let mut metric_id: i32 = 0; + // let mut metric_id: i32 = 0; + // let query = metrics::table.order(metrics::created_at); + let mut query = Box::new(metrics::id.gt(0)); if offset.is_some() { let result = offset.unwrap().url_decode(); // https://api.rocket.rs/v0.3/rocket/http/struct.RawStr.html if result.is_ok() { - metric_id = result.ok().unwrap().parse().unwrap(); + let metric_id: i32 = result.ok().unwrap().parse().unwrap(); + // query = query.filter(Box::new(metrics::id.gt(metric_id))) + query = Box::new(metrics::id.gt(metric_id)); } } - let results = metrics::table.filter(metrics::id.gt(metric_id)) + // if start_datetime.is_some() { + // let result = start_datetime.unwrap().url_decode(); + // if result.is_ok() { + // let created_at_start = result.ok().unwrap().parse().unwrap(); + // let created_at_start = NaiveDateTime::parse_from_str( + // created_at_start, + // "%Y-%m-%dT%H:%M:%S" // "2014-5-17T12:34:56" + // ); + // query = query.filter( + // metrics::created_at.gt(created_at_start) + // ); + // } + // } + + + // metrics::table.filter(metrics::id.gt(metric_id)) + let results = metrics::table + .filter(query) .order(metrics::id) .limit(10) .load::(&db_conn) From a0eeae124b5f5ddc4b55ab773dbf08073e0db9f7 Mon Sep 17 00:00:00 2001 From: Kaiser Dandangi Date: Mon, 11 Nov 2019 23:47:51 -0500 Subject: [PATCH 5/8] dynamically include start_datetime query filter --- metrix/src/main.rs | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/metrix/src/main.rs b/metrix/src/main.rs index a6afcac..a5804c4 100644 --- a/metrix/src/main.rs +++ b/metrix/src/main.rs @@ -52,8 +52,8 @@ fn query_metric_route( let db_conn = establish_connection(); // let mut metric_id: i32 = 0; // let query = metrics::table.order(metrics::created_at); - - let mut query = Box::new(metrics::id.gt(0)); + use diesel::sql_types::Bool; + let mut query: Box> = Box::new(metrics::id.gt(0)); if offset.is_some() { let result = offset.unwrap().url_decode(); // https://api.rocket.rs/v0.3/rocket/http/struct.RawStr.html @@ -64,19 +64,28 @@ fn query_metric_route( } } - // if start_datetime.is_some() { - // let result = start_datetime.unwrap().url_decode(); - // if result.is_ok() { - // let created_at_start = result.ok().unwrap().parse().unwrap(); - // let created_at_start = NaiveDateTime::parse_from_str( - // created_at_start, - // "%Y-%m-%dT%H:%M:%S" // "2014-5-17T12:34:56" - // ); - // query = query.filter( - // metrics::created_at.gt(created_at_start) - // ); - // } - // } + if start_datetime.is_some() { + let result = start_datetime.unwrap().url_decode(); + if result.is_ok() { + let created_at_start = result.ok().unwrap(); + let created_at_start_parsed = NaiveDateTime::parse_from_str( + &created_at_start, // "2019-11-11T01:00:00" + &"%Y-%m-%dT%H:%M:%S".to_string() // "2014-5-17T12:34:56" + ); + + if created_at_start_parsed.is_ok() { + query = Box::new( + query.and( + Box::new( + metrics::created_at.gt( + created_at_start_parsed.ok().unwrap() + ) + ) + ) + ); + } + } + } // metrics::table.filter(metrics::id.gt(metric_id)) From bf8ab567bc772090f3de9341f0d3b4adce014b7a Mon Sep 17 00:00:00 2001 From: Kaiser Dandangi Date: Tue, 12 Nov 2019 23:48:41 -0500 Subject: [PATCH 6/8] dynamically include end_datetime query filter --- metrix/src/main.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/metrix/src/main.rs b/metrix/src/main.rs index a5804c4..766972d 100644 --- a/metrix/src/main.rs +++ b/metrix/src/main.rs @@ -58,8 +58,8 @@ fn query_metric_route( let result = offset.unwrap().url_decode(); // https://api.rocket.rs/v0.3/rocket/http/struct.RawStr.html if result.is_ok() { - let metric_id: i32 = result.ok().unwrap().parse().unwrap(); - // query = query.filter(Box::new(metrics::id.gt(metric_id))) + let metric_id_str: String = result.ok().unwrap(); + let metric_id: i32 = metric_id_str.parse().unwrap(); query = Box::new(metrics::id.gt(metric_id)); } } @@ -87,8 +87,29 @@ fn query_metric_route( } } + if end_datetime.is_some() { + let result = end_datetime.unwrap().url_decode(); + if result.is_ok() { + let created_at_end = result.ok().unwrap(); + let created_at_end_parsed = NaiveDateTime::parse_from_str( + &created_at_end, // "2019-11-11T01:00:00" + &"%Y-%m-%dT%H:%M:%S".to_string() // "2014-5-17T12:34:56" + ); + + if created_at_end_parsed.is_ok() { + query = Box::new( + query.and( + Box::new( + metrics::created_at.lt( + created_at_end_parsed.ok().unwrap() + ) + ) + ) + ); + } + } + } - // metrics::table.filter(metrics::id.gt(metric_id)) let results = metrics::table .filter(query) .order(metrics::id) From e840fef1aa9e8ae3b3737b55706798b8b6431eef Mon Sep 17 00:00:00 2001 From: Kaiser Dandangi Date: Wed, 13 Nov 2019 00:11:03 -0500 Subject: [PATCH 7/8] switch to manual query generation by using QueryableByName --- metrix/src/main.rs | 49 ++++++++++++++++++-------------------------- metrix/src/models.rs | 5 ++--- 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/metrix/src/main.rs b/metrix/src/main.rs index 766972d..0a39fe2 100644 --- a/metrix/src/main.rs +++ b/metrix/src/main.rs @@ -23,6 +23,7 @@ use models::*; use rocket_contrib::json::Json; use rocket::http::RawStr; use chrono::naive::NaiveDateTime; +use diesel::sql_query; #[get("/")] @@ -50,17 +51,17 @@ fn query_metric_route( end_datetime: Option<&RawStr>, ) -> Json> { let db_conn = establish_connection(); - // let mut metric_id: i32 = 0; - // let query = metrics::table.order(metrics::created_at); - use diesel::sql_types::Bool; - let mut query: Box> = Box::new(metrics::id.gt(0)); + let mut filter_clause = String::from("WHERE 1=1"); + if offset.is_some() { let result = offset.unwrap().url_decode(); // https://api.rocket.rs/v0.3/rocket/http/struct.RawStr.html if result.is_ok() { let metric_id_str: String = result.ok().unwrap(); - let metric_id: i32 = metric_id_str.parse().unwrap(); - query = Box::new(metrics::id.gt(metric_id)); + filter_clause.insert_str( + filter_clause.len(), + &format!(" AND id > {}", metric_id_str).to_string() + ); } } @@ -69,19 +70,14 @@ fn query_metric_route( if result.is_ok() { let created_at_start = result.ok().unwrap(); let created_at_start_parsed = NaiveDateTime::parse_from_str( - &created_at_start, // "2019-11-11T01:00:00" + &created_at_start, &"%Y-%m-%dT%H:%M:%S".to_string() // "2014-5-17T12:34:56" ); if created_at_start_parsed.is_ok() { - query = Box::new( - query.and( - Box::new( - metrics::created_at.gt( - created_at_start_parsed.ok().unwrap() - ) - ) - ) + filter_clause.insert_str( + filter_clause.len(), + &format!(" AND created_at > '{}'", created_at_start).to_string() ); } } @@ -92,29 +88,24 @@ fn query_metric_route( if result.is_ok() { let created_at_end = result.ok().unwrap(); let created_at_end_parsed = NaiveDateTime::parse_from_str( - &created_at_end, // "2019-11-11T01:00:00" + &created_at_end, &"%Y-%m-%dT%H:%M:%S".to_string() // "2014-5-17T12:34:56" ); if created_at_end_parsed.is_ok() { - query = Box::new( - query.and( - Box::new( - metrics::created_at.lt( - created_at_end_parsed.ok().unwrap() - ) - ) - ) + filter_clause.insert_str( + filter_clause.len(), + &format!(" AND created_at < '{}'", created_at_end).to_string() ); } } } - let results = metrics::table - .filter(query) - .order(metrics::id) - .limit(10) - .load::(&db_conn) + println!("### QUERY: SELECT * FROM metrics {};", filter_clause); + + let query_string = format!("SELECT * FROM metrics {} ORDER BY id LIMIT 10", filter_clause); + let results = sql_query(query_string) + .load(&db_conn) .expect("Error loading metrics"); Json(results) diff --git a/metrix/src/models.rs b/metrix/src/models.rs index f6b5565..309dd9a 100644 --- a/metrix/src/models.rs +++ b/metrix/src/models.rs @@ -2,9 +2,8 @@ use super::schema::metrics; use serde_json; use chrono::naive::NaiveDateTime; -#[derive(Serialize, Deserialize, Queryable)] -// #[table_name="metrics"] -- idk why it throws compile error -// "error: cannot find attribute `table_name` in this scope" ... +#[derive(Serialize, Deserialize, Queryable, QueryableByName)] +#[table_name="metrics"] pub struct Metric { pub id: i32, pub metric_name: String, From 3540c46177b4fb5293cf7144f7bc0dcf8f14359f Mon Sep 17 00:00:00 2001 From: Kaiser Dandangi Date: Wed, 13 Nov 2019 22:50:47 -0500 Subject: [PATCH 8/8] make date ranges inclusive of range --- metrix/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/metrix/src/main.rs b/metrix/src/main.rs index 0a39fe2..31a28f7 100644 --- a/metrix/src/main.rs +++ b/metrix/src/main.rs @@ -77,7 +77,7 @@ fn query_metric_route( if created_at_start_parsed.is_ok() { filter_clause.insert_str( filter_clause.len(), - &format!(" AND created_at > '{}'", created_at_start).to_string() + &format!(" AND created_at >= '{}'", created_at_start).to_string() ); } } @@ -95,7 +95,7 @@ fn query_metric_route( if created_at_end_parsed.is_ok() { filter_clause.insert_str( filter_clause.len(), - &format!(" AND created_at < '{}'", created_at_end).to_string() + &format!(" AND created_at <= '{}'", created_at_end).to_string() ); } }