1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
//! 本库为Rust Tiny Orm的辅助宏
extern crate proc_macro;
use TokenStream;
use quote;
use ;
/// 为结构体自动实现TinyOrmDbModel数据库模型
///
/// # 用法
///
/// #[derive(TinyOrm)]
///
/// 本宏定义了如下属性,用于设置数据映射接口和参数
///
/// # 应用于结构体的属性
///
/// 1. #[orm_table_name = "core_user"]
///
/// 可选属性,可设置多个。
///
/// 自定义数据库表名称。
/// 未设置则表名称为结构名称的蛇形命名,
/// 例如:TestUser转换为test_user。
///
/// 2. #[orm_table_name_pref = "core"]
///
/// 可选属性,可设置多个。
///
/// 为自动生成的数据库表名称增加前缀。
/// 例如:TestUser转换为core_test_user.
///
/// 3. #[orm_query]
///
/// 可选属性,可设置多个。
///
/// 生成Self::orm_query_with开头的获取多条记录的查询方法。
///
/// 有三个子属性:
///
/// * name
/// * 生成的函数名称后缀
/// * 如果name设置为tel,实际生成的方法名称为:orm_query_with_tel
/// * sql_where
/// * 数据库select语句的where部分
/// * 可选,未设置则为获取所有记录
/// * args
/// * 生成方法的参数部分定义
/// * 参数数量应与sql_where定义的?参数数量一致
/// * 与实际函数定义的写法一致,如定义2个参数,格式为:arg1:type1,arg2:type2
/// * 实际生成的函数,会自动添加pool: &TinyOrmDbPool
/// * doc
/// * 生成方法的文档说明
///
/// 例如:
///
/// ```ignore
/// #[orm_query(
/// name = "name_and_tel",
/// sql_where = "user.name = ? and mobile_phone = ?",
/// args = "name:&str,mobile_phone:&str",
/// doc = "根据姓名和手机号查询用户",
/// )]
/// 自动生成如下函数:
/// /// 根据姓名和手机号查询用户
/// pub async fn orm_query_with_name_and_tel(pool: &TinyOrmDbPool, name:&str,mobile_phone:&str) ->AnyhowResult<Vec<Self>>{...}
/// ```
///
/// 4. #[orm_update]
///
/// 可选属性,可设置多个。
///
/// 生成Self::orm_update_with开头的将更新记录方法。
///
/// 有三个子属性:
///
/// * name
/// * 生成的函数名称后缀
/// * 如果name设置为tel,实际生成的方法名称为:orm_update_with_tel
/// * sql_set
/// * 数据库update语句的set部分
/// * sql_where
/// * 数据库update语句的where部分
/// * 可选,未设置则为更新所有记录
/// * args
/// * 生成方法的参数部分定义
/// * 与实际函数定义的写法一致,如定义2个参数,格式为:arg1:type1,arg2:type2
/// * 参数数量应与sql_set+sql_where定义的?参数数量一致
/// * 实际生成的函数,会自动添加pool: &TinyOrmDbPool
/// * doc
/// * 生成方法的文档说明
///
/// 例如:
///
/// ```ignore
/// #[orm_update(
/// name = "name_and_tel",
/// sql_set = "user.name = ? ,user.mobile_phone = ?",
/// sql_where = "id = ?",
/// args = "id:u32,name:&str,mobile_phone:&str",
/// doc = "根据id更新姓名和手机号",
/// )]
/// 自动生成如下更新函数:
/// /// 根据id更新姓名和手机号
/// pub async orm_update_with_name_and_tel(pool: &TinyOrmDbPool, name: &str,mobile_phone: &str) -> AnyhowResult<()>{...}
/// ```
///
/// 5. #[orm_delete]
///
/// 可选属性,可设置多个。
///
/// 生成Self::orm_delete_with开头的删除记录方法。
///
///
/// 有三个子属性:
///
/// * name
/// * 生成的函数名称后缀
/// * 如果name设置为tel,实际生成的方法名称为:orm_delete_with_tel
/// * sql_where
/// * 数据库delete语句的where部分
/// * 可选,未设置则为删除所有记录
/// * args
/// * 生成方法的参数部分定义
/// * 参数数量应与sql_where定义的?参数数量一致
/// * 与实际函数定义的写法一致,如定义2个参数,格式为:arg1:type1,arg2:type2
/// * 实际生成的函数,会自动添加pool: &TinyOrmDbPool
/// * doc
/// * 生成方法的文档说明
///
/// 例如:
///
/// ```ignore
/// #[orm_delete(
/// name = "name_and_tel",
/// sql_where = "user.name = ? and mobile_phone = ?"
/// args = "name:&str,mobile_phone:&str",
/// doc = "根据姓名和手机号删除用户"
/// )]
/// 自动生成如下函数:
/// /// 根据姓名和手机号查询用户
/// pub async fn orm_delete_with_name_and_tel(pool: &TinyOrmDbPool, name:&str,mobile_phone:&str) ->AnyhowResult<()>{...}
/// ```
///
/// 6. #[orm_exist]
///
/// 可选属性,可设置多个。
///
/// 生成Self::orm_exist_with开头的删除记录方法。
///
///
/// 有三个子属性:
///
/// * name
/// * 生成的函数名称后缀
/// * 如果name设置为tel,实际生成的方法名称为:orm_exist_with_tel
/// * sql_where
/// * 数据库select语句的where部分
/// * 实际生成的sql为:select count(1) from table_name where sql_where
/// * 可选,未设置则为所有记录
/// * args
/// * 生成方法的参数部分定义
/// * 参数数量应与sql_where定义的?参数数量一致
/// * 与实际函数定义的写法一致,如定义2个参数,格式为:arg1:type1,arg2:type2
/// * 实际生成的函数,会自动添加pool: &TinyOrmDbPool
/// * doc
/// * 生成方法的文档说明
///
/// 例如:
///
/// ```ignore
/// #[orm_exist(
/// name = "id",
/// sql_where = "id = ?"
/// args = "id:u32",
/// doc = "根据id查询记录是否存在"
/// )]
/// 自动生成如下函数:
/// /// 根据id查询记录是否存在
/// pub async fn orm_exist_with_name_and_tel(pool: &TinyOrmDbPool, id: u32) ->AnyhowResult<bool>
/// ```
///
/// # 应用于结构体字段的方法
///
/// 1. #[orm_pk(name="id", auto="true")]
///
/// 至少需要设置1个,可设置多个。
///
/// 设置当前字段为主键字段
///
/// 有两个子属性:
///
/// * name
/// * 设置对应数据库表中的字段名称
/// * 可选属性,如果未设置,数据库中的字段名称和结构体字段名称一致
/// * auto
/// * 设置为true,则标识这是个自动增长的主键,在插入时不设置值
/// * 可选属性
///
/// 该属性会自动生成如下方法:
///
/// 多个主键会自动汇聚为一个方法,并将主键设置为对应的函数方法的参数
///
/// * Self::orm_get_with_pk
/// * 通过主键获取单条记录
/// * 如果设置了多个主键,会将按照字段定义顺序,合并到该方法的参数中
/// * 函数定义
/// * pub async fn orm_get_with_pk(pool: &TinyOrmDbPool,主键字段1:字段类型1,主键字段2:字段类型2,...) -> AnyhowResult<Self>
/// * 结构体字段类型自动转换
/// * Option<T> 自动转换为 T
/// * String 自动转换为 &str
/// * Self::orm_delete_with_pk
/// * 通过主键删除记录
/// * 如果设置了多个主键,会将按照字段定义顺序,合并到该方法的参数中
/// * 函数定义
/// * pub async fn orm_delete_with_pk(pool: &TinyOrmDbPool,主键字段1:字段类型1,主键字段2:字段类型2,...) -> AnyhowResult<()>
/// * 结构体字段类型自动转换
/// * Option<T> 自动转换为 T
/// * String 自动转换为 &str
/// * self::orm_delete
/// * 通过主键删除当前实例在数据库记录
/// * 如果设置了多个主键,会将按照字段定义顺序,合并到该方法的参数中
/// * 函数定义
/// * pub async fn orm_delete(&self,pool: &TinyOrmDbPool) -> AnyhowResult<Self>
/// * Self::orm_exist_with_pk
/// * 通过主键查询记录是否存在
/// * 如果设置了多个主键,会将按照字段定义顺序,合并到该方法的参数中
/// * 函数定义
/// * pub async fn orm_exists_with_pk(pool: &TinyOrmDbPool,主键字段1:字段类型1,主键字段2:字段类型2,...) -> AnyhowResult<bool>
/// * 结构体字段类型自动转换
/// * Option<T> 自动转换为 T
/// * String 自动转换为 &str
/// * Self::orm_exist
/// * 通过主键查询当前实例在数据库记录是否存在
/// * 如果设置了多个主键,会将按照字段定义顺序,合并到该方法的参数中
/// * 函数定义
/// * pub async fn orm_exists_with_pk(&self,pool: &TinyOrmDbPool) -> AnyhowResult<bool>
///
/// # 示例
///
/// ```ignore
/// struct TestUser {
/// #[orm_pk(name="user_id",auto="true")]
/// id:u32,
/// #[orm_pk]
/// tel:String,
/// }
///
/// //以上会自动生成如下方法
/// pub async fn orm_get_with_pk(pool: &TinyOrmDbPool,id:u32,tel:&str) -> AnyhowResult<Self>{...}
/// pub async fn orm_delete_with_pk(pool: &TinyOrmDbPool,id:u32,tel:&str) -> AnyhowResult<()>{...}
/// pub async fn orm_exist_with_pk(pool: &TinyOrmDbPool,id:u32,tel:&str) -> AnyhowResult<bool>{...}
/// pub async fn orm_delete(self,pool: &TinyOrmDbPool) -> AnyhowResult<bool>{...}
/// pub async fn orm_exist(self,pool: &TinyOrmDbPool) -> AnyhowResult<bool>{...}
///
/// ```
///
/// 2. #[orm_join]
///
/// 可选属性,可设置多个。
///
/// 设置对应字段为关联其他表的join字段
///
/// 有六个子属性:
///
/// * name
/// * 设置对应数据库表中的字段名称
/// * 可选属性,如果未设置,数据库中的字段名称和结构体字段名称一致
/// * select_field
/// * 从join表select数据库字段的对应sql语句
/// * 该语句会与结构体自身对应数据库表的字段合并为select的选择字段清单
/// * join
/// * 连接表的join语句
/// * link_id
/// * 字段的rust类型的对应连接字段
/// * 例如,如某结构体User
/// * 其中某一字段定义为:user_type:UserType,设置link_id="id"
/// * 写入User表记录时,会自动读取self.user_type.id为对应数据库字段的值
/// * link_id_type
/// * 连接字段的rust类型
/// * 如以上UserType::id为u32类型,则link_id_type="u32"
/// * skip_method
/// * 是否不自动生成相关join方法
/// * true,则不自动生成
///
/// 如为设置skip_method="true",该属性会自动生成如下方法:
///
/// * Self::orm_query_join_with_字段名称
/// * 使用join字段查询记录
/// * 函数定义
/// * pub async fn orm_query_join_with_字段名称(pool: &TinyOrmDbPool,字段名称:字段类型) -> AnyhowResult<Vec<Self>>
/// * 结构体字段类型自动转换
/// * Option<T> 自动转换为 T
/// * String 自动转换为 &str
/// * Self::orm_query_join_with_字段名称_{link_id名称}
/// * 使用join字段的link_id查询记录
/// * 函数定义
/// * pub async fn orm_query_join_with_字段名称_{link_id名称}(pool: &TinyOrmDbPool,link_id名称:link_id_type名称) -> AnyhowResult<Vec<Self>>
/// * Self::orm_delete_join_with_字段名称
/// * 使用join字段删除记录
/// * 函数定义
/// * pub async fn orm_delete_join_with_字段名称(pool: &TinyOrmDbPool,字段名称:字段类型) -> AnyhowResult<()>
/// * 结构体字段类型自动转换
/// * Option<T> 自动转换为 T
/// * String 自动转换为 &str
/// * Self::orm_delete_join_with_字段名称_{link_id名称}
/// * 使用join字段的link_id删除记录
/// * 函数定义
/// * pub async fn orm_delete_join_with_字段名称_{link_id名称}(pool: &TinyOrmDbPool,link_id名称:link_id_type名称) -> AnyhowResult<()>
/// * self::orm_update_join_with_字段名称
/// * 使用当前实例的对应join字段.link_id保存到数据库中对应字段中
/// * 函数定义
/// * pub async fn orm_update_join_with_字段名称(&self,pool: &TinyOrmDbPool) -> AnyhowResult<()>
///
/// # 示例
///
/// ```
/// struct User {
/// #[orm_join(
/// name="user_type_id",
/// select_field="user_type.name as user_type_name, user_type.template",
/// join="JOIN user_type ON user_type.id = user_type_id",
/// link_id="id",
/// link_id_type="u32",
/// )]
/// user_type:UserType
/// }
/// // 会自动生成如下方法
/// pub async fn orm_query_join_with_user_type(pool: &TinyOrmDbPool,user_type:UserType) -> AnyhowResult<Vec<Self>>{...}
/// pub async fn orm_query_join_with_user_type_id(pool: &TinyOrmDbPool,query_value:u32) -> AnyhowResult<Vec<Self>>{...}
/// pub async fn orm_delete_join_with_user_type(pool: &TinyOrmDbPool,user_type:UserType) -> AnyhowResult<()>{...}
/// pub async fn orm_delete_join_with_user_type_id(pool: &TinyOrmDbPool,query_value:u32) -> AnyhowResult<()>{...}
/// pub async fn orm_update_join_with_user_type(&self,pool: &TinyOrmDbPool) -> AnyhowResult<()>{...}
/// ```
///
/// 3. #[orm_field(name = "custom_table_field_name")]
///
/// 可选属性,可设置多个。
///
/// 设置对应数据库表的字段名称
///
/// 有1个子属性:
///
/// * name
/// * 设置对应数据库表中的字段名称
/// * 可选属性,如果未设置,数据库中的字段名称和结构体字段名称一致
///
/// 4. #[orm_ignore]
///
/// 可选属性,可设置多个。
///
/// 默认情况下,结构体的每个字段均对应一个数据库表字段。
/// 设置该属性后,可忽略对应字段,不对应数据库表的字段名称
///
/// 5. #[orm_update]
///
/// 生成更新数据库中的对应字段值的方法,方法定义如下:
/// pub async fn orm_update_字段名称(&self,pool: &TinyOrmDbPool) ->AnyhowResult<()>
///
/// 6. #[orm_query]
///
/// 生成使用该字段查询数据库记录的方法,方法定义如下:
/// * pub async fn orm_query_with_字段名称(pool: &TinyOrmDbPool,query_value:字段类型) -> AnyhowResult<Vec<Self>>
/// * 结构体字段类型自动转换
/// * Option<T> 自动转换为 T
/// * String 自动转换为 &str
///
/// 7. #[orm_get]
///
/// 生成使用该字段获取单条数据库记录的方法,方法定义如下:
/// * pub async fn orm_get_with_字段名称(pool: &TinyOrmDbPool,query_value:字段类型) -> AnyhowResult<Self>
/// * 结构体字段类型自动转换
/// * Option<T> 自动转换为 T
/// * String 自动转换为 &str
///
/// # 其他自动生成方法
///
/// 1. self.orm_insert方法
///
/// 将当前结构体实例数据插入到数据库表中,用于新增记录的保存
///
/// 方法定义如下:
/// pub async fn orm_insert(&mut self, pool: &TinyOrmDbPool) -> AnyhowResult<()>
///
/// 2. self.orm_update_all方法
///
/// 将当前结构体实例数据更新到数据库表中,用于变更记录的保存
///
/// 方法定义如下:
/// pub async fn orm_update_all(&self,pool: &TinyOrmDbPool) -> AnyhowResult<()>
/// 自动实现TinyOrmQuery trait宏
///
/// 自动实现相关数据库的插入、更新、查询、删除等接口
///
/// 用法如下:
/// #[derive(TinyOrmQuery)]
/// 为请求报文自动实现DbQuery