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
11pub 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 }