|
1 | | -use std::sync::Arc; |
| 1 | +use std::{io, sync::Arc}; |
2 | 2 |
|
| 3 | +use api::get_model_storage; |
3 | 4 | use async_trait::async_trait; |
4 | | -use model::{DevupModel, column::DevupModelColumn}; |
| 5 | +use devup_sql::generate_find_sql_result; |
| 6 | +use inflections::case::to_snake_case; |
| 7 | +use model::{DevupModel, DevupModelFieldType, ObjectFieldNameType, column::DevupModelColumn}; |
5 | 8 | use serde_json::{Map, Value}; |
| 9 | +use sql_utils::generate_where_sql; |
6 | 10 | use sqlx::{Error, MySql, Postgres, Sqlite, Transaction}; |
7 | 11 |
|
8 | 12 | pub enum QueryParams { |
@@ -86,12 +90,117 @@ pub trait DatabaseStrategy: Send + Sync { |
86 | 90 | instance_id: &Map<String, Value>, |
87 | 91 | obj: &Value, |
88 | 92 | tx: &mut DatabaseTransaction, |
89 | | - ) -> Result<SqlResult, Error>; |
| 93 | + ) -> Result<SqlResult, Error> { |
| 94 | + let (fields, values): (Vec<_>, Vec<_>) = obj |
| 95 | + .as_object() |
| 96 | + .ok_or(Error::Protocol("Wrong object".to_string()))? |
| 97 | + .into_iter() |
| 98 | + .filter_map(|(key, value)| { |
| 99 | + if key.starts_with("__devup_") { |
| 100 | + None |
| 101 | + } else { |
| 102 | + Some((to_snake_case(key), value.clone())) |
| 103 | + } |
| 104 | + }) |
| 105 | + .unzip(); |
| 106 | + let q = format!( |
| 107 | + "UPDATE {} SET {} WHERE {}", |
| 108 | + to_snake_case(&model.name), |
| 109 | + fields |
| 110 | + .into_iter() |
| 111 | + .map(|f| format!("{} = ?", f)) |
| 112 | + .collect::<Vec<String>>() |
| 113 | + .join(","), |
| 114 | + generate_where_sql(&Value::Object(instance_id.clone()))? |
| 115 | + ); |
| 116 | + self.execute(&q, &values, Some(tx)) |
| 117 | + .await |
| 118 | + .map_err(|e| Error::Protocol(format!("Update Error {} {} {:?}", e, q, values)))?; |
| 119 | + Ok(SqlResult { |
| 120 | + instance_id: instance_id.clone(), |
| 121 | + instance: obj |
| 122 | + .as_object() |
| 123 | + .ok_or(Error::Protocol("Wrong object".to_string()))? |
| 124 | + .clone(), |
| 125 | + }) |
| 126 | + } |
90 | 127 |
|
91 | 128 | async fn delete_sql( |
92 | 129 | &self, |
93 | 130 | model: Arc<DevupModel>, |
94 | 131 | instance_id: &Map<String, Value>, |
95 | 132 | tx: &mut DatabaseTransaction, |
96 | | - ) -> Result<(), Error>; |
| 133 | + ) -> Result<(), Error> { |
| 134 | + let q = format!( |
| 135 | + "DELETE FROM {} WHERE {}", |
| 136 | + to_snake_case(&model.name), |
| 137 | + generate_where_sql(&Value::Object(instance_id.clone()))? |
| 138 | + ); |
| 139 | + self.execute(&q, &[], Some(tx)) |
| 140 | + .await |
| 141 | + .map_err(|e| Error::Protocol(format!("Delete Error {} {} {:?}", e, q, instance_id)))?; |
| 142 | + Ok(()) |
| 143 | + } |
| 144 | + |
| 145 | + async fn find( |
| 146 | + &self, |
| 147 | + model: &DevupModel, |
| 148 | + tx: Option<&mut DatabaseTransaction>, |
| 149 | + field_name_type: ObjectFieldNameType, |
| 150 | + // option: Option<DevupApiQueryOption>, |
| 151 | + ) -> Result<Vec<Value>, Error> { |
| 152 | + let q = generate_find_sql_result(&model, None, &get_model_storage()); |
| 153 | + let s = &q.to_sql(field_name_type); |
| 154 | + dbg!(s); |
| 155 | + let result = self.fetch_all(s, &[], tx).await?; |
| 156 | + Ok(result |
| 157 | + .into_iter() |
| 158 | + .map(|v| add_instance_id(model, v, field_name_type)) |
| 159 | + .collect::<Result<Vec<_>, _>>()?) |
| 160 | + } |
| 161 | +} |
| 162 | + |
| 163 | +pub fn add_instance_id( |
| 164 | + model: &DevupModel, |
| 165 | + mut obj: Value, |
| 166 | + field_name_type: ObjectFieldNameType, |
| 167 | +) -> Result<Value, io::Error> { |
| 168 | + let _obj = obj |
| 169 | + .as_object_mut() |
| 170 | + .ok_or(io::Error::new(io::ErrorKind::InvalidData, "Not an object"))?; |
| 171 | + // create instance id object |
| 172 | + let instance_id = { |
| 173 | + let mut instance_id = Map::new(); |
| 174 | + |
| 175 | + for field in model.fields.iter() { |
| 176 | + if let DevupModelFieldType::Column(column) = field { |
| 177 | + if column.primary_key { |
| 178 | + instance_id.insert( |
| 179 | + match field_name_type { |
| 180 | + ObjectFieldNameType::SnakeCase => to_snake_case(&column.name), |
| 181 | + // column name is already camel case |
| 182 | + ObjectFieldNameType::CamelCase => column.name.clone(), |
| 183 | + }, |
| 184 | + _obj.get(&match field_name_type { |
| 185 | + ObjectFieldNameType::SnakeCase => to_snake_case(&column.name), |
| 186 | + // column name is already camel case |
| 187 | + ObjectFieldNameType::CamelCase => column.name.clone(), |
| 188 | + }) |
| 189 | + .ok_or(io::Error::new( |
| 190 | + io::ErrorKind::InvalidData, |
| 191 | + "Primary key not found", |
| 192 | + ))? |
| 193 | + .clone(), |
| 194 | + ); |
| 195 | + } |
| 196 | + } |
| 197 | + } |
| 198 | + instance_id |
| 199 | + }; |
| 200 | + |
| 201 | + _obj.insert( |
| 202 | + "__devup_instance_id".to_string(), |
| 203 | + Value::Object(instance_id), |
| 204 | + ); |
| 205 | + Ok(obj) |
97 | 206 | } |
0 commit comments