1#[derive(Debug, Clone, PartialEq)]
10pub struct Comment {
11 pub text: String,
13 pub is_line_comment: bool,
15}
16
17impl Comment {
18 pub fn line(text: String) -> Self {
20 Self {
21 text,
22 is_line_comment: true,
23 }
24 }
25
26 pub fn block(text: String) -> Self {
28 Self {
29 text,
30 is_line_comment: false,
31 }
32 }
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, Hash)]
39pub enum QuoteStyle {
40 None,
42 DoubleQuotes,
44 Brackets,
46}
47
48#[derive(Debug, Clone, PartialEq, Eq, Hash)]
50pub struct ColumnRef {
51 pub name: String,
52 pub quote_style: QuoteStyle,
53 pub table_prefix: Option<String>,
55}
56
57impl ColumnRef {
58 pub fn unquoted(name: String) -> Self {
60 Self {
61 name,
62 quote_style: QuoteStyle::None,
63 table_prefix: None,
64 }
65 }
66
67 pub fn quoted(name: String) -> Self {
69 Self {
70 name,
71 quote_style: QuoteStyle::DoubleQuotes,
72 table_prefix: None,
73 }
74 }
75
76 pub fn qualified(table: String, name: String) -> Self {
78 Self {
79 name,
80 quote_style: QuoteStyle::None,
81 table_prefix: Some(table),
82 }
83 }
84
85 pub fn to_qualified_string(&self) -> String {
87 match &self.table_prefix {
88 Some(table) => format!("{}.{}", table, self.name),
89 None => self.name.clone(),
90 }
91 }
92
93 pub fn bracketed(name: String) -> Self {
95 Self {
96 name,
97 quote_style: QuoteStyle::Brackets,
98 table_prefix: None,
99 }
100 }
101
102 pub fn to_sql(&self) -> String {
104 let column_part = match self.quote_style {
105 QuoteStyle::None => self.name.clone(),
106 QuoteStyle::DoubleQuotes => format!("\"{}\"", self.name),
107 QuoteStyle::Brackets => format!("[{}]", self.name),
108 };
109
110 match &self.table_prefix {
111 Some(table) => format!("{}.{}", table, column_part),
112 None => column_part,
113 }
114 }
115}
116
117impl PartialEq<str> for ColumnRef {
118 fn eq(&self, other: &str) -> bool {
119 self.name == other
120 }
121}
122
123impl PartialEq<&str> for ColumnRef {
124 fn eq(&self, other: &&str) -> bool {
125 self.name == *other
126 }
127}
128
129impl std::fmt::Display for ColumnRef {
130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131 write!(f, "{}", self.to_sql())
132 }
133}
134
135#[derive(Debug, Clone)]
136pub enum SqlExpression {
137 Column(ColumnRef),
138 StringLiteral(String),
139 NumberLiteral(String),
140 BooleanLiteral(bool),
141 Null, DateTimeConstructor {
143 year: i32,
144 month: u32,
145 day: u32,
146 hour: Option<u32>,
147 minute: Option<u32>,
148 second: Option<u32>,
149 },
150 DateTimeToday {
151 hour: Option<u32>,
152 minute: Option<u32>,
153 second: Option<u32>,
154 },
155 MethodCall {
156 object: String,
157 method: String,
158 args: Vec<SqlExpression>,
159 },
160 ChainedMethodCall {
161 base: Box<SqlExpression>,
162 method: String,
163 args: Vec<SqlExpression>,
164 },
165 FunctionCall {
166 name: String,
167 args: Vec<SqlExpression>,
168 distinct: bool, },
170 WindowFunction {
171 name: String,
172 args: Vec<SqlExpression>,
173 window_spec: WindowSpec,
174 },
175 BinaryOp {
176 left: Box<SqlExpression>,
177 op: String,
178 right: Box<SqlExpression>,
179 },
180 InList {
181 expr: Box<SqlExpression>,
182 values: Vec<SqlExpression>,
183 },
184 NotInList {
185 expr: Box<SqlExpression>,
186 values: Vec<SqlExpression>,
187 },
188 Between {
189 expr: Box<SqlExpression>,
190 lower: Box<SqlExpression>,
191 upper: Box<SqlExpression>,
192 },
193 Not {
194 expr: Box<SqlExpression>,
195 },
196 CaseExpression {
197 when_branches: Vec<WhenBranch>,
198 else_branch: Option<Box<SqlExpression>>,
199 },
200 SimpleCaseExpression {
201 expr: Box<SqlExpression>,
202 when_branches: Vec<SimpleWhenBranch>,
203 else_branch: Option<Box<SqlExpression>>,
204 },
205 ScalarSubquery {
208 query: Box<SelectStatement>,
209 },
210 InSubquery {
213 expr: Box<SqlExpression>,
214 subquery: Box<SelectStatement>,
215 },
216 Unnest {
220 column: Box<SqlExpression>,
221 delimiter: String,
222 },
223 NotInSubquery {
226 expr: Box<SqlExpression>,
227 subquery: Box<SelectStatement>,
228 },
229}
230
231#[derive(Debug, Clone)]
232pub struct WhenBranch {
233 pub condition: Box<SqlExpression>,
234 pub result: Box<SqlExpression>,
235}
236
237#[derive(Debug, Clone)]
238pub struct SimpleWhenBranch {
239 pub value: Box<SqlExpression>,
240 pub result: Box<SqlExpression>,
241}
242
243#[derive(Debug, Clone)]
246pub struct WhereClause {
247 pub conditions: Vec<Condition>,
248}
249
250#[derive(Debug, Clone)]
251pub struct Condition {
252 pub expr: SqlExpression,
253 pub connector: Option<LogicalOp>, }
255
256#[derive(Debug, Clone)]
257pub enum LogicalOp {
258 And,
259 Or,
260}
261
262#[derive(Debug, Clone, PartialEq)]
265pub enum SortDirection {
266 Asc,
267 Desc,
268}
269
270#[derive(Debug, Clone)]
273pub struct OrderByColumn {
274 pub column: String,
275 pub direction: SortDirection,
276}
277
278#[derive(Debug, Clone)]
280pub struct OrderByItem {
281 pub expr: SqlExpression,
282 pub direction: SortDirection,
283}
284
285impl OrderByItem {
286 pub fn from_column_name(name: String, direction: SortDirection) -> Self {
288 Self {
289 expr: SqlExpression::Column(ColumnRef {
290 name,
291 quote_style: QuoteStyle::None,
292 table_prefix: None,
293 }),
294 direction,
295 }
296 }
297
298 pub fn from_expression(expr: SqlExpression, direction: SortDirection) -> Self {
300 Self { expr, direction }
301 }
302}
303
304#[derive(Debug, Clone, PartialEq)]
308pub enum FrameBound {
309 UnboundedPreceding,
310 CurrentRow,
311 Preceding(i64),
312 Following(i64),
313 UnboundedFollowing,
314}
315
316#[derive(Debug, Clone, PartialEq)]
318pub enum FrameUnit {
319 Rows,
320 Range,
321}
322
323#[derive(Debug, Clone)]
325pub struct WindowFrame {
326 pub unit: FrameUnit,
327 pub start: FrameBound,
328 pub end: Option<FrameBound>, }
330
331#[derive(Debug, Clone)]
332pub struct WindowSpec {
333 pub partition_by: Vec<String>,
334 pub order_by: Vec<OrderByItem>,
335 pub frame: Option<WindowFrame>, }
337
338#[derive(Debug, Clone, PartialEq)]
342pub enum SetOperation {
343 UnionAll,
345 Union,
347 Intersect,
349 Except,
351}
352
353#[derive(Debug, Clone)]
355pub enum SelectItem {
356 Column {
358 column: ColumnRef,
359 leading_comments: Vec<Comment>,
360 trailing_comment: Option<Comment>,
361 },
362 Expression {
364 expr: SqlExpression,
365 alias: String,
366 leading_comments: Vec<Comment>,
367 trailing_comment: Option<Comment>,
368 },
369 Star {
371 table_prefix: Option<String>, leading_comments: Vec<Comment>,
373 trailing_comment: Option<Comment>,
374 },
375 StarExclude {
377 table_prefix: Option<String>,
378 excluded_columns: Vec<String>,
379 leading_comments: Vec<Comment>,
380 trailing_comment: Option<Comment>,
381 },
382}
383
384#[derive(Debug, Clone)]
385pub struct SelectStatement {
386 pub distinct: bool, pub columns: Vec<String>, pub select_items: Vec<SelectItem>, pub from_table: Option<String>,
390 pub from_subquery: Option<Box<SelectStatement>>, pub from_function: Option<TableFunction>, pub from_alias: Option<String>, pub joins: Vec<JoinClause>, pub where_clause: Option<WhereClause>,
395 pub order_by: Option<Vec<OrderByItem>>, pub group_by: Option<Vec<SqlExpression>>, pub having: Option<SqlExpression>, pub qualify: Option<SqlExpression>, pub limit: Option<usize>,
400 pub offset: Option<usize>,
401 pub ctes: Vec<CTE>, pub into_table: Option<IntoTable>, pub set_operations: Vec<(SetOperation, Box<SelectStatement>)>, pub leading_comments: Vec<Comment>, pub trailing_comment: Option<Comment>, }
409
410impl Default for SelectStatement {
411 fn default() -> Self {
412 SelectStatement {
413 distinct: false,
414 columns: Vec::new(),
415 select_items: Vec::new(),
416 from_table: None,
417 from_subquery: None,
418 from_function: None,
419 from_alias: None,
420 joins: Vec::new(),
421 where_clause: None,
422 order_by: None,
423 group_by: None,
424 having: None,
425 qualify: None,
426 limit: None,
427 offset: None,
428 ctes: Vec::new(),
429 into_table: None,
430 set_operations: Vec::new(),
431 leading_comments: Vec::new(),
432 trailing_comment: None,
433 }
434 }
435}
436
437#[derive(Debug, Clone, PartialEq)]
439pub struct IntoTable {
440 pub name: String,
442}
443
444#[derive(Debug, Clone)]
448pub enum TableFunction {
449 Generator {
450 name: String,
451 args: Vec<SqlExpression>,
452 },
453}
454
455#[derive(Debug, Clone)]
457pub struct CTE {
458 pub name: String,
459 pub column_list: Option<Vec<String>>, pub cte_type: CTEType,
461}
462
463#[derive(Debug, Clone)]
465pub enum CTEType {
466 Standard(SelectStatement),
467 Web(WebCTESpec),
468}
469
470#[derive(Debug, Clone)]
472pub struct WebCTESpec {
473 pub url: String,
474 pub format: Option<DataFormat>, pub headers: Vec<(String, String)>, pub cache_seconds: Option<u64>, pub method: Option<HttpMethod>, pub body: Option<String>, pub json_path: Option<String>, pub form_files: Vec<(String, String)>, pub form_fields: Vec<(String, String)>, pub template_vars: Vec<TemplateVar>, }
484
485#[derive(Debug, Clone)]
487pub struct TemplateVar {
488 pub placeholder: String, pub table_name: String, pub column: Option<String>, pub index: Option<usize>, }
493
494#[derive(Debug, Clone)]
496pub enum HttpMethod {
497 GET,
498 POST,
499 PUT,
500 DELETE,
501 PATCH,
502}
503
504#[derive(Debug, Clone)]
506pub enum DataFormat {
507 CSV,
508 JSON,
509 Auto, }
511
512#[derive(Debug, Clone)]
514pub enum TableSource {
515 Table(String), DerivedTable {
517 query: Box<SelectStatement>,
519 alias: String, },
521}
522
523#[derive(Debug, Clone, PartialEq)]
525pub enum JoinType {
526 Inner,
527 Left,
528 Right,
529 Full,
530 Cross,
531}
532
533#[derive(Debug, Clone, PartialEq)]
535pub enum JoinOperator {
536 Equal,
537 NotEqual,
538 LessThan,
539 GreaterThan,
540 LessThanOrEqual,
541 GreaterThanOrEqual,
542}
543
544#[derive(Debug, Clone)]
546pub struct SingleJoinCondition {
547 pub left_expr: SqlExpression, pub operator: JoinOperator, pub right_expr: SqlExpression, }
551
552#[derive(Debug, Clone)]
554pub struct JoinCondition {
555 pub conditions: Vec<SingleJoinCondition>, }
557
558#[derive(Debug, Clone)]
560pub struct JoinClause {
561 pub join_type: JoinType,
562 pub table: TableSource, pub alias: Option<String>, pub condition: JoinCondition, }