Skip to main content

polyglot_sql/dialects/
druid.rs

1//! Apache Druid Dialect
2//!
3//! Druid-specific SQL dialect based on sqlglot patterns.
4//! Reference: https://druid.apache.org/docs/latest/querying/sql-data-types/
5//!
6//! Key characteristics:
7//! - Type mappings: NCHAR, NVARCHAR, TEXT, UUID → STRING
8//! - CURRENT_TIMESTAMP without parentheses
9//! - MOD function for modulo
10//! - ARRAY[...] syntax for arrays
11
12use super::{DialectImpl, DialectType};
13use crate::error::Result;
14use crate::expressions::{Expression, Function};
15use crate::generator::GeneratorConfig;
16use crate::tokens::TokenizerConfig;
17
18/// Apache Druid dialect
19pub struct DruidDialect;
20
21impl DialectImpl for DruidDialect {
22    fn dialect_type(&self) -> DialectType {
23        DialectType::Druid
24    }
25
26    fn tokenizer_config(&self) -> TokenizerConfig {
27        let mut config = TokenizerConfig::default();
28        // Druid uses double quotes for identifiers
29        config.identifiers.insert('"', '"');
30        config
31    }
32
33    fn generator_config(&self) -> GeneratorConfig {
34        use crate::generator::IdentifierQuoteStyle;
35        GeneratorConfig {
36            identifier_quote: '"',
37            identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
38            dialect: Some(DialectType::Druid),
39            ..Default::default()
40        }
41    }
42
43    fn transform_expr(&self, expr: Expression) -> Result<Expression> {
44        match expr {
45            // CurrentTimestamp without args in Druid
46            Expression::CurrentTimestamp(_) => Ok(Expression::CurrentTimestamp(
47                crate::expressions::CurrentTimestamp { precision: None, sysdate: false },
48            )),
49
50            // Modulo -> MOD function in Druid
51            Expression::Mod(op) => Ok(Expression::Function(Box::new(Function::new(
52                "MOD".to_string(),
53                vec![op.left, op.right],
54            )))),
55
56            // Generic function transformations
57            Expression::Function(f) => self.transform_function(*f),
58
59            // Pass through everything else
60            _ => Ok(expr),
61        }
62    }
63}
64
65impl DruidDialect {
66    fn transform_function(&self, f: Function) -> Result<Expression> {
67        let name_upper = f.name.to_uppercase();
68        match name_upper.as_str() {
69            // CURRENT_TIMESTAMP without parentheses
70            "CURRENT_TIMESTAMP" => Ok(Expression::CurrentTimestamp(
71                crate::expressions::CurrentTimestamp { precision: None, sysdate: false },
72            )),
73
74            // Pass through everything else
75            _ => Ok(Expression::Function(Box::new(f))),
76        }
77    }
78}