1use std::sync::Arc;
2
3#[derive(Debug, Clone)]
5pub enum SqlValue {
6 String(String),
7 Int(i64),
8 Float(f64),
9 Bool(bool),
10 Expression(String),
12}
13
14#[derive(Debug, Clone, PartialEq, Eq, Default)]
16pub enum JoinType {
17 #[default]
18 Left,
19 Inner,
20 Full,
21 Cross,
22}
23
24impl JoinType {
25 pub fn sql_keyword(&self) -> &'static str {
26 match self {
27 JoinType::Left => "LEFT JOIN",
28 JoinType::Inner => "INNER JOIN",
29 JoinType::Full => "FULL OUTER JOIN",
30 JoinType::Cross => "CROSS JOIN",
31 }
32 }
33}
34
35#[derive(Clone)]
39pub struct QueryBuilderFn(pub Arc<dyn Fn(&QueryIR) -> CompileResult + Send + Sync>);
40
41impl std::fmt::Debug for QueryBuilderFn {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 f.write_str("QueryBuilderFn(...)")
44 }
45}
46
47#[derive(Debug, Clone)]
49pub struct QueryIR {
50 pub cube: String,
51 pub schema: String,
52 pub table: String,
53 pub selects: Vec<SelectExpr>,
54 pub filters: FilterNode,
55 pub having: FilterNode,
56 pub group_by: Vec<String>,
57 pub order_by: Vec<OrderExpr>,
58 pub limit: u32,
59 pub offset: u32,
60 pub limit_by: Option<LimitByExpr>,
62 pub use_final: bool,
64 pub joins: Vec<JoinExpr>,
66 pub custom_query_builder: Option<QueryBuilderFn>,
68 pub from_subquery: Option<String>,
71}
72
73#[derive(Debug, Clone)]
75pub struct JoinExpr {
76 pub schema: String,
77 pub table: String,
78 pub alias: String,
80 pub conditions: Vec<(String, String)>,
82 pub selects: Vec<SelectExpr>,
84 pub group_by: Vec<String>,
86 pub use_final: bool,
88 pub is_aggregate: bool,
90 pub target_cube: String,
92 pub join_field: String,
94 pub join_type: JoinType,
96}
97
98#[derive(Debug, Clone, PartialEq, Eq)]
101pub enum DimAggType {
102 ArgMax,
103 ArgMin,
104}
105
106#[derive(Debug, Clone)]
107pub enum SelectExpr {
108 Column {
109 column: String,
110 alias: Option<String>,
111 },
112 Aggregate {
113 function: String,
114 column: String,
115 alias: String,
116 condition: Option<String>,
117 },
118 DimAggregate {
121 agg_type: DimAggType,
122 value_column: String,
123 compare_column: String,
124 alias: String,
125 condition: Option<String>,
126 },
127}
128
129#[derive(Debug, Clone)]
130pub enum FilterNode {
131 And(Vec<FilterNode>),
132 Or(Vec<FilterNode>),
133 Condition {
134 column: String,
135 op: CompareOp,
136 value: SqlValue,
137 },
138 ArrayIncludes {
141 array_columns: Vec<String>,
143 element_conditions: Vec<Vec<FilterNode>>,
146 },
147 Empty,
148}
149
150#[derive(Debug, Clone)]
151pub enum CompareOp {
152 Eq,
153 Ne,
154 Gt,
155 Ge,
156 Lt,
157 Le,
158 Like,
159 In,
160 NotIn,
161 Includes,
162 IsNull,
163 IsNotNull,
164}
165
166impl CompareOp {
167 pub fn sql_op(&self) -> &'static str {
168 match self {
169 CompareOp::Eq => "=",
170 CompareOp::Ne => "!=",
171 CompareOp::Gt => ">",
172 CompareOp::Ge => ">=",
173 CompareOp::Lt => "<",
174 CompareOp::Le => "<=",
175 CompareOp::Like => "LIKE",
176 CompareOp::In => "IN",
177 CompareOp::NotIn => "NOT IN",
178 CompareOp::Includes => "LIKE",
179 CompareOp::IsNull => "IS NULL",
180 CompareOp::IsNotNull => "IS NOT NULL",
181 }
182 }
183
184 pub fn is_unary(&self) -> bool {
185 matches!(self, CompareOp::IsNull | CompareOp::IsNotNull)
186 }
187}
188
189#[derive(Debug, Clone)]
190pub struct OrderExpr {
191 pub column: String,
192 pub descending: bool,
193}
194
195#[derive(Debug, Clone)]
196pub struct LimitByExpr {
197 pub count: u32,
198 pub offset: u32,
199 pub columns: Vec<String>,
200}
201
202impl FilterNode {
203 pub fn is_empty(&self) -> bool {
204 matches!(self, FilterNode::Empty)
205 }
206}
207
208pub struct CompileResult {
210 pub sql: String,
211 pub bindings: Vec<SqlValue>,
212 pub alias_remap: Vec<(String, String)>,
215}