database_api.rs 24.62 KiB
use crate::api_model::SortOrder;
use crate::error::Error;
use crate::error::ErrorContext;
use crate::error::Result;
use crate::schema::Schema;
use crate::schema::SchemaPropertyType;
use field_count::FieldCount;
use log::debug;
use rusqlite::params;
use rusqlite::types::ToSqlOutput;
use rusqlite::Row;
use rusqlite::Transaction as Tx;
use rusqlite::NO_PARAMS;
use std::collections::HashMap;
use warp::http::StatusCode;
pub type Rowid = i64;
pub type DbTime = i64;
#[derive(FieldCount)]
pub struct ItemBase {
    pub rowid: Rowid,
    pub id: String,
    pub _type: String,
    pub date_created: DbTime,
    pub date_modified: DbTime,
    pub date_server_modified: DbTime,
    pub deleted: bool,
#[allow(clippy::too_many_arguments)]
pub fn insert_item_base(
    tx: &Tx,
    id: &str,
    _type: &str,
    date_created_millis: DbTime,
    date_modified_millis: DbTime,
    date_server_modified_millis: DbTime,
    deleted: bool,
) -> Result<Rowid> {
    let mut stmt = tx
        .prepare_cached(
            "INSERT INTO items (\
            id, \
            type, \
            dateCreated, \
            dateModified, \
            dateServerModified, \
            deleted \
        ) VALUES (?, ?, ?, ?, ?, ?);",
        .context_str("Failed to prepare/compile INSERT statement")?;
    stmt.insert(params![
        id,
        _type,
        date_created_millis,
        date_modified_millis,
        date_server_modified_millis,
        deleted,
    .context_str("Failed to execute insert_item with parameters")
pub fn get_item_base(tx: &Tx, rowid: Rowid) -> Result<Option<ItemBase>> {
    let database_search = DatabaseSearch {
        rowid: Some(rowid),
        id: None,
        _type: None,
        date_server_modified_gte: None,
        date_server_modified_lt: None,
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
deleted: None, sort_order: SortOrder::Asc, _limit: 1, }; let item = search_items(tx, &database_search)?.into_iter().next(); Ok(item) } pub fn get_item_rowid(tx: &Tx, id: &str) -> Result<Option<Rowid>> { let mut stmt = tx.prepare_cached("SELECT rowid FROM items WHERE id = ?;")?; let mut rows = stmt.query_map(params![id], |row| row.get(0))?; if let Some(row) = rows.next() { let rowid: i64 = row?; Ok(Some(rowid)) } else { Ok(None) } } pub struct DatabaseSearch<'a> { pub rowid: Option<Rowid>, pub id: Option<&'a str>, pub _type: Option<&'a str>, pub date_server_modified_gte: Option<DbTime>, pub date_server_modified_lt: Option<DbTime>, pub deleted: Option<bool>, pub sort_order: SortOrder, pub _limit: u64, } fn parse_item_base(row: &Row) -> Result<ItemBase> { Ok(ItemBase { rowid: row.get(0)?, id: row.get(1)?, _type: row.get(2)?, date_created: row.get(3)?, date_modified: row.get(4)?, date_server_modified: row.get(5)?, deleted: row.get(6)?, }) } pub fn search_items(tx: &Tx, query: &DatabaseSearch) -> Result<Vec<ItemBase>> { let mut sql_query = "\ SELECT \ rowid, \ id, \ type, \ dateCreated, \ dateModified, \ dateServerModified, \ deleted \ FROM \ items \ WHERE " .to_string(); let mut params_vec: Vec<ToSqlOutput> = Vec::new(); if let Some(r) = query.rowid { add_sql_param(&mut sql_query, "rowid", &Comparison::Equals); params_vec.push(r.into()); } if let Some(id) = &query.id { add_sql_param(&mut sql_query, "id", &Comparison::Equals); params_vec.push((*id).into()); } if let Some(typ) = &query._type { add_sql_param(&mut sql_query, "type", &Comparison::Equals); params_vec.push((*typ).into()); } if let Some(dt) = query.date_server_modified_gte {