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},
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use rusqlite::Connection;
|
||||
use rusqlite::{CachedStatement, Connection};
|
||||
use tower_http::trace::TraceLayer;
|
||||
use tower_request_id::{RequestId, RequestIdLayer};
|
||||
use tracing::{debug, error, info, info_span};
|
||||
|
|
@ -40,6 +40,53 @@ struct Food {
|
|||
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]
|
||||
async fn main() -> Result<(), std::io::Error> {
|
||||
tracing_subscriber::registry()
|
||||
|
|
@ -60,11 +107,11 @@ async fn main() -> Result<(), std::io::Error> {
|
|||
let db_connecion_str = "./foods.db".to_string();
|
||||
debug!(db_connecion_str, "opening 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");
|
||||
panic!("failed to create tables: {:#?}", e);
|
||||
}
|
||||
let conn = Arc::new(Mutex::new(conn));
|
||||
|
||||
let app = Router::new()
|
||||
.route("/", get(root))
|
||||
|
|
@ -91,7 +138,7 @@ async fn main() -> Result<(), std::io::Error> {
|
|||
}),
|
||||
)
|
||||
.layer(RequestIdLayer)
|
||||
.with_state(conn);
|
||||
.with_state(Arc::new(Mutex::new(conn)));
|
||||
|
||||
let address = "0.0.0.0:3001";
|
||||
let listener = tokio::net::TcpListener::bind(address)
|
||||
|
|
@ -106,13 +153,9 @@ async fn main() -> Result<(), std::io::Error> {
|
|||
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 mut stmt = conn
|
||||
.prepare(
|
||||
"SELECT id, portion, name, kc_per_serving, target_servings, actual_servings, color FROM food",
|
||||
)
|
||||
.unwrap();
|
||||
let mut stmt = PreparedStatements::get_foods(&conn);
|
||||
let foods: Vec<_> = stmt
|
||||
.query_map((), |row| {
|
||||
Ok(Food {
|
||||
|
|
@ -134,15 +177,13 @@ fn get_foods(conn: &Arc<Mutex<Connection>>) -> Vec<Food> {
|
|||
|
||||
fn get_sum(conn: &Arc<Mutex<Connection>>) -> i32 {
|
||||
let conn = conn.lock();
|
||||
let mut stmt = conn
|
||||
.prepare("SELECT SUM(kc_per_serving * actual_servings) as kc FROM food")
|
||||
.unwrap();
|
||||
let mut stmt = PreparedStatements::get_sum(&conn);
|
||||
let sum = stmt.query_one((), |row| row.get(0)).unwrap();
|
||||
debug!(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 sum = get_sum(&conn);
|
||||
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) {
|
||||
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();
|
||||
debug!(id, new_serving_count = new, "increase");
|
||||
}
|
||||
|
||||
fn get_food(conn: &Arc<Mutex<Connection>>, id: i32) -> Food {
|
||||
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
|
||||
.query_one((id,), |row| {
|
||||
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) {
|
||||
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();
|
||||
debug!(id, new_serving_count = new, "decrease");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue