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}
11
12#[derive(Debug, Clone, PartialEq, Eq, Default)]
14pub enum JoinType {
15 #[default]
16 Left,
17 Inner,
18 Full,
19 Cross,
20}
21
22impl JoinType {
23 pub fn sql_keyword(&self) -> &'static str {
24 match self {
25 JoinType::Left => "LEFT JOIN",
26 JoinType::Inner => "INNER JOIN",
27 JoinType::Full => "FULL OUTER JOIN",
28 JoinType::Cross => "CROSS JOIN",
29 }
30 }
31}
32
33#[derive(Clone)]
37pub struct QueryBuilderFn(pub Arc<dyn Fn(&QueryIR) -> CompileResult + Send + Sync>);
38
39impl std::fmt::Debug for QueryBuilderFn {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 f.write_str("QueryBuilderFn(...)")
42 }
43}
44
45#[derive(Debug, Clone)]
47pub struct QueryIR {
48 pub cube: String,
49 pub schema: String,
50 pub table: String,
51 pub selects: Vec<SelectExpr>,
52 pub filters: FilterNode,
53 pub having: FilterNode,
54 pub group_by: Vec<String>,
55 pub order_by: Vec<OrderExpr>,
56 pub limit: u32,
57 pub offset: u32,
58 pub limit_by: Option<LimitByExpr>,
60 pub use_final: bool,
62 pub joins: Vec<JoinExpr>,
64 pub custom_query_builder: Option<QueryBuilderFn>,
66}
67
68#[derive(Debug, Clone)]
70pub struct JoinExpr {
71 pub schema: String,
72 pub table: String,
73 pub alias: String,
75 pub conditions: Vec<(String, String)>,
77 pub selects: Vec<SelectExpr>,
79 pub group_by: Vec<String>,
81 pub use_final: bool,
83 pub is_aggregate: bool,
85 pub target_cube: String,
87 pub join_field: String,
89 pub join_type: JoinType,
91}
92
93#[derive(Debug, Clone)]
94pub enum SelectExpr {
95 Column {
96 column: String,
97 alias: Option<String>,
98 },
99 Aggregate {
100 function: String,
101 column: String,
102 alias: String,
103 condition: Option<String>,
104 },
105}
106
107#[derive(Debug, Clone)]
108pub enum FilterNode {
109 And(Vec<FilterNode>),
110 Or(Vec<FilterNode>),
111 Condition {
112 column: String,
113 op: CompareOp,
114 value: SqlValue,
115 },
116 Empty,
117}
118
119#[derive(Debug, Clone)]
120pub enum CompareOp {
121 Eq,
122 Ne,
123 Gt,
124 Ge,
125 Lt,
126 Le,
127 Like,
128 In,
129 NotIn,
130 Includes,
131 IsNull,
132 IsNotNull,
133}
134
135impl CompareOp {
136 pub fn sql_op(&self) -> &'static str {
137 match self {
138 CompareOp::Eq => "=",
139 CompareOp::Ne => "!=",
140 CompareOp::Gt => ">",
141 CompareOp::Ge => ">=",
142 CompareOp::Lt => "<",
143 CompareOp::Le => "<=",
144 CompareOp::Like => "LIKE",
145 CompareOp::In => "IN",
146 CompareOp::NotIn => "NOT IN",
147 CompareOp::Includes => "LIKE",
148 CompareOp::IsNull => "IS NULL",
149 CompareOp::IsNotNull => "IS NOT NULL",
150 }
151 }
152
153 pub fn is_unary(&self) -> bool {
154 matches!(self, CompareOp::IsNull | CompareOp::IsNotNull)
155 }
156}
157
158#[derive(Debug, Clone)]
159pub struct OrderExpr {
160 pub column: String,
161 pub descending: bool,
162}
163
164#[derive(Debug, Clone)]
165pub struct LimitByExpr {
166 pub count: u32,
167 pub offset: u32,
168 pub columns: Vec<String>,
169}
170
171impl FilterNode {
172 pub fn is_empty(&self) -> bool {
173 matches!(self, FilterNode::Empty)
174 }
175}
176
177pub struct CompileResult {
179 pub sql: String,
180 pub bindings: Vec<SqlValue>,
181 pub alias_remap: Vec<(String, String)>,
184}