1use std::collections::HashSet;
16use std::fmt::{Display, Formatter};
17
18use sqlparser::ast::{Expr, ObjectName, Query, SetExpr, SqlOption, TableFactor, Value};
19
20use crate::error::{InvalidSqlSnafu, InvalidTableOptionValueSnafu, Result};
21
22pub fn format_raw_object_name(name: &ObjectName) -> String {
24 struct Inner<'a> {
25 name: &'a ObjectName,
26 }
27
28 impl Display for Inner<'_> {
29 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
30 let mut delim = "";
31 for ident in self.name.0.iter() {
32 write!(f, "{delim}")?;
33 delim = ".";
34 write!(f, "{}", ident.value)?;
35 }
36 Ok(())
37 }
38 }
39
40 format!("{}", Inner { name })
41}
42
43pub fn parse_option_string(option: SqlOption) -> Result<(String, String)> {
44 let SqlOption::KeyValue { key, value } = option else {
45 return InvalidSqlSnafu {
46 msg: "Expecting a key-value pair in the option",
47 }
48 .fail();
49 };
50 let v = match value {
51 Expr::Value(Value::SingleQuotedString(v)) | Expr::Value(Value::DoubleQuotedString(v)) => v,
52 Expr::Identifier(v) => v.value,
53 Expr::Value(Value::Number(v, _)) => v.to_string(),
54 value => return InvalidTableOptionValueSnafu { key, value }.fail(),
55 };
56 let k = key.value.to_lowercase();
57 Ok((k, v))
58}
59
60pub fn extract_tables_from_query(query: &Query) -> impl Iterator<Item = ObjectName> {
62 let mut names = HashSet::new();
63
64 extract_tables_from_set_expr(&query.body, &mut names);
65
66 names.into_iter()
67}
68
69fn extract_tables_from_set_expr(set_expr: &SetExpr, names: &mut HashSet<ObjectName>) {
73 match set_expr {
74 SetExpr::Select(select) => {
75 for from in &select.from {
76 table_factor_to_object_name(&from.relation, names);
77 for join in &from.joins {
78 table_factor_to_object_name(&join.relation, names);
79 }
80 }
81 }
82 SetExpr::Query(query) => {
83 extract_tables_from_set_expr(&query.body, names);
84 }
85 SetExpr::SetOperation { left, right, .. } => {
86 extract_tables_from_set_expr(left, names);
87 extract_tables_from_set_expr(right, names);
88 }
89 SetExpr::Values(_) | SetExpr::Insert(_) | SetExpr::Update(_) | SetExpr::Table(_) => {}
90 };
91}
92
93fn table_factor_to_object_name(table_factor: &TableFactor, names: &mut HashSet<ObjectName>) {
97 if let TableFactor::Table { name, .. } = table_factor {
98 names.insert(name.to_owned());
99 }
100}