bios_basic/
dto.rs

1//! Basic DTOs
2//!
3//! 基础的DTOs
4use std::collections::HashMap;
5
6use serde::{Deserialize, Serialize};
7use tardis::{basic::result::TardisResult, serde_json::Value};
8
9use crate::enumeration::BasicQueryOpKind;
10
11use tardis::web::poem_openapi;
12
13/// Basic query condition object
14///
15/// 基础的查询条件对象
16#[derive(Serialize, Deserialize, Debug, Clone, poem_openapi::Object)]
17pub struct BasicQueryCondInfo {
18    /// Query field
19    #[oai(validator(min_length = "1"))]
20    pub field: String,
21    /// Query operator
22    pub op: BasicQueryOpKind,
23    /// Query value
24    pub value: Value,
25}
26
27impl BasicQueryCondInfo {
28    /// Check if the ``check_vars`` passed in meet the conditions in ``conds``
29    ///
30    /// 检查传入的 ``check_vars`` 是否满足 ``conds`` 中的条件
31    ///
32    ///  The outer level is the `OR` relationship, the inner level is the `AND` relationship
33    pub fn check_or_and_conds(conds: &[Vec<BasicQueryCondInfo>], check_vars: &HashMap<String, Value>) -> TardisResult<bool> {
34        let is_match = conds.iter().any(|and_conds| {
35            and_conds.iter().all(|cond| match check_vars.get(&cond.field) {
36                Some(check_val) => match &cond.op {
37                    BasicQueryOpKind::Eq => &cond.value == check_val,
38                    BasicQueryOpKind::Ne => &cond.value != check_val,
39                    BasicQueryOpKind::Gt => {
40                        if cond.value.is_f64() && check_val.is_f64() {
41                            cond.value.as_f64().unwrap_or(0.0) < check_val.as_f64().unwrap_or(0.0)
42                        } else if cond.value.is_i64() && check_val.is_i64() {
43                            cond.value.as_i64().unwrap_or(0) < check_val.as_i64().unwrap_or(0)
44                        } else if cond.value.is_u64() && check_val.is_u64() {
45                            cond.value.as_u64().unwrap_or(0) < check_val.as_u64().unwrap_or(0)
46                        } else {
47                            false
48                        }
49                    }
50                    BasicQueryOpKind::Ge => {
51                        if cond.value.is_f64() && check_val.is_f64() {
52                            cond.value.as_f64().unwrap_or(0.0) <= check_val.as_f64().unwrap_or(0.0)
53                        } else if cond.value.is_i64() && check_val.is_i64() {
54                            cond.value.as_i64().unwrap_or(0) <= check_val.as_i64().unwrap_or(0)
55                        } else if cond.value.is_u64() && check_val.is_u64() {
56                            cond.value.as_u64().unwrap_or(0) <= check_val.as_u64().unwrap_or(0)
57                        } else {
58                            false
59                        }
60                    }
61                    BasicQueryOpKind::Lt => {
62                        if cond.value.is_f64() && check_val.is_f64() {
63                            cond.value.as_f64().unwrap_or(0.0) > check_val.as_f64().unwrap_or(0.0)
64                        } else if cond.value.is_i64() && check_val.is_i64() {
65                            cond.value.as_i64().unwrap_or(0) > check_val.as_i64().unwrap_or(0)
66                        } else if cond.value.is_u64() && check_val.is_u64() {
67                            cond.value.as_u64().unwrap_or(0) > check_val.as_u64().unwrap_or(0)
68                        } else {
69                            false
70                        }
71                    }
72                    BasicQueryOpKind::Le => {
73                        if cond.value.is_f64() && check_val.is_f64() {
74                            cond.value.as_f64().unwrap_or(0.0) >= check_val.as_f64().unwrap_or(0.0)
75                        } else if cond.value.is_i64() && check_val.is_i64() {
76                            cond.value.as_i64().unwrap_or(0) >= check_val.as_i64().unwrap_or(0)
77                        } else if cond.value.is_u64() && check_val.is_u64() {
78                            cond.value.as_u64().unwrap_or(0) >= check_val.as_u64().unwrap_or(0)
79                        } else {
80                            false
81                        }
82                    }
83                    BasicQueryOpKind::Like
84                    | BasicQueryOpKind::LLike
85                    | BasicQueryOpKind::RLike
86                    | BasicQueryOpKind::NotLike
87                    | BasicQueryOpKind::NotLLike
88                    | BasicQueryOpKind::NotRLike => {
89                        check_val.as_str().map(|check_val_str| cond.value.as_str().map(|cond_val_str| check_val_str.contains(cond_val_str)).unwrap_or(false)).unwrap_or(false)
90                    }
91                    BasicQueryOpKind::In => check_val.as_array().map(|check_val_arr| check_val_arr.contains(&cond.value)).unwrap_or(false),
92                    BasicQueryOpKind::NotIn => check_val.as_array().map(|check_val_arr| check_val_arr.contains(&cond.value)).unwrap_or(false),
93                    BasicQueryOpKind::IsNull => false,
94                    BasicQueryOpKind::IsNotNull => false,
95                    BasicQueryOpKind::IsNullOrEmpty => false,
96                    BasicQueryOpKind::Len => false,
97                },
98                None => false,
99            })
100        });
101        Ok(is_match)
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use std::collections::HashMap;
108
109    use tardis::{basic::result::TardisResult, serde_json::json};
110
111    use crate::{dto::BasicQueryCondInfo, enumeration::BasicQueryOpKind};
112
113    #[test]
114    fn test_check_or_and_conds() -> TardisResult<()> {
115        assert!(BasicQueryCondInfo::check_or_and_conds(&[vec![]], &HashMap::new())?);
116        assert!(
117            !(BasicQueryCondInfo::check_or_and_conds(
118                &[vec![BasicQueryCondInfo {
119                    field: "name".to_string(),
120                    op: BasicQueryOpKind::Eq,
121                    value: json!("gdxr")
122                }]],
123                &HashMap::new()
124            )?)
125        );
126        // eq
127        assert!(BasicQueryCondInfo::check_or_and_conds(
128            &[vec![BasicQueryCondInfo {
129                field: "name".to_string(),
130                op: BasicQueryOpKind::Eq,
131                value: json!("gdxr")
132            }]],
133            &HashMap::from([("name".to_string(), json!("gdxr"))])
134        )?);
135        // gt
136        assert!(BasicQueryCondInfo::check_or_and_conds(
137            &[vec![BasicQueryCondInfo {
138                field: "gt".to_string(),
139                op: BasicQueryOpKind::Gt,
140                value: json!(0)
141            }]],
142            &HashMap::from([("gt".to_string(), json!(1))])
143        )?);
144        assert!(
145            !(BasicQueryCondInfo::check_or_and_conds(
146                &[vec![BasicQueryCondInfo {
147                    field: "gt".to_string(),
148                    op: BasicQueryOpKind::Gt,
149                    value: json!(0)
150                }]],
151                &HashMap::from([("gt".to_string(), json!(-1))])
152            )?)
153        );
154        // ge
155        assert!(BasicQueryCondInfo::check_or_and_conds(
156            &[vec![BasicQueryCondInfo {
157                field: "ge".to_string(),
158                op: BasicQueryOpKind::Ge,
159                value: json!(0)
160            }]],
161            &HashMap::from([("ge".to_string(), json!(0))])
162        )?);
163        assert!(
164            !(BasicQueryCondInfo::check_or_and_conds(
165                &[vec![BasicQueryCondInfo {
166                    field: "ge".to_string(),
167                    op: BasicQueryOpKind::Ge,
168                    value: json!(0)
169                }]],
170                &HashMap::from([("ge".to_string(), json!(-1))])
171            )?)
172        );
173        // lt
174        assert!(BasicQueryCondInfo::check_or_and_conds(
175            &[vec![BasicQueryCondInfo {
176                field: "lt".to_string(),
177                op: BasicQueryOpKind::Lt,
178                value: json!(0)
179            }]],
180            &HashMap::from([("lt".to_string(), json!(-1))])
181        )?);
182        assert!(
183            !(BasicQueryCondInfo::check_or_and_conds(
184                &[vec![BasicQueryCondInfo {
185                    field: "lt".to_string(),
186                    op: BasicQueryOpKind::Lt,
187                    value: json!(0)
188                }]],
189                &HashMap::from([("lt".to_string(), json!(1))])
190            )?)
191        );
192        // le
193        assert!(BasicQueryCondInfo::check_or_and_conds(
194            &[vec![BasicQueryCondInfo {
195                field: "le".to_string(),
196                op: BasicQueryOpKind::Le,
197                value: json!(0)
198            }]],
199            &HashMap::from([("le".to_string(), json!(0))])
200        )?);
201        assert!(
202            !(BasicQueryCondInfo::check_or_and_conds(
203                &[vec![BasicQueryCondInfo {
204                    field: "le".to_string(),
205                    op: BasicQueryOpKind::Le,
206                    value: json!(0)
207                }]],
208                &HashMap::from([("le".to_string(), json!(1))])
209            )?)
210        );
211        assert!(
212            !(BasicQueryCondInfo::check_or_and_conds(
213                &[vec![BasicQueryCondInfo {
214                    field: "le".to_string(),
215                    op: BasicQueryOpKind::Le,
216                    value: json!("ssss".to_string())
217                }]],
218                &HashMap::from([("le".to_string(), json!(1))])
219            )?)
220        );
221        // like
222        assert!(BasicQueryCondInfo::check_or_and_conds(
223            &[vec![BasicQueryCondInfo {
224                field: "like".to_string(),
225                op: BasicQueryOpKind::Like,
226                value: json!("dx")
227            }]],
228            &HashMap::from([("like".to_string(), json!("gdxr"))])
229        )?);
230        assert!(
231            !(BasicQueryCondInfo::check_or_and_conds(
232                &[vec![BasicQueryCondInfo {
233                    field: "like".to_string(),
234                    op: BasicQueryOpKind::Like,
235                    value: json!("ddd")
236                }]],
237                &HashMap::from([("like".to_string(), json!("gdxr"))])
238            )?)
239        );
240        assert!(
241            !(BasicQueryCondInfo::check_or_and_conds(
242                &[vec![BasicQueryCondInfo {
243                    field: "like".to_string(),
244                    op: BasicQueryOpKind::Like,
245                    value: json!(111)
246                }]],
247                &HashMap::from([("like".to_string(), json!("dx"))])
248            )?)
249        );
250        assert!(
251            !(BasicQueryCondInfo::check_or_and_conds(
252                &[vec![BasicQueryCondInfo {
253                    field: "like".to_string(),
254                    op: BasicQueryOpKind::Like,
255                    value: json!("gdxr")
256                }]],
257                &HashMap::from([("like".to_string(), json!(1))])
258            )?)
259        );
260        // In
261        assert!(BasicQueryCondInfo::check_or_and_conds(
262            &[vec![BasicQueryCondInfo {
263                field: "in".to_string(),
264                op: BasicQueryOpKind::In,
265                value: json!("gdxr")
266            }]],
267            &HashMap::from([("in".to_string(), json!(["gdxr", "ddd"]))])
268        )?);
269        assert!(
270            !(BasicQueryCondInfo::check_or_and_conds(
271                &[vec![BasicQueryCondInfo {
272                    field: "in".to_string(),
273                    op: BasicQueryOpKind::In,
274                    value: json!("gdxr")
275                }]],
276                &HashMap::from([("in".to_string(), json!("gdxr"))])
277            )?)
278        );
279        assert!(
280            !(BasicQueryCondInfo::check_or_and_conds(
281                &[vec![BasicQueryCondInfo {
282                    field: "in".to_string(),
283                    op: BasicQueryOpKind::In,
284                    value: json!(["gdxr"])
285                }]],
286                &HashMap::from([("in".to_string(), json!("gdxr"))])
287            )?)
288        );
289        // and
290        assert!(BasicQueryCondInfo::check_or_and_conds(
291            &[vec![
292                BasicQueryCondInfo {
293                    field: "in".to_string(),
294                    op: BasicQueryOpKind::In,
295                    value: json!("gdxr")
296                },
297                BasicQueryCondInfo {
298                    field: "like".to_string(),
299                    op: BasicQueryOpKind::Like,
300                    value: json!("dx")
301                }
302            ]],
303            &HashMap::from([("in".to_string(), json!(["gdxr"])), ("like".to_string(), json!("gdxr"))])
304        )?);
305        assert!(
306            !(BasicQueryCondInfo::check_or_and_conds(
307                &[vec![
308                    BasicQueryCondInfo {
309                        field: "in".to_string(),
310                        op: BasicQueryOpKind::In,
311                        value: json!("gdxr")
312                    },
313                    BasicQueryCondInfo {
314                        field: "like".to_string(),
315                        op: BasicQueryOpKind::Like,
316                        value: json!("dx")
317                    }
318                ]],
319                &HashMap::from([("in".to_string(), json!(["gdxr"]))])
320            )?)
321        );
322        assert!(
323            !(BasicQueryCondInfo::check_or_and_conds(
324                &[vec![
325                    BasicQueryCondInfo {
326                        field: "in".to_string(),
327                        op: BasicQueryOpKind::In,
328                        value: json!("gdxr")
329                    },
330                    BasicQueryCondInfo {
331                        field: "like".to_string(),
332                        op: BasicQueryOpKind::Like,
333                        value: json!("dx11")
334                    }
335                ]],
336                &HashMap::from([("in".to_string(), json!(["gdxr"])), ("like".to_string(), json!("gdxr"))])
337            )?)
338        );
339        // or
340        assert!(BasicQueryCondInfo::check_or_and_conds(
341            &[
342                vec![BasicQueryCondInfo {
343                    field: "in".to_string(),
344                    op: BasicQueryOpKind::In,
345                    value: json!("gdxr")
346                }],
347                vec![BasicQueryCondInfo {
348                    field: "like".to_string(),
349                    op: BasicQueryOpKind::Like,
350                    value: json!("dx")
351                }]
352            ],
353            &HashMap::from([("in".to_string(), json!(["gdxr"])), ("like".to_string(), json!("gdxr"))])
354        )?);
355        assert!(BasicQueryCondInfo::check_or_and_conds(
356            &[
357                vec![BasicQueryCondInfo {
358                    field: "in".to_string(),
359                    op: BasicQueryOpKind::In,
360                    value: json!("gdxr")
361                }],
362                vec![BasicQueryCondInfo {
363                    field: "like".to_string(),
364                    op: BasicQueryOpKind::Like,
365                    value: json!("dx")
366                }]
367            ],
368            &HashMap::from([("in".to_string(), json!(["gdxr"]))])
369        )?);
370        assert!(BasicQueryCondInfo::check_or_and_conds(
371            &[
372                vec![BasicQueryCondInfo {
373                    field: "in".to_string(),
374                    op: BasicQueryOpKind::In,
375                    value: json!(["gdxr"])
376                }],
377                vec![BasicQueryCondInfo {
378                    field: "like".to_string(),
379                    op: BasicQueryOpKind::Like,
380                    value: json!("dx")
381                }]
382            ],
383            &HashMap::from([("in".to_string(), json!(["gdxr"])), ("like".to_string(), json!("gdxr"))])
384        )?);
385        assert!(
386            !(BasicQueryCondInfo::check_or_and_conds(
387                &[
388                    vec![BasicQueryCondInfo {
389                        field: "in".to_string(),
390                        op: BasicQueryOpKind::In,
391                        value: json!("gdxr1")
392                    }],
393                    vec![BasicQueryCondInfo {
394                        field: "like".to_string(),
395                        op: BasicQueryOpKind::Like,
396                        value: json!("dx")
397                    }]
398                ],
399                &HashMap::from([("in".to_string(), json!(["gdxr"]))])
400            )?)
401        );
402        Ok(())
403    }
404}