py_sql/node/
foreach_node.rs

1use crate::ast::RbatisAST;
2use crate::node::node::do_child_nodes;
3use crate::node::node_type::NodeType;
4use rexpr::ast::Node;
5use rexpr::runtime::RExprRuntime;
6use serde_json::{json, Value};
7#[derive(Clone, Debug)]
8pub struct ForEachNode {
9    pub childs: Vec<NodeType>,
10    pub collection: String,
11    pub index: String,
12    pub item: String,
13    pub get_collection_func: Node,
14}
15
16impl ForEachNode {
17    pub fn from(
18        runtime: &RExprRuntime,
19        source: &str,
20        express: &str,
21        childs: Vec<NodeType>,
22    ) -> Result<Self, crate::error::Error> {
23        if !express.contains("in ") {
24            return Err(crate::error::Error::from(
25                "[rbatis] parser express fail:".to_string() + source,
26            ));
27        }
28        let express = express[Self::name().len()..].trim();
29        let in_index = express.find("in ").unwrap();
30        let col = express[in_index + "in ".len()..].trim();
31        let mut item = express[..in_index].trim();
32        let mut index = "";
33        if item.contains(",") {
34            let items: Vec<&str> = item.split(",").collect();
35            if items.len() != 2 {
36                return Err(crate::error::Error::from(format!(
37                    "[rbatis][py] parse fail 'for ,' must be 'for arg1,arg2 in ...',value:'{}'",
38                    source
39                )));
40            }
41            index = items[0];
42            item = items[1];
43        }
44        return Ok(ForEachNode {
45            childs: childs,
46            collection: col.to_string(),
47            index: index.to_string(),
48            item: item.to_string(),
49            get_collection_func: runtime.parse(col)?,
50        });
51    }
52}
53
54impl RbatisAST for ForEachNode {
55    fn name() -> &'static str {
56        "for"
57    }
58    fn eval(
59        &self,
60        convert: &dyn crate::StringConvert,
61        env: &mut Value,
62        engine: &RExprRuntime,
63        arg_array: &mut Vec<Value>,
64        arg_sql: &mut String,
65    ) -> Result<serde_json::Value, crate::error::Error> {
66        let collection_value = self.get_collection_func.eval(env)?;
67        if collection_value.is_null() {
68            return Result::Ok(serde_json::Value::Null);
69        }
70        if collection_value.is_array() {
71            let collection = collection_value.as_array().unwrap();
72            let mut index = -1;
73            for item in collection {
74                index = index + 1;
75                env[&self.item] = item.clone();
76                env[&self.index] = serde_json::Value::Number(serde_json::Number::from(index));
77                do_child_nodes(convert, &self.childs, env, engine, arg_array, arg_sql)?;
78                match env {
79                    serde_json::Value::Object(obj) => {
80                        obj.remove(&self.item);
81                        obj.remove(&self.index);
82                    }
83                    _ => {}
84                }
85            }
86            return Result::Ok(serde_json::Value::Null);
87        } else if collection_value.is_object() {
88            let collection = collection_value.as_object().unwrap();
89            let mut index = -1;
90            for (key, item) in collection {
91                index = index + 1;
92                env[&self.item] = item.clone();
93                env[&self.index] = serde_json::Value::String(key.to_string());
94                do_child_nodes(convert, &self.childs, env, engine, arg_array, arg_sql)?;
95                match env {
96                    serde_json::Value::Object(obj) => {
97                        obj.remove(&self.item);
98                        obj.remove(&self.index);
99                    }
100                    _ => {}
101                }
102            }
103            return Result::Ok(serde_json::Value::Null);
104        } else {
105            return Result::Err(crate::error::Error::from(
106                "[rbatis] collection name:".to_owned()
107                    + self.collection.as_str()
108                    + " is not a array or object/map value!",
109            ));
110        }
111    }
112}