put sql statements in separate files
This commit is contained in:
parent
1bb63b1fa4
commit
080bb80956
6 changed files with 107 additions and 17 deletions
14
src/decrease.sql
Normal file
14
src/decrease.sql
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
UPDATE
|
||||||
|
food
|
||||||
|
SET
|
||||||
|
actual_servings = MAX(
|
||||||
|
(SELECT
|
||||||
|
actual_servings
|
||||||
|
FROM
|
||||||
|
food
|
||||||
|
WHERE id = ?1) - 1,
|
||||||
|
0)
|
||||||
|
WHERE
|
||||||
|
id = ?1
|
||||||
|
RETURNING
|
||||||
|
actual_servings
|
||||||
12
src/get_food.sql
Normal file
12
src/get_food.sql
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
portion,
|
||||||
|
name,
|
||||||
|
kc_per_serving,
|
||||||
|
target_servings,
|
||||||
|
actual_servings,
|
||||||
|
color
|
||||||
|
FROM
|
||||||
|
food
|
||||||
|
WHERE
|
||||||
|
id = ?1
|
||||||
10
src/get_foods.sql
Normal file
10
src/get_foods.sql
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
portion,
|
||||||
|
name,
|
||||||
|
kc_per_serving,
|
||||||
|
target_servings,
|
||||||
|
actual_servings,
|
||||||
|
color
|
||||||
|
FROM
|
||||||
|
food
|
||||||
4
src/get_sum.sql
Normal file
4
src/get_sum.sql
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
SELECT
|
||||||
|
SUM(kc_per_serving * actual_servings) AS kc
|
||||||
|
FROM
|
||||||
|
food
|
||||||
9
src/increase.sql
Normal file
9
src/increase.sql
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
UPDATE
|
||||||
|
food
|
||||||
|
SET actual_servings = (
|
||||||
|
SELECT actual_servings
|
||||||
|
FROM food
|
||||||
|
WHERE id = ?1
|
||||||
|
) + 1
|
||||||
|
WHERE id = ?1
|
||||||
|
RETURNING actual_servings
|
||||||
75
src/main.rs
75
src/main.rs
|
|
@ -9,7 +9,7 @@ use axum::{
|
||||||
routing::{get, post},
|
routing::{get, post},
|
||||||
};
|
};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use rusqlite::Connection;
|
use rusqlite::{CachedStatement, Connection};
|
||||||
use tower_http::trace::TraceLayer;
|
use tower_http::trace::TraceLayer;
|
||||||
use tower_request_id::{RequestId, RequestIdLayer};
|
use tower_request_id::{RequestId, RequestIdLayer};
|
||||||
use tracing::{debug, error, info, info_span};
|
use tracing::{debug, error, info, info_span};
|
||||||
|
|
@ -40,6 +40,53 @@ struct Food {
|
||||||
color: String,
|
color: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct PreparedStatements {}
|
||||||
|
|
||||||
|
impl<'conn> PreparedStatements {
|
||||||
|
fn check(conn: &Connection) -> rusqlite::Result<Self> {
|
||||||
|
conn.prepare_cached(include_str!("create_tables.sql"))?;
|
||||||
|
conn.prepare_cached(include_str!("increase.sql"))?;
|
||||||
|
conn.prepare_cached(include_str!("decrease.sql"))?;
|
||||||
|
conn.prepare_cached(include_str!("get_food.sql"))?;
|
||||||
|
conn.prepare_cached(include_str!("get_foods.sql"))?;
|
||||||
|
conn.prepare_cached(include_str!("get_sum.sql"))?;
|
||||||
|
Ok(PreparedStatements {})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_tables(conn: &'conn Connection) -> CachedStatement<'conn> {
|
||||||
|
conn.prepare_cached(include_str!("create_tables.sql"))
|
||||||
|
.expect("cached statement is invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn increase(conn: &'conn Connection) -> CachedStatement<'conn> {
|
||||||
|
conn.prepare_cached(include_str!("increase.sql"))
|
||||||
|
.expect("cached statement is invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decrease(conn: &'conn Connection) -> CachedStatement<'conn> {
|
||||||
|
conn.prepare_cached(include_str!("decrease.sql"))
|
||||||
|
.expect("cached statement is invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_food(conn: &'conn Connection) -> CachedStatement<'conn> {
|
||||||
|
conn.prepare_cached(include_str!("get_food.sql"))
|
||||||
|
.expect("cached statement is invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_foods(conn: &'conn Connection) -> CachedStatement<'conn> {
|
||||||
|
conn.prepare_cached(include_str!("get_foods.sql"))
|
||||||
|
.expect("cached statement is invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_sum(conn: &'conn Connection) -> CachedStatement<'conn> {
|
||||||
|
conn.prepare_cached(include_str!("get_sum.sql"))
|
||||||
|
.expect("cached statement is invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConnState = Arc<Mutex<Connection>>;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), std::io::Error> {
|
async fn main() -> Result<(), std::io::Error> {
|
||||||
tracing_subscriber::registry()
|
tracing_subscriber::registry()
|
||||||
|
|
@ -60,11 +107,11 @@ async fn main() -> Result<(), std::io::Error> {
|
||||||
let db_connecion_str = "./foods.db".to_string();
|
let db_connecion_str = "./foods.db".to_string();
|
||||||
debug!(db_connecion_str, "opening database");
|
debug!(db_connecion_str, "opening database");
|
||||||
let conn = Connection::open(db_connecion_str).expect("failed to open database");
|
let conn = Connection::open(db_connecion_str).expect("failed to open database");
|
||||||
if let Err(e) = conn.execute(include_str!("create_tables.sql"), ()) {
|
PreparedStatements::check(&conn).expect("failed to prepare sql statements");
|
||||||
|
if let Err(e) = PreparedStatements::create_tables(&conn).execute(()) {
|
||||||
error!(?e, "failed to create tables");
|
error!(?e, "failed to create tables");
|
||||||
panic!("failed to create tables: {:#?}", e);
|
panic!("failed to create tables: {:#?}", e);
|
||||||
}
|
}
|
||||||
let conn = Arc::new(Mutex::new(conn));
|
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/", get(root))
|
.route("/", get(root))
|
||||||
|
|
@ -91,7 +138,7 @@ async fn main() -> Result<(), std::io::Error> {
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.layer(RequestIdLayer)
|
.layer(RequestIdLayer)
|
||||||
.with_state(conn);
|
.with_state(Arc::new(Mutex::new(conn)));
|
||||||
|
|
||||||
let address = "0.0.0.0:3001";
|
let address = "0.0.0.0:3001";
|
||||||
let listener = tokio::net::TcpListener::bind(address)
|
let listener = tokio::net::TcpListener::bind(address)
|
||||||
|
|
@ -106,13 +153,9 @@ async fn main() -> Result<(), std::io::Error> {
|
||||||
axum::serve(listener, app).await
|
axum::serve(listener, app).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_foods(conn: &Arc<Mutex<Connection>>) -> Vec<Food> {
|
fn get_foods(conn: &ConnState) -> Vec<Food> {
|
||||||
let conn = conn.lock();
|
let conn = conn.lock();
|
||||||
let mut stmt = conn
|
let mut stmt = PreparedStatements::get_foods(&conn);
|
||||||
.prepare(
|
|
||||||
"SELECT id, portion, name, kc_per_serving, target_servings, actual_servings, color FROM food",
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let foods: Vec<_> = stmt
|
let foods: Vec<_> = stmt
|
||||||
.query_map((), |row| {
|
.query_map((), |row| {
|
||||||
Ok(Food {
|
Ok(Food {
|
||||||
|
|
@ -134,15 +177,13 @@ fn get_foods(conn: &Arc<Mutex<Connection>>) -> Vec<Food> {
|
||||||
|
|
||||||
fn get_sum(conn: &Arc<Mutex<Connection>>) -> i32 {
|
fn get_sum(conn: &Arc<Mutex<Connection>>) -> i32 {
|
||||||
let conn = conn.lock();
|
let conn = conn.lock();
|
||||||
let mut stmt = conn
|
let mut stmt = PreparedStatements::get_sum(&conn);
|
||||||
.prepare("SELECT SUM(kc_per_serving * actual_servings) as kc FROM food")
|
|
||||||
.unwrap();
|
|
||||||
let sum = stmt.query_one((), |row| row.get(0)).unwrap();
|
let sum = stmt.query_one((), |row| row.get(0)).unwrap();
|
||||||
debug!(sum);
|
debug!(sum);
|
||||||
sum
|
sum
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn root(State(conn): State<Arc<Mutex<Connection>>>) -> Html<String> {
|
async fn root(State(conn): State<ConnState>) -> Html<String> {
|
||||||
let foods = get_foods(&conn);
|
let foods = get_foods(&conn);
|
||||||
let sum = get_sum(&conn);
|
let sum = get_sum(&conn);
|
||||||
let index = IndexTemplate { foods, sum };
|
let index = IndexTemplate { foods, sum };
|
||||||
|
|
@ -151,14 +192,14 @@ async fn root(State(conn): State<Arc<Mutex<Connection>>>) -> Html<String> {
|
||||||
|
|
||||||
fn do_increase(conn: &Arc<Mutex<Connection>>, id: i32) {
|
fn do_increase(conn: &Arc<Mutex<Connection>>, id: i32) {
|
||||||
let conn = conn.lock();
|
let conn = conn.lock();
|
||||||
let mut stmt = conn.prepare("UPDATE food SET actual_servings = (SELECT actual_servings FROM food WHERE id = ?1) + 1 WHERE id = ?1 RETURNING actual_servings").unwrap();
|
let mut stmt = PreparedStatements::increase(&conn);
|
||||||
let new: i32 = stmt.query_one((id,), |row| row.get(0)).unwrap();
|
let new: i32 = stmt.query_one((id,), |row| row.get(0)).unwrap();
|
||||||
debug!(id, new_serving_count = new, "increase");
|
debug!(id, new_serving_count = new, "increase");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_food(conn: &Arc<Mutex<Connection>>, id: i32) -> Food {
|
fn get_food(conn: &Arc<Mutex<Connection>>, id: i32) -> Food {
|
||||||
let conn = conn.lock();
|
let conn = conn.lock();
|
||||||
let mut stmt = conn.prepare("SELECT id, portion, name, kc_per_serving, target_servings, actual_servings, color FROM food WHERE id = ?1").unwrap();
|
let mut stmt = PreparedStatements::get_food(&conn);
|
||||||
let food = stmt
|
let food = stmt
|
||||||
.query_one((id,), |row| {
|
.query_one((id,), |row| {
|
||||||
Ok(Food {
|
Ok(Food {
|
||||||
|
|
@ -186,7 +227,7 @@ async fn increase(State(conn): State<Arc<Mutex<Connection>>>, Path(id): Path<i32
|
||||||
|
|
||||||
fn do_decrease(conn: &Arc<Mutex<Connection>>, id: i32) {
|
fn do_decrease(conn: &Arc<Mutex<Connection>>, id: i32) {
|
||||||
let conn = conn.lock();
|
let conn = conn.lock();
|
||||||
let mut stmt = conn.prepare("UPDATE food SET actual_servings = MAX((SELECT actual_servings FROM food WHERE id = ?1) - 1, 0) WHERE id = ?1 RETURNING actual_servings").unwrap();
|
let mut stmt = PreparedStatements::decrease(&conn);
|
||||||
let new: i32 = stmt.query_one((id,), |row| row.get(0)).unwrap();
|
let new: i32 = stmt.query_one((id,), |row| row.get(0)).unwrap();
|
||||||
debug!(id, new_serving_count = new, "decrease");
|
debug!(id, new_serving_count = new, "decrease");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue