Skip to main content

databend_common_ast/ast/
query.rs

1// Copyright 2021 Datafuse Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::collections::BTreeMap;
16use std::fmt::Display;
17use std::fmt::Formatter;
18
19use derive_visitor::Drive;
20use derive_visitor::DriveMut;
21use educe::Educe;
22
23use crate::ParseError;
24use crate::Result;
25use crate::Span;
26use crate::ast::Expr;
27use crate::ast::FileLocation;
28use crate::ast::Hint;
29use crate::ast::Identifier;
30use crate::ast::Lambda;
31use crate::ast::SelectStageOptions;
32use crate::ast::SnapshotRefType;
33use crate::ast::TableRef;
34use crate::ast::WindowDefinition;
35use crate::ast::quote::QuotedString;
36use crate::ast::write_comma_separated_list;
37use crate::ast::write_comma_separated_string_map;
38use crate::ast::write_dot_separated_list;
39
40/// Root node of a query tree
41#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
42pub struct Query {
43    pub span: Span,
44    // With clause, common table expression
45    pub with: Option<With>,
46    // Set operator: SELECT or UNION / EXCEPT / INTERSECT
47    pub body: SetExpr,
48
49    // The following clauses can only appear in top level of a subquery/query
50    // `ORDER BY` clause
51    pub order_by: Vec<OrderByExpr>,
52    // `LIMIT` clause
53    pub limit: Vec<Expr>,
54    // `OFFSET` expr
55    pub offset: Option<Expr>,
56
57    // If ignore the result (not output).
58    pub ignore_result: bool,
59}
60
61impl Display for Query {
62    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
63        // CTE, with clause
64        if let Some(with) = &self.with {
65            write!(f, "WITH {with} ")?;
66        }
67
68        // Query body
69        write!(f, "{}", self.body)?;
70
71        // ORDER BY clause
72        if !self.order_by.is_empty() {
73            write!(f, " ORDER BY ")?;
74            write_comma_separated_list(f, &self.order_by)?;
75        }
76
77        // LIMIT clause
78        if !self.limit.is_empty() {
79            write!(f, " LIMIT ")?;
80            write_comma_separated_list(f, &self.limit)?;
81        }
82
83        // TODO: We should validate if offset exists, limit should be empty or just one element
84        if let Some(offset) = &self.offset {
85            write!(f, " OFFSET {offset}")?;
86        }
87
88        if self.ignore_result {
89            write!(f, " IGNORE_RESULT")?;
90        }
91
92        Ok(())
93    }
94}
95
96#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
97pub struct With {
98    pub span: Span,
99    pub recursive: bool,
100    pub ctes: Vec<CTE>,
101}
102
103impl Display for With {
104    #[recursive::recursive]
105    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
106        if self.recursive {
107            write!(f, "RECURSIVE ")?;
108        }
109
110        write_comma_separated_list(f, &self.ctes)?;
111        Ok(())
112    }
113}
114
115#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
116pub struct CTE {
117    pub span: Span,
118    pub alias: TableAlias,
119    pub user_specified_materialized: bool,
120    pub materialized: bool,
121    pub query: Box<Query>,
122}
123
124impl Display for CTE {
125    #[recursive::recursive]
126    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
127        write!(f, "{} AS ", self.alias)?;
128        if self.user_specified_materialized {
129            write!(f, "MATERIALIZED ")?;
130        }
131        write!(f, "({})", self.query)?;
132        Ok(())
133    }
134}
135
136#[derive(Educe, Drive, DriveMut)]
137#[educe(
138    PartialEq(bound = false, attrs = "#[recursive::recursive]"),
139    Clone(bound = false, attrs = "#[recursive::recursive]"),
140    Debug(bound = false, attrs = "#[recursive::recursive]")
141)]
142pub struct SetOperation {
143    pub span: Span,
144    pub op: SetOperator,
145    pub all: bool,
146    pub left: Box<SetExpr>,
147    pub right: Box<SetExpr>,
148}
149
150/// A subquery represented with `SELECT` statement
151#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
152pub struct SelectStmt {
153    pub span: Span,
154    pub hints: Option<Hint>,
155    pub distinct: bool,
156    pub top_n: Option<u64>,
157    // Result set of current subquery
158    pub select_list: Vec<SelectTarget>,
159    // `FROM` clause, a list of table references.
160    // The table references split by `,` will be joined with cross join,
161    // and the result set is union of the joined tables by default.
162    pub from: Vec<TableReference>,
163    // `WHERE` clause
164    pub selection: Option<Expr>,
165    // `GROUP BY` clause
166    pub group_by: Option<GroupBy>,
167    // `HAVING` clause
168    pub having: Option<Expr>,
169    // `WINDOW` clause
170    pub window_list: Option<Vec<WindowDefinition>>,
171    // `QUALIFY` clause
172    pub qualify: Option<Expr>,
173}
174
175impl Display for SelectStmt {
176    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
177        // SELECT clause
178        write!(f, "SELECT ")?;
179        if let Some(hints) = &self.hints {
180            write!(f, "{} ", hints)?;
181        }
182        if self.distinct {
183            write!(f, "DISTINCT ")?;
184        }
185        if let Some(topn) = &self.top_n {
186            write!(f, "TOP {} ", topn)?;
187        }
188        write_comma_separated_list(f, &self.select_list)?;
189
190        // FROM clause
191        if !self.from.is_empty() {
192            write!(f, " FROM ")?;
193            write_comma_separated_list(f, &self.from)?;
194        }
195
196        // WHERE clause
197        if let Some(expr) = &self.selection {
198            write!(f, " WHERE {expr}")?;
199        }
200
201        // GROUP BY clause
202        if let Some(g) = &self.group_by {
203            write!(f, " GROUP BY ")?;
204            write!(f, "{}", g)?;
205        }
206        // HAVING clause
207        if let Some(having) = &self.having {
208            write!(f, " HAVING {having}")?;
209        }
210
211        // WINDOW clause
212        if let Some(windows) = &self.window_list {
213            write!(f, " WINDOW ")?;
214            write_comma_separated_list(f, windows)?;
215        }
216
217        if let Some(qualify) = &self.qualify {
218            write!(f, " QUALIFY {qualify}")?;
219        }
220        Ok(())
221    }
222}
223
224/// Group by Clause.
225#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
226pub enum GroupBy {
227    /// GROUP BY expr [, expr]*
228    Normal(Vec<Expr>),
229    /// GROUP By ALL
230    All,
231    /// GROUP BY GROUPING SETS ( GroupSet [, GroupSet]* )
232    ///
233    /// GroupSet := (expr [, expr]*) | expr
234    GroupingSets(Vec<Vec<Expr>>),
235    /// GROUP BY CUBE ( expr [, expr]* )
236    Cube(Vec<Expr>),
237    /// GROUP BY ROLLUP ( expr [, expr]* )
238    Rollup(Vec<Expr>),
239    Combined(Vec<GroupBy>),
240}
241
242impl GroupBy {
243    pub fn normal_items(&self) -> Vec<Expr> {
244        match self {
245            GroupBy::Normal(exprs) => exprs.clone(),
246            _ => Vec::new(),
247        }
248    }
249}
250
251impl Display for GroupBy {
252    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
253        match self {
254            GroupBy::Normal(exprs) => {
255                write_comma_separated_list(f, exprs)?;
256            }
257            GroupBy::All => {
258                write!(f, "ALL")?;
259            }
260            GroupBy::GroupingSets(sets) => {
261                write!(f, "GROUPING SETS (")?;
262                for (i, set) in sets.iter().enumerate() {
263                    if i > 0 {
264                        write!(f, ", ")?;
265                    }
266                    write!(f, "(")?;
267                    write_comma_separated_list(f, set)?;
268                    write!(f, ")")?;
269                }
270                write!(f, ")")?;
271            }
272            GroupBy::Cube(exprs) => {
273                write!(f, "CUBE (")?;
274                write_comma_separated_list(f, exprs)?;
275                write!(f, ")")?;
276            }
277            GroupBy::Rollup(exprs) => {
278                write!(f, "ROLLUP (")?;
279                write_comma_separated_list(f, exprs)?;
280                write!(f, ")")?;
281            }
282            GroupBy::Combined(group_bys) => {
283                for (i, group_by) in group_bys.iter().enumerate() {
284                    if i > 0 {
285                        write!(f, ", ")?;
286                    }
287                    write!(f, "{}", group_by)?;
288                }
289            }
290        }
291        Ok(())
292    }
293}
294
295/// A relational set expression, like `SELECT ... FROM ... {UNION|EXCEPT|INTERSECT} SELECT ... FROM ...`
296#[derive(Educe, Drive, DriveMut)]
297#[educe(
298    PartialEq(bound = false, attrs = "#[recursive::recursive]"),
299    Clone(bound = false, attrs = "#[recursive::recursive]"),
300    Debug(bound = false, attrs = "#[recursive::recursive]")
301)]
302pub enum SetExpr {
303    Select(Box<SelectStmt>),
304    Query(Box<Query>),
305    // UNION/EXCEPT/INTERSECT operator
306    SetOperation(Box<SetOperation>),
307    // Values clause
308    Values { span: Span, values: Vec<Vec<Expr>> },
309}
310
311impl Display for SetExpr {
312    #[recursive::recursive]
313    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
314        match self {
315            SetExpr::Select(select_stmt) => {
316                write!(f, "{select_stmt}")?;
317            }
318            SetExpr::Query(query) => {
319                write!(f, "({query})")?;
320            }
321            SetExpr::SetOperation(set_operation) => {
322                // Check if the left or right expressions are also SetOperations
323                let left_needs_parentheses = matches!(set_operation.left.as_ref(), SetExpr::SetOperation(left_op) if left_op.op < set_operation.op);
324                let right_needs_parentheses = matches!(set_operation.right.as_ref(), SetExpr::SetOperation(right_op) if right_op.op < set_operation.op);
325
326                if left_needs_parentheses {
327                    write!(f, "(")?;
328                }
329                write!(f, "{}", set_operation.left)?;
330                if left_needs_parentheses {
331                    write!(f, ")")?;
332                }
333
334                match set_operation.op {
335                    SetOperator::Union => {
336                        write!(f, " UNION ")?;
337                    }
338                    SetOperator::Except => {
339                        write!(f, " EXCEPT ")?;
340                    }
341                    SetOperator::Intersect => {
342                        write!(f, " INTERSECT ")?;
343                    }
344                }
345                if set_operation.all {
346                    write!(f, "ALL ")?;
347                }
348                // Add parentheses if necessary
349                if right_needs_parentheses {
350                    write!(f, "(")?;
351                }
352                write!(f, "{}", set_operation.right)?;
353                if right_needs_parentheses {
354                    write!(f, ")")?;
355                }
356            }
357            SetExpr::Values { values, .. } => {
358                write!(f, "VALUES")?;
359                for (i, value) in values.iter().enumerate() {
360                    if i > 0 {
361                        write!(f, ", ")?;
362                    }
363                    write!(f, "(")?;
364                    write_comma_separated_list(f, value)?;
365                    write!(f, ")")?;
366                }
367            }
368        }
369        Ok(())
370    }
371}
372
373#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
374pub enum SetOperator {
375    Union,
376    Except,
377    Intersect,
378}
379
380impl PartialOrd for SetOperator {
381    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
382        if self == other {
383            Some(std::cmp::Ordering::Equal)
384        } else if self == &SetOperator::Intersect {
385            Some(std::cmp::Ordering::Greater)
386        } else {
387            Some(std::cmp::Ordering::Less)
388        }
389    }
390}
391
392/// `ORDER BY` clause
393#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
394pub struct OrderByExpr {
395    pub expr: Expr,
396    /// `ASC` or `DESC`
397    pub asc: Option<bool>,
398    /// `NULLS FIRST` or `NULLS LAST`
399    pub nulls_first: Option<bool>,
400}
401
402impl Display for OrderByExpr {
403    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
404        write!(f, "{}", self.expr)?;
405        if let Some(asc) = self.asc {
406            if asc {
407                write!(f, " ASC")?;
408            } else {
409                write!(f, " DESC")?;
410            }
411        }
412        if let Some(nulls_first) = self.nulls_first {
413            if nulls_first {
414                write!(f, " NULLS FIRST")?;
415            } else {
416                write!(f, " NULLS LAST")?;
417            }
418        }
419        Ok(())
420    }
421}
422
423/// One item of the comma-separated list following `SELECT`
424#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
425pub enum SelectTarget {
426    /// Expression with alias, e.g. `SELECT t.a, b AS a, a+1 AS b FROM t`
427    AliasedExpr {
428        expr: Box<Expr>,
429        alias: Option<Identifier>,
430    },
431
432    /// Qualified star name, e.g. `SELECT t.*  exclude a, columns(expr) FROM t`.
433    /// Columns("pattern_str")
434    /// Columns(lambda expression)
435    /// For simplicity, star wildcard is involved.
436    StarColumns {
437        qualified: QualifiedName,
438        column_filter: Option<ColumnFilter>,
439    },
440}
441
442impl SelectTarget {
443    pub fn is_star(&self) -> bool {
444        match self {
445            SelectTarget::AliasedExpr { .. } => false,
446            SelectTarget::StarColumns { qualified, .. } => {
447                matches!(qualified.last(), Some(Indirection::Star(_)))
448            }
449        }
450    }
451
452    pub fn exclude(&mut self, exclude: Vec<Identifier>) {
453        match self {
454            SelectTarget::AliasedExpr { .. } => unreachable!(),
455            SelectTarget::StarColumns { column_filter, .. } => {
456                *column_filter = Some(ColumnFilter::Excludes(exclude));
457            }
458        }
459    }
460
461    pub fn has_window(&self) -> bool {
462        match self {
463            SelectTarget::AliasedExpr { expr, .. } => match &**expr {
464                Expr::FunctionCall { func, .. } => func.window.is_some(),
465                _ => false,
466            },
467            SelectTarget::StarColumns { .. } => false,
468        }
469    }
470
471    pub fn function_call_name(&self) -> Option<String> {
472        match self {
473            SelectTarget::AliasedExpr { expr, .. } => match &**expr {
474                Expr::FunctionCall { func, .. } if func.window.is_none() => {
475                    Some(func.name.name.to_lowercase())
476                }
477                _ => None,
478            },
479            SelectTarget::StarColumns { .. } => None,
480        }
481    }
482}
483
484impl Display for SelectTarget {
485    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
486        match self {
487            SelectTarget::AliasedExpr { expr, alias } => {
488                write!(f, "{expr}")?;
489                if let Some(ident) = alias {
490                    write!(f, " AS {ident}")?;
491                }
492            }
493            SelectTarget::StarColumns {
494                qualified,
495                column_filter,
496            } => match column_filter {
497                Some(ColumnFilter::Excludes(excludes)) => {
498                    write_dot_separated_list(f, qualified)?;
499                    write!(f, " EXCLUDE (")?;
500                    write_comma_separated_list(f, excludes)?;
501                    write!(f, ")")?;
502                }
503                Some(ColumnFilter::Lambda(lambda)) => {
504                    write!(f, "COLUMNS({lambda})")?;
505                }
506                None => {
507                    write_dot_separated_list(f, qualified)?;
508                }
509            },
510        }
511        Ok(())
512    }
513}
514
515#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
516pub enum ColumnFilter {
517    Excludes(Vec<Identifier>),
518    Lambda(Lambda),
519}
520
521impl ColumnFilter {
522    pub fn get_excludes(&self) -> Option<&[Identifier]> {
523        if let ColumnFilter::Excludes(ex) = self {
524            Some(ex)
525        } else {
526            None
527        }
528    }
529
530    pub fn get_lambda(&self) -> Option<&Lambda> {
531        if let ColumnFilter::Lambda(l) = self {
532            Some(l)
533        } else {
534            None
535        }
536    }
537}
538
539pub type QualifiedName = Vec<Indirection>;
540
541/// Indirection of a select result, like a part of `db.table.column`.
542/// Can be a database name, table name, field name or wildcard star(`*`).
543#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
544pub enum Indirection {
545    // Field name
546    Identifier(Identifier),
547    // Wildcard star
548    Star(Span),
549}
550
551impl Display for Indirection {
552    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
553        match self {
554            Indirection::Identifier(ident) => {
555                write!(f, "{ident}")?;
556            }
557            Indirection::Star(_) => {
558                write!(f, "*")?;
559            }
560        }
561        Ok(())
562    }
563}
564
565/// Time Travel specification
566#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
567pub enum TimeTravelPoint {
568    Snapshot(String),
569    Timestamp(Box<Expr>),
570    Offset(Box<Expr>),
571    Stream {
572        catalog: Option<Identifier>,
573        database: Option<Identifier>,
574        name: Identifier,
575    },
576    TableRef {
577        typ: SnapshotRefType,
578        name: Identifier,
579    },
580}
581
582impl Display for TimeTravelPoint {
583    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
584        match self {
585            TimeTravelPoint::Snapshot(sid) => {
586                write!(f, "(SNAPSHOT => '{sid}')")?;
587            }
588            TimeTravelPoint::Timestamp(ts) => {
589                write!(f, "(TIMESTAMP => {ts})")?;
590            }
591            TimeTravelPoint::Offset(num) => {
592                write!(f, "(OFFSET => {num})")?;
593            }
594            TimeTravelPoint::Stream {
595                catalog,
596                database,
597                name,
598            } => {
599                write!(f, "(STREAM => ")?;
600                write_dot_separated_list(
601                    f,
602                    catalog.iter().chain(database.iter()).chain(Some(name)),
603                )?;
604                write!(f, ")")?;
605            }
606            TimeTravelPoint::TableRef { typ, name } => {
607                write!(f, "({} => {})", typ, name)?;
608            }
609        }
610
611        Ok(())
612    }
613}
614
615#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
616pub enum PivotValues {
617    ColumnValues(Vec<Expr>),
618    Subquery(Box<Query>),
619    Any { order_by: Option<Vec<OrderByExpr>> },
620}
621
622#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
623pub struct Pivot {
624    pub aggregate: Expr,
625    pub value_column: Identifier,
626    pub values: PivotValues,
627}
628
629impl Display for Pivot {
630    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
631        write!(f, "PIVOT({} FOR {} IN (", self.aggregate, self.value_column)?;
632        match &self.values {
633            PivotValues::ColumnValues(column_values) => {
634                write_comma_separated_list(f, column_values)?;
635            }
636            PivotValues::Subquery(subquery) => {
637                write!(f, "{}", subquery)?;
638            }
639            PivotValues::Any { order_by } => {
640                write!(f, "ANY")?;
641                if let Some(order_by_exprs) = order_by {
642                    write!(f, " ORDER BY ")?;
643                    write_comma_separated_list(f, order_by_exprs)?;
644                }
645            }
646        }
647        write!(f, "))")?;
648        Ok(())
649    }
650}
651
652#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
653pub struct UnpivotName {
654    pub ident: Identifier,
655    pub alias: Option<String>,
656}
657
658impl Display for UnpivotName {
659    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
660        match &self.alias {
661            Some(alias) => {
662                write!(f, "{} AS {}", self.ident, QuotedString(alias, '\''))
663            }
664            None => write!(f, "{}", self.ident),
665        }
666    }
667}
668
669#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
670pub struct Unpivot {
671    pub value_column: Identifier,
672    pub unpivot_column: Identifier,
673    pub column_names: Vec<UnpivotName>,
674}
675
676impl Display for Unpivot {
677    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
678        write!(
679            f,
680            "UNPIVOT({} FOR {} IN (",
681            self.value_column, self.unpivot_column
682        )?;
683        write_comma_separated_list(f, &self.column_names)?;
684        write!(f, "))")
685    }
686}
687
688#[derive(Debug, Clone, PartialEq, Eq, Default, Drive, DriveMut)]
689pub struct WithOptions {
690    pub options: BTreeMap<String, String>,
691}
692
693impl Display for WithOptions {
694    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
695        write!(f, "WITH (")?;
696        write_comma_separated_string_map(f, &self.options)?;
697        write!(f, ")")
698    }
699}
700
701impl WithOptions {
702    /// Used for build change query.
703    pub fn to_change_query_with_clause(&self) -> String {
704        let mut result = String::from(" WITH (");
705        for (i, (k, v)) in self.options.iter().enumerate() {
706            if i > 0 {
707                result.push_str(", ");
708            }
709
710            if k == "consume" {
711                // The consume stream will be recorded in QueryContext.
712                // Skip 'consume' to avoid unnecessary operations.
713                result.push_str("consume = false");
714            } else {
715                result.push_str(&format!("{k} = '{v}'"));
716            }
717        }
718        result.push(')');
719        result
720    }
721}
722
723#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
724pub struct ChangesInterval {
725    pub append_only: bool,
726    pub at_point: TimeTravelPoint,
727    pub end_point: Option<TimeTravelPoint>,
728}
729
730impl Display for ChangesInterval {
731    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
732        write!(f, "CHANGES (INFORMATION => ")?;
733        if self.append_only {
734            write!(f, "APPEND_ONLY")?;
735        } else {
736            write!(f, "DEFAULT")?;
737        }
738        write!(f, ") AT {}", self.at_point)?;
739        if let Some(end_point) = &self.end_point {
740            write!(f, " END {}", end_point)?;
741        }
742        Ok(())
743    }
744}
745
746#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
747pub enum TemporalClause {
748    TimeTravel(TimeTravelPoint),
749    Changes(ChangesInterval),
750}
751
752impl Display for TemporalClause {
753    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
754        match self {
755            TemporalClause::TimeTravel(point) => {
756                write!(f, "AT {}", point)?;
757            }
758            TemporalClause::Changes(changes) => {
759                write!(f, "{}", changes)?;
760            }
761        }
762        Ok(())
763    }
764}
765
766#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Drive, DriveMut)]
767pub enum SampleRowLevel {
768    RowsNum(f64),
769    Probability(f64),
770}
771
772impl SampleRowLevel {
773    pub fn sample_probability(&self, stats_rows: Option<u64>) -> Result<Option<f64>> {
774        let rand = match &self {
775            SampleRowLevel::Probability(probability) => probability / 100.0,
776            SampleRowLevel::RowsNum(rows) => {
777                if let Some(row_num) = stats_rows {
778                    if row_num > 0 {
779                        rows / row_num as f64
780                    } else {
781                        return Ok(None);
782                    }
783                } else {
784                    return Ok(None);
785                }
786            }
787        };
788        if rand > 1.0 {
789            return Err(ParseError(
790                None,
791                format!(
792                    "Sample value should be less than or equal to 100, but got {}",
793                    rand * 100.0
794                ),
795            ));
796        }
797        Ok(Some(rand))
798    }
799}
800
801impl Eq for SampleRowLevel {}
802
803#[derive(
804    serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Drive, DriveMut, Default,
805)]
806pub struct SampleConfig {
807    pub row_level: Option<SampleRowLevel>,
808    pub block_level: Option<f64>,
809}
810
811impl SampleConfig {
812    pub fn set_row_level_sample(&mut self, value: f64, rows: bool) {
813        if rows {
814            self.row_level = Some(SampleRowLevel::RowsNum(value));
815        } else {
816            self.row_level = Some(SampleRowLevel::Probability(value));
817        }
818    }
819
820    pub fn set_block_level_sample(&mut self, probability: f64) {
821        self.block_level = Some(probability);
822    }
823}
824
825impl Eq for SampleConfig {}
826
827impl Display for SampleConfig {
828    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
829        write!(f, "SAMPLE ")?;
830        if let Some(block_level) = self.block_level {
831            write!(f, "BLOCK ({}) ", block_level)?;
832        }
833        if let Some(row_level) = &self.row_level {
834            match row_level {
835                SampleRowLevel::RowsNum(rows) => {
836                    write!(f, "ROW ({} ROWS)", rows)?;
837                }
838                SampleRowLevel::Probability(probability) => {
839                    write!(f, "ROW ({})", probability)?;
840                }
841            }
842        }
843        Ok(())
844    }
845}
846
847/// A table name or a parenthesized subquery with an optional alias
848#[allow(clippy::large_enum_variant)]
849#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
850pub enum TableReference {
851    // Table name
852    Table {
853        span: Span,
854        table: TableRef,
855        alias: Option<TableAlias>,
856        temporal: Option<TemporalClause>,
857        with_options: Option<WithOptions>,
858        pivot: Option<Box<Pivot>>,
859        unpivot: Option<Box<Unpivot>>,
860        sample: Option<SampleConfig>,
861    },
862    // `TABLE(expr)[ AS alias ]`
863    TableFunction {
864        span: Span,
865        /// Whether the table function is a lateral table function
866        lateral: bool,
867        name: Identifier,
868        params: Vec<Expr>,
869        named_params: Vec<(Identifier, Expr)>,
870        alias: Option<TableAlias>,
871        sample: Option<SampleConfig>,
872    },
873    // Derived table, which can be a subquery or joined tables or combination of them
874    Subquery {
875        span: Span,
876        /// Whether the subquery is a lateral subquery
877        lateral: bool,
878        subquery: Box<Query>,
879        alias: Option<TableAlias>,
880        pivot: Option<Box<Pivot>>,
881        unpivot: Option<Box<Unpivot>>,
882    },
883    Join {
884        span: Span,
885        join: Join,
886    },
887    Location {
888        span: Span,
889        location: FileLocation,
890        options: SelectStageOptions,
891        alias: Option<TableAlias>,
892    },
893}
894
895impl TableReference {
896    pub fn pivot(&self) -> Option<&Pivot> {
897        match self {
898            TableReference::Table { pivot, .. } => pivot.as_ref().map(|b| b.as_ref()),
899            TableReference::Subquery { pivot, .. } => pivot.as_ref().map(|b| b.as_ref()),
900            _ => None,
901        }
902    }
903
904    pub fn unpivot(&self) -> Option<&Unpivot> {
905        match self {
906            TableReference::Table { unpivot, .. } => unpivot.as_ref().map(|b| b.as_ref()),
907            TableReference::Subquery { unpivot, .. } => unpivot.as_ref().map(|b| b.as_ref()),
908            _ => None,
909        }
910    }
911
912    pub fn is_lateral_table_function(&self) -> bool {
913        match self {
914            TableReference::TableFunction { lateral, .. } => *lateral,
915            _ => false,
916        }
917    }
918
919    pub fn is_lateral_subquery(&self) -> bool {
920        match self {
921            TableReference::Subquery { lateral, .. } => *lateral,
922            _ => false,
923        }
924    }
925}
926
927impl Display for TableReference {
928    #[recursive::recursive]
929    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
930        match self {
931            TableReference::Table {
932                span: _,
933                table,
934                alias,
935                temporal,
936                with_options,
937                pivot,
938                unpivot,
939                sample,
940            } => {
941                write!(f, "{table}")?;
942
943                if let Some(temporal) = temporal {
944                    write!(f, " {temporal}")?;
945                }
946
947                if let Some(with_options) = with_options {
948                    write!(f, " {with_options}")?;
949                }
950
951                if let Some(alias) = alias {
952                    write!(f, " AS {alias}")?;
953                }
954                if let Some(pivot) = pivot {
955                    write!(f, " {pivot}")?;
956                }
957
958                if let Some(unpivot) = unpivot {
959                    write!(f, " {unpivot}")?;
960                }
961
962                if let Some(sample) = sample {
963                    write!(f, " {sample}")?;
964                }
965            }
966            TableReference::TableFunction {
967                span: _,
968                lateral,
969                name,
970                params,
971                named_params,
972                alias,
973                sample,
974            } => {
975                if *lateral {
976                    write!(f, "LATERAL ")?;
977                }
978                write!(f, "{name}(")?;
979                write_comma_separated_list(f, params)?;
980                if !params.is_empty() && !named_params.is_empty() {
981                    write!(f, ",")?;
982                }
983                for (i, (k, v)) in named_params.iter().enumerate() {
984                    if i > 0 {
985                        write!(f, ",")?;
986                    }
987                    write!(f, "{k}=>{v}")?;
988                }
989                write!(f, ")")?;
990                if let Some(alias) = alias {
991                    write!(f, " AS {alias}")?;
992                }
993                if let Some(sample) = sample {
994                    write!(f, " {sample}")?;
995                }
996            }
997            TableReference::Subquery {
998                span: _,
999                lateral,
1000                subquery,
1001                alias,
1002                pivot,
1003                unpivot,
1004            } => {
1005                if *lateral {
1006                    write!(f, "LATERAL ")?;
1007                }
1008                write!(f, "({subquery})")?;
1009                if let Some(alias) = alias {
1010                    write!(f, " AS {alias}")?;
1011                }
1012
1013                if let Some(pivot) = pivot {
1014                    write!(f, " {pivot}")?;
1015                }
1016
1017                if let Some(unpivot) = unpivot {
1018                    write!(f, " {unpivot}")?;
1019                }
1020            }
1021            TableReference::Join { span: _, join } => {
1022                write!(f, "{}", join.left)?;
1023                if join.condition == JoinCondition::Natural {
1024                    write!(f, " NATURAL")?;
1025                }
1026                match join.op {
1027                    JoinOperator::Inner => {
1028                        write!(f, " INNER JOIN")?;
1029                    }
1030                    JoinOperator::LeftOuter => {
1031                        write!(f, " LEFT OUTER JOIN")?;
1032                    }
1033                    JoinOperator::RightOuter => {
1034                        write!(f, " RIGHT OUTER JOIN")?;
1035                    }
1036                    JoinOperator::FullOuter => {
1037                        write!(f, " FULL OUTER JOIN")?;
1038                    }
1039                    JoinOperator::LeftSemi => {
1040                        write!(f, " LEFT SEMI JOIN")?;
1041                    }
1042                    JoinOperator::RightSemi => {
1043                        write!(f, " RIGHT SEMI JOIN")?;
1044                    }
1045                    JoinOperator::LeftAnti => {
1046                        write!(f, " LEFT ANTI JOIN")?;
1047                    }
1048                    JoinOperator::RightAnti => {
1049                        write!(f, " RIGHT ANTI JOIN")?;
1050                    }
1051                    JoinOperator::CrossJoin => {
1052                        write!(f, " CROSS JOIN")?;
1053                    }
1054                    JoinOperator::Asof => {
1055                        write!(f, " ASOF JOIN")?;
1056                    }
1057                    JoinOperator::LeftAsof => {
1058                        write!(f, " ASOF LEFT JOIN")?;
1059                    }
1060                    JoinOperator::RightAsof => {
1061                        write!(f, " ASOF RIGHT JOIN")?;
1062                    }
1063                    JoinOperator::InnerAny => {
1064                        write!(f, " INNER ANY JOIN")?;
1065                    }
1066                    JoinOperator::LeftAny => {
1067                        write!(f, " LEFT ANY JOIN")?;
1068                    }
1069                    JoinOperator::RightAny => {
1070                        write!(f, " RIGHT ANY JOIN")?;
1071                    }
1072                }
1073                write!(f, " {}", join.right)?;
1074                match &join.condition {
1075                    JoinCondition::On(expr) => {
1076                        write!(f, " ON {expr}")?;
1077                    }
1078                    JoinCondition::Using(idents) => {
1079                        write!(f, " USING(")?;
1080                        write_comma_separated_list(f, idents)?;
1081                        write!(f, ")")?;
1082                    }
1083                    _ => {}
1084                }
1085            }
1086            TableReference::Location {
1087                span: _,
1088                location,
1089                options,
1090                alias,
1091            } => {
1092                write!(f, "{location}")?;
1093                if !options.is_empty() {
1094                    write!(f, "{options}")?;
1095                }
1096                if let Some(alias) = alias {
1097                    write!(f, " AS {alias}")?;
1098                }
1099            }
1100        }
1101        Ok(())
1102    }
1103}
1104
1105#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
1106pub struct TableAlias {
1107    pub name: Identifier,
1108    pub columns: Vec<Identifier>,
1109    /// When true, keep the original database name on bound columns even after aliasing.
1110    pub keep_database_name: bool,
1111}
1112
1113impl Display for TableAlias {
1114    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
1115        write!(f, "{}", &self.name)?;
1116        if !self.columns.is_empty() {
1117            write!(f, "(")?;
1118            write_comma_separated_list(f, &self.columns)?;
1119            write!(f, ")")?;
1120        }
1121        Ok(())
1122    }
1123}
1124
1125#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
1126pub struct Join {
1127    pub op: JoinOperator,
1128    pub condition: JoinCondition,
1129    pub left: Box<TableReference>,
1130    pub right: Box<TableReference>,
1131}
1132
1133#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
1134pub enum JoinOperator {
1135    Inner,
1136    // Outer joins can not work with `JoinCondition::None`
1137    LeftOuter,
1138    RightOuter,
1139    FullOuter,
1140    LeftSemi,
1141    LeftAnti,
1142    RightSemi,
1143    RightAnti,
1144    // CrossJoin can only work with `JoinCondition::None`
1145    CrossJoin,
1146    // Asof
1147    Asof,
1148    LeftAsof,
1149    RightAsof,
1150    // Any
1151    InnerAny,
1152    LeftAny,
1153    RightAny,
1154}
1155
1156#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
1157pub enum JoinCondition {
1158    On(Box<Expr>),
1159    Using(Vec<Identifier>),
1160    Natural,
1161    None,
1162}
1163
1164impl SetExpr {
1165    pub fn span(&self) -> Span {
1166        match self {
1167            SetExpr::Select(stmt) => stmt.span,
1168            SetExpr::Query(query) => query.span,
1169            SetExpr::SetOperation(op) => op.span,
1170            SetExpr::Values { span, .. } => *span,
1171        }
1172    }
1173
1174    pub fn into_query(self) -> Query {
1175        match self {
1176            SetExpr::Query(query) => *query,
1177            _ => Query {
1178                span: self.span(),
1179                with: None,
1180                body: self,
1181                order_by: vec![],
1182                limit: vec![],
1183                offset: None,
1184                ignore_result: false,
1185            },
1186        }
1187    }
1188}