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
use serde_json::{Value as JsonValue, Result};
use regex::Regex;

#[derive(Debug)]
pub struct NodeWhere {
    condition: JsonValue
}
impl NodeWhere {
    pub fn new(condition: JsonValue) -> Self {
        Self {
            condition
        }
    }
    pub fn to_sql(&self, table_name: &str) -> Result<String> {
        let mut vec = vec![];
        if let JsonValue::Object(map_value) = &self.condition {
            for key in map_value.keys() {
                let column = if Regex::new(r"\.").unwrap().is_match(key) {
                    format!("'{}'", key)
                } else {
                    format!("`{}`.`{}`", table_name, key)
                };
                if let Some(json_value) = map_value.get(key) {
                    match json_value {
                        JsonValue::Array(value) => {
                            let mut values = vec![];
                            for json_value in value.iter() {
                                match json_value {
                                    JsonValue::String(value) => {
                                        values.push(format!("'{}'", value));
                                    },
                                    JsonValue::Number(value) => {
                                        values.push(format!("{}", value));
                                    },
                                    _ => ()
                                }
                            }
                            if values.len() > 0 {
                                vec.push(format!("{} in [{}]", column, values.join(",")));
                            }
                        },
                        JsonValue::String(value) => {
                            vec.push(format!("{} = '{}'", column, value));
                        },
                        JsonValue::Number(value) => {
                            vec.push(format!("{} = {}", column, value));
                        },
                        JsonValue::Bool(value) => {
                            let value = if *value {1} else {0};
                            vec.push(format!("{} = {}", column, value));
                        },
                        JsonValue::Null => {
                            vec.push(format!("{} IS NULL", column));
                        },
                        _ => ()
                    }
                }
            }
        }
        Ok(vec.join(" and "))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json::json;
    #[test]
    fn it_works() {
        let node_where = NodeWhere::new(json!({
            "active": true,
            "age": 18,
            "gender": ["male", "female"],
            "profile": null
        }));
        assert_eq!(node_where.to_sql("users").unwrap(), "`users`.`active` = 1 and `users`.`age` = 18 and `users`.`gender` in ['male','female'] and `users`.`profile` IS NULL");
    }
}