sql/statements/
set_variables.rs1use std::fmt::Display;
16
17use serde::Serialize;
18use sqlparser::ast::{Expr, ObjectName, ObjectNamePart, Value, ValueWithSpan};
19use sqlparser_derive::{Visit, VisitMut};
20
21#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
23pub struct SetVariables {
24 pub variable: ObjectName,
25 pub value: Vec<Expr>,
26}
27
28impl SetVariables {
29 pub fn search_path(&self) -> Option<&str> {
31 let [ObjectNamePart::Identifier(variable)] = self.variable.0.as_slice() else {
32 return None;
33 };
34 if variable.quote_style.is_some() || !variable.value.eq_ignore_ascii_case("search_path") {
35 return None;
36 }
37
38 match self.value.first()? {
39 Expr::Value(ValueWithSpan {
40 value: Value::SingleQuotedString(value) | Value::DoubleQuotedString(value),
41 ..
42 }) => Some(value),
43 Expr::Identifier(value) => Some(&value.value),
44 _ => None,
45 }
46 }
47}
48
49impl Display for SetVariables {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 let variable = &self.variable;
52 let value = &self
53 .value
54 .iter()
55 .map(|expr| format!("{}", expr))
56 .collect::<Vec<_>>()
57 .join(", ");
58
59 write!(f, r#"SET {variable} = {value}"#)
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use std::assert_matches;
66
67 use crate::dialect::GreptimeDbDialect;
68 use crate::parser::{ParseOptions, ParserContext};
69 use crate::statements::statement::Statement;
70
71 #[test]
72 fn test_display_show_variables() {
73 let sql = r"set delayed_insert_timeout=300;";
74 let stmts =
75 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
76 .unwrap();
77 assert_eq!(1, stmts.len());
78 assert_matches!(&stmts[0], Statement::SetVariables { .. });
79
80 match &stmts[0] {
81 Statement::SetVariables(set) => {
82 let new_sql = format!("\n{}", set);
83 assert_eq!(
84 r#"
85SET delayed_insert_timeout = 300"#,
86 &new_sql
87 );
88 }
89 _ => {
90 unreachable!();
91 }
92 }
93 }
94
95 #[test]
96 fn test_search_path() {
97 for (sql, expected) in [
98 ("SET search_path TO public", Some("public")),
99 ("SET SEARCH_PATH TO 'private'", Some("private")),
100 ("SET search_path TO \"quoted\"", Some("quoted")),
101 ("SET \"search_path\" TO private", None),
102 ("SET timezone TO 'UTC'", None),
103 ] {
104 let statements = ParserContext::create_with_dialect(
105 sql,
106 &GreptimeDbDialect {},
107 ParseOptions::default(),
108 )
109 .unwrap();
110 let [Statement::SetVariables(set)] = statements.as_slice() else {
111 unreachable!()
112 };
113 assert_eq!(expected, set.search_path());
114 }
115 }
116}