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 pub from_subquery: Option<String>,
69}
70
71#[derive(Debug, Clone)]
73pub struct JoinExpr {
74 pub schema: String,
75 pub table: String,
76 pub alias: String,
78 pub conditions: Vec<(String, String)>,
80 pub selects: Vec<SelectExpr>,
82 pub group_by: Vec<String>,
84 pub use_final: bool,
86 pub is_aggregate: bool,
88 pub target_cube: String,
90 pub join_field: String,
92 pub join_type: JoinType,
94}
95
96#[derive(Debug, Clone)]
97pub enum SelectExpr {
98 Column {
99 column: String,
100 alias: Option<String>,
101 },
102 Aggregate {
103 function: String,
104 column: String,
105 alias: String,
106 condition: Option<String>,
107 },
108}
109
110#[derive(Debug, Clone)]
111pub enum FilterNode {
112 And(Vec<FilterNode>),
113 Or(Vec<FilterNode>),
114 Condition {
115 column: String,
116 op: CompareOp,
117 value: SqlValue,
118 },
119 Empty,
120}
121
122#[derive(Debug, Clone)]
123pub enum CompareOp {
124 Eq,
125 Ne,
126 Gt,
127 Ge,
128 Lt,
129 Le,
130 Like,
131 In,
132 NotIn,
133 Includes,
134 IsNull,
135 IsNotNull,
136}
137
138impl CompareOp {
139 pub fn sql_op(&self) -> &'static str {
140 match self {
141 CompareOp::Eq => "=",
142 CompareOp::Ne => "!=",
143 CompareOp::Gt => ">",
144 CompareOp::Ge => ">=",
145 CompareOp::Lt => "<",
146 CompareOp::Le => "<=",
147 CompareOp::Like => "LIKE",
148 CompareOp::In => "IN",
149 CompareOp::NotIn => "NOT IN",
150 CompareOp::Includes => "LIKE",
151 CompareOp::IsNull => "IS NULL",
152 CompareOp::IsNotNull => "IS NOT NULL",
153 }
154 }
155
156 pub fn is_unary(&self) -> bool {
157 matches!(self, CompareOp::IsNull | CompareOp::IsNotNull)
158 }
159}
160
161#[derive(Debug, Clone)]
162pub struct OrderExpr {
163 pub column: String,
164 pub descending: bool,
165}
166
167#[derive(Debug, Clone)]
168pub struct LimitByExpr {
169 pub count: u32,
170 pub offset: u32,
171 pub columns: Vec<String>,
172}
173
174impl FilterNode {
175 pub fn is_empty(&self) -> bool {
176 matches!(self, FilterNode::Empty)
177 }
178}
179
180pub struct CompileResult {
182 pub sql: String,
183 pub bindings: Vec<SqlValue>,
184 pub alias_remap: Vec<(String, String)>,
187}