v_common/search/
sql_params.rs1use v_individual_model::onto::individual::Individual;
2use v_individual_model::onto::resource::Value;
3use crate::search::sql_lex_tree::tr_statement;
4use klickhouse::query_parser::parse_query_arguments;
5use regex::Regex;
6use sqlparser::dialect::AnsiDialect;
7use sqlparser::dialect::MySqlDialect;
8use sqlparser::parser::Parser;
9use std::io::{Error, ErrorKind};
10
11pub fn parse_sql_query_arguments(query: &str, params: &mut Individual, dialect: &str) -> Result<String, Error> {
12 match dialect {
13 "clickhouse" => {
14 let re = Regex::new(r"(\{[^\}]+\}|'\{[^\}]+\}')").unwrap();
15
16 let mut arg_names = Vec::new();
17 let mut arg_values = Vec::new();
18 let res_query = re
19 .replace_all(query, |caps: ®ex::Captures| {
20 let arg_name_with_braces = caps.get(1).unwrap().as_str();
21 let arg_name = arg_name_with_braces.trim_start_matches("'{").trim_end_matches("}'").trim_start_matches("{").trim_end_matches("}");
22 arg_names.push(arg_name.to_string());
23 let arg_index = arg_names.len();
24 format!("${}", arg_index)
25 })
26 .to_string();
27
28 for arg_name in &arg_names {
32 if let Some(res) = params.get_obj().get_resources().get(arg_name) {
34 let arg_value = match &res[0].value {
35 Value::Uri(v) | Value::Str(v, _) => klickhouse::Value::string(v),
36 Value::Int(v) => klickhouse::Value::Int64(*v),
37 Value::Bool(v) => klickhouse::Value::UInt8(*v as u8),
38 Value::Num(_m, _d) => klickhouse::Value::Float64(res[0].get_float()),
39 Value::Datetime(v) => klickhouse::Value::DateTime(klickhouse::DateTime(klickhouse::Tz::UTC, *v as u32)),
40 _ => return Err(Error::new(ErrorKind::Other, format!("Unsupported value type {:?}", res[0].value))),
41 };
42 arg_values.push(arg_value);
43 } else {
44 return Err(Error::new(ErrorKind::Other, format!("Variable {} not found in params", arg_name)));
45 }
46 }
47
48 let res_query = parse_query_arguments(&res_query, &arg_values);
49 return Ok(res_query);
52 },
53 "mysql" | _ => {
54 let lex_tree = match dialect {
55 "mysql" => Parser::parse_sql(&MySqlDialect {}, query),
56 _ => Parser::parse_sql(&AnsiDialect {}, query),
57 };
58
59 match lex_tree {
60 Ok(mut ast) => {
61 if let Some(el) = ast.iter_mut().next() {
62 tr_statement(el, params)?;
63 debug!("NEW: {}", el);
64 return match dialect {
65 "mysql" => Ok(el.to_string()),
66 _ => Err(Error::new(ErrorKind::Other, "unknown SQL dialect")),
67 };
68 }
69 },
70 Err(e) => {
71 error!("{:?}", e);
72 },
73 }
74 Err(Error::new(ErrorKind::Other, "?"))
75 },
76 }
77}