lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

plot.rs (5544B)


      1 use radroots_replica_db_schema::plot::{
      2     IPlotCreate, IPlotCreateResolve, IPlotDelete, IPlotDeleteResolve, IPlotFieldsFilter,
      3     IPlotFindMany, IPlotFindManyResolve, IPlotFindOne, IPlotFindOneResolve, IPlotUpdate,
      4     IPlotUpdateResolve, Plot, PlotQueryBindValues,
      5 };
      6 use radroots_sql_core::error::SqlError;
      7 use radroots_sql_core::{SqlExecutor, utils};
      8 use radroots_types::types::{IError, IResult, IResultList};
      9 use serde_json::Value;
     10 
     11 const TABLE_NAME: &str = "plot";
     12 
     13 pub fn create(
     14     exec: &dyn SqlExecutor,
     15     opts: &IPlotCreate,
     16 ) -> Result<IPlotCreateResolve, IError<SqlError>> {
     17     let field_map = utils::to_object_map(opts).expect("serialize object map");
     18     let id = utils::uuidv4();
     19     let now = utils::time_created_on();
     20     let meta: [(&str, Value); 3] = [
     21         ("id", Value::from(id.clone())),
     22         ("created_at", Value::from(now.clone())),
     23         ("updated_at", Value::from(now.clone())),
     24     ];
     25     let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
     26     let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
     27     let _ = exec.exec(&sql, &params_json)?;
     28     let on = PlotQueryBindValues::Id { id: id.clone() };
     29     let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
     30     Ok(IResult { result })
     31 }
     32 
     33 pub fn find_one(
     34     exec: &dyn SqlExecutor,
     35     opts: &IPlotFindOne,
     36 ) -> Result<IPlotFindOneResolve, IError<SqlError>> {
     37     let result = match opts {
     38         IPlotFindOne::On(args) => find_one_by_on(exec, &args.on)?,
     39     };
     40     Ok(IResult { result })
     41 }
     42 
     43 pub fn find_many(
     44     exec: &dyn SqlExecutor,
     45     opts: &IPlotFindMany,
     46 ) -> Result<IPlotFindManyResolve, IError<SqlError>> {
     47     let results = find_many_filter(exec, &opts.filter)?;
     48     Ok(IResultList { results })
     49 }
     50 
     51 fn find_many_filter(
     52     exec: &dyn SqlExecutor,
     53     filter: &Option<IPlotFieldsFilter>,
     54 ) -> Result<Vec<Plot>, IError<SqlError>> {
     55     let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
     56     let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
     57     let json = exec.query_raw(&sql, &params_json)?;
     58     let rows: Vec<Plot> = utils::parse_json(&json)?;
     59     Ok(rows)
     60 }
     61 
     62 fn find_one_by_on(
     63     exec: &dyn SqlExecutor,
     64     on: &PlotQueryBindValues,
     65 ) -> Result<Option<Plot>, IError<SqlError>> {
     66     let (column, value) = on.to_filter_param();
     67     let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
     68     let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
     69     let json = exec.query_raw(&sql, &params_json)?;
     70     let mut rows: Vec<Plot> = utils::parse_json(&json)?;
     71     Ok(rows.pop())
     72 }
     73 
     74 fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<Plot, IError<SqlError>> {
     75     let params_json =
     76         utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
     77     let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
     78     let json = exec.query_raw(&sql, &params_json)?;
     79     let mut rows: Vec<Plot> = utils::parse_json(&json)?;
     80     rows.pop()
     81         .ok_or(IError::from(SqlError::NotFound(id.to_owned())))
     82 }
     83 
     84 pub fn update(
     85     exec: &dyn SqlExecutor,
     86     opts: &IPlotUpdate,
     87 ) -> Result<IPlotUpdateResolve, IError<SqlError>> {
     88     let mut updates =
     89         utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
     90     if updates.is_empty() {
     91         return Err(IError::from(SqlError::InvalidArgument(String::from(
     92             "no fields to update",
     93         ))));
     94     }
     95     updates.insert(
     96         String::from("updated_at"),
     97         Value::from(utils::time_created_on()),
     98     );
     99     let mut set_parts = Vec::with_capacity(updates.len());
    100     let mut bind_values = Vec::with_capacity(updates.len() + 1);
    101     for (column, value) in updates {
    102         set_parts.push(format!("{column} = ?"));
    103         bind_values.push(utils::to_db_bind_value(&value));
    104     }
    105     let id_for_lookup = match opts.on.primary_key() {
    106         Some(id) => id,
    107         None => {
    108             let found = find_one_by_on(exec, &opts.on)?;
    109             let model = found.ok_or(IError::from(SqlError::NotFound(opts.on.lookup_key())))?;
    110             model.id
    111         }
    112     };
    113     bind_values.push(Value::from(id_for_lookup.clone()));
    114     let sql = format!(
    115         "UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
    116         set_parts.join(", ")
    117     );
    118     let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
    119     let _ = exec.exec(&sql, &params_json)?;
    120     let updated = select_by_id(exec, &id_for_lookup)?;
    121     Ok(IResult { result: updated })
    122 }
    123 
    124 pub fn delete(
    125     exec: &dyn SqlExecutor,
    126     opts: &IPlotDelete,
    127 ) -> Result<IPlotDeleteResolve, IError<SqlError>> {
    128     let id_for_lookup = match opts {
    129         IPlotDelete::On(args) => match args.on.primary_key() {
    130             Some(id) => id,
    131             None => {
    132                 let found = find_one_by_on(exec, &args.on)?;
    133                 let model = found.ok_or(IError::from(SqlError::NotFound(args.on.lookup_key())))?;
    134                 model.id
    135             }
    136         },
    137     };
    138     let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
    139         .expect("serialize bind params");
    140     let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
    141     let outcome = exec.exec(&sql, &params_json)?;
    142     if outcome.changes == 0 {
    143         return Err(IError::from(SqlError::NotFound(id_for_lookup.clone())));
    144     }
    145     Ok(IResult {
    146         result: id_for_lookup,
    147     })
    148 }