sqlx_model/curd/
insert.rs

1use super::{
2    DbType, FieldItem, ModelTableField, ModelTableName, ModelUpdateData, TableFields, Update,
3    UpdateData,
4};
5use sqlx::database::HasArguments;
6use sqlx::query::Query;
7use sqlx::{Arguments, Executor, IntoArguments};
8use sqlx::{Database, Error};
9use std::vec;
10
11/// 插入操作
12pub trait InsertData<'t, DB>
13where
14    DB: Database,
15{
16    fn columns(&self) -> Vec<FieldItem>;
17    fn sqlx_bind<'q>(
18        &'q self,
19        field: &FieldItem,
20        res: Query<'q, DB, <DB as HasArguments<'q>>::Arguments>,
21    ) -> Query<'q, DB, <DB as HasArguments<'q>>::Arguments>;
22    fn sqlx_string(&self, field: &FieldItem) -> Option<String>;
23}
24pub trait ModelInsertData<'t, DB, DT>: ModelTableField<DB> + ModelTableName
25where
26    DT: InsertData<'t, DB>,
27    DB: Database,
28{
29    fn insert_data(&'t self) -> DT;
30}
31
32pub struct Insert<'q, DB, T, DT>
33where
34    T: ModelTableName,
35    DB: Database,
36    DT: InsertData<'q, DB>,
37{
38    pub val: Vec<DT>,
39    pub fields: TableFields,
40    _marker: (
41        std::marker::PhantomData<T>,
42        std::marker::PhantomData<&'q DT>,
43        std::marker::PhantomData<DB>,
44    ),
45}
46impl<'q, DB, T, DT> Insert<'q, DB, T, DT>
47where
48    T: ModelTableName,
49    DT: InsertData<'q, DB>,
50    DB: Database,
51{
52    pub fn new(val: DT) -> Self {
53        let column = val.columns();
54        Self {
55            val: vec![val],
56            fields: TableFields(column),
57            _marker: Default::default(),
58        }
59    }
60    pub fn new_vec(val: Vec<DT>) -> Self {
61        let mut fields = TableFields::new(vec![]);
62        for tmp in val.iter() {
63            fields.marge(&tmp.columns());
64        }
65        Self {
66            val,
67            fields,
68            _marker: Default::default(),
69        }
70    }
71    pub fn model<'t: 'q, MI>(val: &'t MI) -> Self
72    where
73        MI: ModelInsertData<'q, DB, DT>,
74    {
75        let ival = val.insert_data();
76        let column = ival.columns();
77        Self {
78            val: vec![ival],
79            fields: TableFields(column),
80            _marker: Default::default(),
81        }
82    }
83    pub fn model_vec<'t: 'q, MI>(val: &'t Vec<MI>) -> Self
84    where
85        MI: ModelInsertData<'q, DB, DT>,
86    {
87        let mut vals = vec![];
88        let mut fields = TableFields::new(vec![]);
89        for tmp in val {
90            let ival = tmp.insert_data();
91            fields.marge(&ival.columns());
92            vals.push(ival);
93        }
94        Self {
95            val: vals,
96            fields,
97            _marker: Default::default(),
98        }
99    }
100    pub fn sql_param(&self) -> Vec<String> {
101        let mut values = Vec::<String>::with_capacity(self.val.len());
102        for (gid, _) in self.val.iter().enumerate() {
103            let len = self.fields.0.len();
104            let mut value = Vec::with_capacity(len);
105            for i in 0..len {
106                let pos = gid * len + i;
107                let str = DbType::type_new::<DB>().mark(pos);
108                value.push(str);
109            }
110            let val: String = value.join(",");
111            let val = "(".to_string() + val.as_str() + ")";
112            values.push(val);
113        }
114        values
115    }
116    pub fn sql_values(&self) -> Vec<String> {
117        let mut values = Vec::<String>::with_capacity(self.val.len());
118        for val in self.val.iter() {
119            let mut value = Vec::with_capacity(self.fields.0.len());
120            for field in &self.fields.0 {
121                if let Some(ival) = val.sqlx_string(field) {
122                    value.push(ival);
123                }
124            }
125            let val: String = value.join(",");
126            let val = "(".to_string() + val.as_str() + ")";
127            values.push(val);
128        }
129        values
130    }
131    pub fn bind_values<'t>(
132        &'t self,
133        mut res: Query<'t, DB, <DB as HasArguments<'t>>::Arguments>,
134    ) -> Query<'t, DB, <DB as HasArguments<'t>>::Arguments> {
135        for val in self.val.iter() {
136            for field in &self.fields.0 {
137                res = val.sqlx_bind(field, res);
138            }
139        }
140        res
141    }
142    #[cfg(feature = "sqlx-postgres")]
143    pub async fn execute_return<'c, E>(
144        self,
145        executor: E,
146        filed: &str,
147    ) -> Result<<DB as Database>::Row, Error>
148    where
149        for<'n> <DB as HasArguments<'n>>::Arguments: Arguments<'n> + IntoArguments<'n, DB>,
150        E: Executor<'c, Database = DB>,
151    {
152        let table = T::table_name();
153        let vals = self.sql_param();
154        let sql = format!(
155            "INSERT INTO {} ({})VALUES {} RETURNING {}",
156            table.full_name(),
157            self.fields.to_vec().join(","),
158            vals.join(","),
159            filed
160        );
161        let mut res = sqlx::query(sql.as_str());
162        res = self.bind_values(res);
163        executor.fetch_one(res).await
164    }
165    pub async fn execute<'c, E>(self, executor: E) -> Result<<DB as Database>::QueryResult, Error>
166    where
167        for<'n> <DB as HasArguments<'n>>::Arguments: Arguments<'n> + IntoArguments<'n, DB>,
168        E: Executor<'c, Database = DB>,
169    {
170        let table = T::table_name();
171        let vals = self.sql_param();
172        let sql = format!(
173            "INSERT INTO {} ({})VALUES {}",
174            table.full_name(),
175            self.fields.to_vec().join(","),
176            vals.join(",")
177        );
178        let mut res = sqlx::query(sql.as_str());
179        res = self.bind_values(res);
180        executor.execute(res).await
181    }
182    #[cfg(feature = "sqlx-mysql")]
183    pub async fn execute_update<'c, 't, CT, IT, E>(
184        self,
185        update: &Update<'t, DB, IT, CT>,
186        executor: E,
187    ) -> Result<<DB as Database>::QueryResult, Error>
188    where
189        IT: ModelUpdateData<'t, DB, CT>,
190        CT: UpdateData<'t, DB>,
191        for<'n> <DB as HasArguments<'n>>::Arguments: Arguments<'n> + IntoArguments<'n, DB>,
192        E: Executor<'c, Database = DB>,
193    {
194        let table = T::table_name();
195        let vals = self.sql_param();
196        let sql = format!(
197            "INSERT INTO {} ({})VALUES {} ON DUPLICATE KEY UPDATE {}",
198            table.full_name(),
199            self.fields.to_vec().join(","),
200            vals.join(","),
201            update.sql_sets()
202        );
203        let mut res = sqlx::query(sql.as_str());
204        res = self.bind_values(res);
205        res = update.bind_values(res);
206        executor.execute(res).await
207    }
208    //  execute_by_sql!(Insert<DB,T,DT>);
209}