added database

This commit is contained in:
Ide
2025-12-28 19:54:32 +01:00
parent 62996052f2
commit 5c88c876b3
6 changed files with 91 additions and 37 deletions
Generated
+29
View File
@@ -2390,6 +2390,7 @@ dependencies = [
"rocket",
"serde",
"serde_json",
"sqlite",
]
[[package]]
@@ -4913,6 +4914,34 @@ dependencies = [
"pin-utils",
]
[[package]]
name = "sqlite"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f66e9c01a11936154f3910dbba732c01f8b591543bc4d6672bddee79fd9c4783"
dependencies = [
"sqlite3-sys",
]
[[package]]
name = "sqlite3-src"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5b6d3c860886b0a33e69e421796a5f4a27f23597a182c2450f6d7ace5103120"
dependencies = [
"cc",
"pkg-config",
]
[[package]]
name = "sqlite3-sys"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7781d97adc13a1d5081127a9ee29afad8427f3757bd984daf814d8265267039"
dependencies = [
"sqlite3-src",
]
[[package]]
name = "stable-pattern"
version = "0.1.0"
+10 -1
View File
@@ -95,7 +95,15 @@ async fn main() -> Result<(), MagicAnyError> {
let conf2 = conf2.clone();
tokio::spawn(async move {
// TODO: add number to increment
let res = put_list(&item, &ItemData { checked: false }, &conf2).await;
let res = put_list(
&item,
&ItemData {
checked: false,
amount: 1,
},
&conf2,
)
.await;
if let Err(err) = res {
eprintln!("{err:?}");
}
@@ -122,6 +130,7 @@ async fn main() -> Result<(), MagicAnyError> {
&item.name,
&ItemData {
checked: item.checked,
amount: 1,
},
&conf2,
)
+1
View File
@@ -10,5 +10,6 @@ pub struct Item {
pub struct ItemData {
pub checked: bool,
pub amount: i64,
// TODO: add number
}
+1
View File
@@ -8,3 +8,4 @@ rocket = { version = "0.5.1", features = ["json"] }
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.145"
inkopslista-lib = { path = "../lib" }
sqlite = "0.37.0"
+6
View File
@@ -0,0 +1,6 @@
CREATE TABLE
IF NOT EXISTS list (
itemname TEXT NOT NULL PRIMARY KEY,
checked INT NOT NULL, -- actually a boolean
amount INT NOT NULL
) STRICT;
+44 -36
View File
@@ -1,62 +1,70 @@
#[macro_use]
extern crate rocket;
use std::sync::Mutex;
use std::env;
use inkopslista_lib::{Item, ItemData};
use rocket::{serde::json::Json, State};
use serde::{Deserialize, Serialize};
use sqlite::ConnectionThreadSafe;
#[get("/")]
fn index() -> &'static str {
"hello world"
}
// http GET hemma.nubo.sh/api/list/
// response: [
// Item { name: "Mjölk", ItemData { checked: true } }
// ]
#[get("/api/list")]
fn get_list(mock_db: &State<Mutex<MockDb>>) -> Json<Vec<Item>> {
let mock_db = mock_db.lock().unwrap();
Json(mock_db.list.clone())
fn get_list(db: &State<ConnectionThreadSafe>) -> Json<Vec<Item>> {
// TODO errorhandling
let query = "SELECT * FROM list;";
let list = db
.prepare(query)
.unwrap()
.into_iter()
.map(|row| {
let row = row.unwrap();
Item {
name: row.read::<&str, _>("itemname").to_string(),
data: ItemData {
checked: row.read::<i64, _>("checked") > 0,
amount: row.read::<i64, _>("amount"),
},
}
})
.collect();
Json(list)
}
// http PUT hemma.nubo.sh/api/list/mjölk
// body: ItemData {
// checked: true,
// }
#[put("/api/list/<item>", data = "<data>")]
fn put_list(item: &str, data: Json<ItemData>, mock_db: &State<Mutex<MockDb>>) {
println!("{} {:?}", item, data);
let mut mock_db = mock_db.lock().unwrap();
if let Some(item) = mock_db.list.iter_mut().find(|x| x.name == item) {
item.data = data.into_inner()
} else {
mock_db.list.push(Item {
name: item.to_string(),
data: data.into_inner(),
});
}
fn put_list(item: &str, data: Json<ItemData>, db: &State<ConnectionThreadSafe>) {
// TODO: errorhandling
let query =
"INSERT INTO list VALUES(?, ?, ?) ON CONFLICT DO UPDATE SET checked = ?, amount = ?;";
let mut statement = db.prepare(query).unwrap();
let data = data.into_inner();
statement.bind((1, item)).unwrap();
statement.bind((2, data.checked as i64)).unwrap();
statement.bind((3, data.amount)).unwrap();
statement.bind((4, data.checked as i64)).unwrap();
statement.bind((5, data.amount)).unwrap();
while let Ok(sqlite::State::Row) = statement.next() {}
}
#[delete("/api/list/<item>")]
fn delete_item(item: &str, mock_db: &State<Mutex<MockDb>>) {
let mut mock_db = mock_db.lock().unwrap();
if let Some(index) = mock_db.list.iter().position(|x| x.name == item) {
mock_db.list.remove(index);
}
fn delete_item(item: &str, db: &State<ConnectionThreadSafe>) {
// TODO: Eror handling
let query = "DELETE FROM list WHERE itemname = ?";
let mut statement = db.prepare(query).unwrap();
statement.bind((1, item)).unwrap();
while let Ok(sqlite::State::Row) = statement.next() {}
}
#[launch]
fn rocket() -> _ {
let db_path = env::var("DB_PATH").unwrap();
let db = sqlite::Connection::open_thread_safe(db_path).unwrap();
db.execute(include_str!("db/init.sql"))
.expect("unable to initialize database");
rocket::build()
.manage(Mutex::new(MockDb::default()))
.manage(db)
.mount("/", routes![index, get_list, put_list, delete_item])
}
#[derive(Serialize, Deserialize, Default, Debug)]
struct MockDb {
pub list: Vec<Item>,
}