sql_parse/
select.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12use alloc::{boxed::Box, vec::Vec};
13
14use crate::qualified_name::parse_qualified_name;
15use crate::QualifiedName;
16use crate::{
17    expression::{parse_expression, Expression},
18    keywords::Keyword,
19    lexer::Token,
20    parser::{ParseError, Parser},
21    span::OptSpanned,
22    statement::parse_compound_query,
23    Identifier, Span, Spanned, Statement,
24};
25
26/// Value in select
27#[derive(Debug, Clone)]
28pub struct SelectExpr<'a> {
29    /// Value to select
30    pub expr: Expression<'a>,
31    /// Optional name to give value if specified
32    pub as_: Option<Identifier<'a>>,
33}
34
35impl<'a> Spanned for SelectExpr<'a> {
36    fn span(&self) -> Span {
37        self.expr.join_span(&self.as_)
38    }
39}
40
41pub(crate) fn parse_select_expr<'a>(
42    parser: &mut Parser<'a, '_>,
43) -> Result<SelectExpr<'a>, ParseError> {
44    let expr = parse_expression(parser, false)?;
45    let as_ = if parser.skip_keyword(Keyword::AS).is_some() {
46        Some(parser.consume_plain_identifier()?)
47    } else {
48        None
49    };
50    Ok(SelectExpr { expr, as_ })
51}
52
53/// Specification for join
54#[derive(Debug, Clone)]
55pub enum JoinSpecification<'a> {
56    /// On specification expression and span of "ON"
57    On(Expression<'a>, Span),
58    /// List of columns to joint using, and span of "USING"
59    Using(Vec<Identifier<'a>>, Span),
60}
61
62impl<'a> Spanned for JoinSpecification<'a> {
63    fn span(&self) -> Span {
64        match &self {
65            JoinSpecification::On(v, s) => s.join_span(v),
66            JoinSpecification::Using(v, s) => s.join_span(v),
67        }
68    }
69}
70
71/// Type of join
72#[derive(Debug, Clone)]
73pub enum JoinType {
74    Inner(Span),
75    Cross(Span),
76    Normal(Span),
77    Straight(Span),
78    Left(Span),
79    Right(Span),
80    Natural(Span),
81    NaturalInner(Span),
82    NaturalLeft(Span),
83    NaturalRight(Span),
84}
85impl Spanned for JoinType {
86    fn span(&self) -> Span {
87        match &self {
88            JoinType::Inner(v) => v.span(),
89            JoinType::Cross(v) => v.span(),
90            JoinType::Normal(v) => v.span(),
91            JoinType::Straight(v) => v.span(),
92            JoinType::Left(v) => v.span(),
93            JoinType::Right(v) => v.span(),
94            JoinType::Natural(v) => v.span(),
95            JoinType::NaturalInner(v) => v.span(),
96            JoinType::NaturalLeft(v) => v.span(),
97            JoinType::NaturalRight(v) => v.span(),
98        }
99    }
100}
101
102#[derive(Debug, Clone)]
103pub enum IndexHintUse {
104    Use(Span),
105    Ignore(Span),
106    Force(Span),
107}
108impl Spanned for IndexHintUse {
109    fn span(&self) -> Span {
110        match &self {
111            IndexHintUse::Use(v) => v.span(),
112            IndexHintUse::Ignore(v) => v.span(),
113            IndexHintUse::Force(v) => v.span(),
114        }
115    }
116}
117
118#[derive(Debug, Clone)]
119pub enum IndexHintType {
120    Index(Span),
121    Key(Span),
122}
123impl Spanned for IndexHintType {
124    fn span(&self) -> Span {
125        match &self {
126            IndexHintType::Index(v) => v.span(),
127            IndexHintType::Key(v) => v.span(),
128        }
129    }
130}
131
132#[derive(Debug, Clone)]
133pub enum IndexHintFor {
134    Join(Span),
135    OrderBy(Span),
136    GroupBy(Span),
137}
138impl Spanned for IndexHintFor {
139    fn span(&self) -> Span {
140        match &self {
141            IndexHintFor::Join(v) => v.span(),
142            IndexHintFor::OrderBy(v) => v.span(),
143            IndexHintFor::GroupBy(v) => v.span(),
144        }
145    }
146}
147
148#[derive(Debug, Clone)]
149pub struct IndexHint<'a> {
150    pub use_: IndexHintUse,
151    pub type_: IndexHintType,
152    pub for_: Option<(Span, IndexHintFor)>,
153    pub lparen: Span,
154    pub index_list: Vec<Identifier<'a>>,
155    pub rparen: Span,
156}
157
158impl<'a> Spanned for IndexHint<'a> {
159    fn span(&self) -> Span {
160        self.use_
161            .span()
162            .join_span(&self.type_)
163            .join_span(&self.for_)
164            .join_span(&self.lparen)
165            .join_span(&self.index_list)
166            .join_span(&self.rparen)
167    }
168}
169
170/// Reference to table in select
171#[derive(Debug, Clone)]
172pub enum TableReference<'a> {
173    /// Reference to a table or view
174    Table {
175        /// Name of table to to select from
176        identifier: QualifiedName<'a>,
177        /// Span of "AS" if specified
178        as_span: Option<Span>,
179        /// Alias for table if specified
180        as_: Option<Identifier<'a>>,
181        /// Index hints
182        index_hints: Vec<IndexHint<'a>>,
183    },
184    /// Subquery
185    Query {
186        /// Query yielding table
187        query: Box<Statement<'a>>,
188        /// Span of "AS" if specified
189        as_span: Option<Span>,
190        /// Alias for table if specified
191        as_: Option<Identifier<'a>>,
192        //TODO collist
193    },
194    /// Join
195    Join {
196        /// What type of join is it
197        join: JoinType,
198        /// Left hand side of join
199        left: Box<TableReference<'a>>,
200        /// Right hand side of join
201        right: Box<TableReference<'a>>,
202        /// How to do the join if specified
203        specification: Option<JoinSpecification<'a>>,
204    },
205}
206
207impl<'a> Spanned for TableReference<'a> {
208    fn span(&self) -> Span {
209        match &self {
210            TableReference::Table {
211                identifier,
212                as_span,
213                as_,
214                index_hints,
215            } => identifier
216                .opt_join_span(as_span)
217                .opt_join_span(as_)
218                .opt_join_span(index_hints)
219                .expect("span of table"),
220            TableReference::Query {
221                query,
222                as_span,
223                as_,
224            } => query.join_span(as_span).join_span(as_),
225            TableReference::Join {
226                join,
227                left,
228                right,
229                specification,
230            } => join
231                .join_span(left)
232                .join_span(right)
233                .join_span(specification),
234        }
235    }
236}
237
238pub(crate) fn parse_table_reference_inner<'a>(
239    parser: &mut Parser<'a, '_>,
240) -> Result<TableReference<'a>, ParseError> {
241    // TODO [LATERAL] table_subquery [AS] alias [(col_list)]
242    // if parser.skip_token(Token::LParen).is_some() {
243    //     let a = parse_table_reference(parser)?;
244    //     parser.consume_token(Token::RParen)?;
245    //     return Ok(a);
246    // }
247
248    match &parser.token {
249        Token::Ident(_, Keyword::SELECT) | Token::LParen => {
250            let query = parse_compound_query(parser)?;
251            let as_span = parser.skip_keyword(Keyword::AS);
252            let as_ = if as_span.is_some()
253                || (matches!(&parser.token, Token::Ident(_, k) if !k.reserved()))
254            {
255                Some(parser.consume_plain_identifier()?)
256            } else {
257                None
258            };
259            Ok(TableReference::Query {
260                query: Box::new(query),
261                as_span,
262                as_,
263            })
264        }
265        Token::Ident(_, _) => {
266            let identifier = parse_qualified_name(parser)?;
267
268            // TODO [PARTITION (partition_names)] [[AS] alias]
269            let as_span = parser.skip_keyword(Keyword::AS);
270            let as_ = if as_span.is_some()
271                || (matches!(&parser.token, Token::Ident(_, k) if !k.reserved()))
272            {
273                Some(parser.consume_plain_identifier()?)
274            } else {
275                None
276            };
277
278            let mut index_hints = Vec::new();
279            loop {
280                let use_ = match parser.token {
281                    Token::Ident(_, Keyword::USE) => IndexHintUse::Use(parser.consume()),
282                    Token::Ident(_, Keyword::IGNORE) => IndexHintUse::Ignore(parser.consume()),
283                    Token::Ident(_, Keyword::FORCE) => IndexHintUse::Force(parser.consume()),
284                    _ => break,
285                };
286                let type_ = match parser.token {
287                    Token::Ident(_, Keyword::INDEX) => IndexHintType::Index(parser.consume()),
288                    Token::Ident(_, Keyword::KEY) => IndexHintType::Key(parser.consume()),
289                    _ => parser.expected_failure("'INDEX' or 'KEY'")?,
290                };
291                let for_ = if let Some(for_span) = parser.skip_keyword(Keyword::FOR) {
292                    let v = match parser.token {
293                        Token::Ident(_, Keyword::JOIN) => IndexHintFor::Join(parser.consume()),
294                        Token::Ident(_, Keyword::GROUP) => IndexHintFor::GroupBy(
295                            parser.consume_keywords(&[Keyword::GROUP, Keyword::BY])?,
296                        ),
297                        Token::Ident(_, Keyword::ORDER) => IndexHintFor::OrderBy(
298                            parser.consume_keywords(&[Keyword::ORDER, Keyword::BY])?,
299                        ),
300                        _ => parser.expected_failure("'JOIN', 'GROUP BY' or 'ORDER BY'")?,
301                    };
302                    Some((for_span, v))
303                } else {
304                    None
305                };
306                let lparen = parser.consume_token(Token::LParen)?;
307                let mut index_list = Vec::new();
308                loop {
309                    parser.recovered(
310                        "')' or ','",
311                        &|t| matches!(t, Token::RParen | Token::Comma),
312                        |parser| {
313                            index_list.push(parser.consume_plain_identifier()?);
314                            Ok(())
315                        },
316                    )?;
317                    if matches!(parser.token, Token::RParen) {
318                        break;
319                    }
320                    parser.consume_token(Token::Comma)?;
321                }
322                let rparen = parser.consume_token(Token::RParen)?;
323                index_hints.push(IndexHint {
324                    use_,
325                    type_,
326                    for_,
327                    lparen,
328                    index_list,
329                    rparen,
330                })
331            }
332
333            if !index_hints.is_empty() && !parser.options.dialect.is_maria() {
334                parser.err(
335                    "Index hints only supported by MariaDb",
336                    &index_hints.opt_span().unwrap(),
337                );
338            }
339
340            Ok(TableReference::Table {
341                identifier,
342                as_span,
343                as_,
344                index_hints,
345            })
346        }
347        _ => parser.expected_failure("subquery or identifier"),
348    }
349}
350
351pub(crate) fn parse_table_reference<'a>(
352    parser: &mut Parser<'a, '_>,
353) -> Result<TableReference<'a>, ParseError> {
354    let mut ans = parse_table_reference_inner(parser)?;
355    loop {
356        let join = match parser.token {
357            Token::Ident(_, Keyword::INNER) => JoinType::Inner(
358                parser
359                    .consume_keyword(Keyword::INNER)?
360                    .join_span(&parser.consume_keyword(Keyword::JOIN)?),
361            ),
362            Token::Ident(_, Keyword::CROSS) => JoinType::Cross(
363                parser
364                    .consume_keyword(Keyword::CROSS)?
365                    .join_span(&parser.consume_keyword(Keyword::JOIN)?),
366            ),
367            Token::Ident(_, Keyword::JOIN) => {
368                JoinType::Normal(parser.consume_keyword(Keyword::JOIN)?)
369            }
370            Token::Ident(_, Keyword::STRAIGHT_JOIN) => {
371                JoinType::Straight(parser.consume_keyword(Keyword::STRAIGHT_JOIN)?)
372            }
373            Token::Ident(_, Keyword::LEFT) => {
374                let left = parser.consume_keyword(Keyword::LEFT)?;
375                if let Some(outer) = parser.skip_keyword(Keyword::OUTER) {
376                    JoinType::Left(
377                        left.join_span(&outer)
378                            .join_span(&parser.consume_keyword(Keyword::JOIN)?),
379                    )
380                } else {
381                    JoinType::Left(left.join_span(&parser.consume_keyword(Keyword::JOIN)?))
382                }
383            }
384            Token::Ident(_, Keyword::RIGHT) => {
385                let right = parser.consume_keyword(Keyword::RIGHT)?;
386                if let Some(outer) = parser.skip_keyword(Keyword::OUTER) {
387                    JoinType::Right(
388                        right
389                            .join_span(&outer)
390                            .join_span(&parser.consume_keyword(Keyword::JOIN)?),
391                    )
392                } else {
393                    JoinType::Right(right.join_span(&parser.consume_keyword(Keyword::JOIN)?))
394                }
395            }
396            Token::Ident(_, Keyword::NATURAL) => {
397                let natural = parser.consume_keyword(Keyword::NATURAL)?;
398                match &parser.token {
399                    Token::Ident(_, Keyword::INNER) => JoinType::NaturalInner(
400                        natural
401                            .join_span(&parser.consume_keywords(&[Keyword::INNER, Keyword::JOIN])?),
402                    ),
403                    Token::Ident(_, Keyword::LEFT) => {
404                        let left = parser.consume_keyword(Keyword::LEFT)?;
405                        if let Some(outer) = parser.skip_keyword(Keyword::OUTER) {
406                            JoinType::NaturalLeft(
407                                left.join_span(&outer)
408                                    .join_span(&parser.consume_keyword(Keyword::JOIN)?),
409                            )
410                        } else {
411                            JoinType::NaturalLeft(
412                                left.join_span(&parser.consume_keyword(Keyword::JOIN)?),
413                            )
414                        }
415                    }
416                    Token::Ident(_, Keyword::RIGHT) => {
417                        let right = parser.consume_keyword(Keyword::RIGHT)?;
418                        if let Some(outer) = parser.skip_keyword(Keyword::OUTER) {
419                            JoinType::NaturalRight(
420                                right
421                                    .join_span(&outer)
422                                    .join_span(&parser.consume_keyword(Keyword::JOIN)?),
423                            )
424                        } else {
425                            JoinType::NaturalRight(
426                                right.join_span(&parser.consume_keyword(Keyword::JOIN)?),
427                            )
428                        }
429                    }
430                    Token::Ident(_, Keyword::JOIN) => JoinType::Natural(
431                        natural.join_span(&parser.consume_keyword(Keyword::JOIN)?),
432                    ),
433                    _ => parser.expected_failure("'INNER', 'LEFT', 'RIGHT' or 'JOIN'")?,
434                }
435            }
436            _ => break,
437        };
438
439        let right = parse_table_reference_inner(parser)?;
440
441        let specification = match &parser.token {
442            Token::Ident(_, Keyword::ON) => {
443                let on = parser.consume_keyword(Keyword::ON)?;
444                let expr = parse_expression(parser, false)?;
445                Some(JoinSpecification::On(expr, on))
446            }
447            Token::Ident(_, Keyword::USING) => {
448                let using = parser.consume_keyword(Keyword::USING)?;
449                let mut join_column_list = Vec::new();
450                loop {
451                    join_column_list.push(parser.consume_plain_identifier()?);
452                    if parser.skip_token(Token::Comma).is_none() {
453                        break;
454                    }
455                }
456                Some(JoinSpecification::Using(join_column_list, using))
457            }
458            _ => None,
459        };
460
461        ans = TableReference::Join {
462            join,
463            left: Box::new(ans),
464            right: Box::new(right),
465            specification,
466        };
467    }
468    Ok(ans)
469}
470
471/// Flags specified after SELECT
472#[derive(Debug, Clone)]
473pub enum SelectFlag {
474    All(Span),
475    Distinct(Span),
476    DistinctRow(Span),
477    HighPriority(Span),
478    StraightJoin(Span),
479    SqlSmallResult(Span),
480    SqlBigResult(Span),
481    SqlBufferResult(Span),
482    SqlNoCache(Span),
483    SqlCalcFoundRows(Span),
484}
485
486impl Spanned for SelectFlag {
487    fn span(&self) -> Span {
488        match &self {
489            SelectFlag::All(v) => v.span(),
490            SelectFlag::Distinct(v) => v.span(),
491            SelectFlag::DistinctRow(v) => v.span(),
492            SelectFlag::HighPriority(v) => v.span(),
493            SelectFlag::StraightJoin(v) => v.span(),
494            SelectFlag::SqlSmallResult(v) => v.span(),
495            SelectFlag::SqlBigResult(v) => v.span(),
496            SelectFlag::SqlBufferResult(v) => v.span(),
497            SelectFlag::SqlNoCache(v) => v.span(),
498            SelectFlag::SqlCalcFoundRows(v) => v.span(),
499        }
500    }
501}
502
503/// Ordering direction
504#[derive(Debug, Clone)]
505pub enum OrderFlag {
506    Asc(Span),
507    Desc(Span),
508    None,
509}
510impl OptSpanned for OrderFlag {
511    fn opt_span(&self) -> Option<Span> {
512        match &self {
513            OrderFlag::Asc(v) => v.opt_span(),
514            OrderFlag::Desc(v) => v.opt_span(),
515            OrderFlag::None => None,
516        }
517    }
518}
519
520/// Lock strength for locking
521#[derive(Debug, Clone)]
522pub enum LockStrength {
523    Update(Span),
524    Share(Span),
525    NoKeyUpdate(Span),
526    KeyShare(Span),
527}
528impl Spanned for LockStrength {
529    fn span(&self) -> Span {
530        match &self {
531            LockStrength::Update(v) => v.span(),
532            LockStrength::Share(v) => v.span(),
533            LockStrength::NoKeyUpdate(v) => v.span(),
534            LockStrength::KeyShare(v) => v.span(),
535        }
536    }
537}
538
539#[derive(Debug, Clone)]
540pub enum LockWait {
541    NoWait(Span),
542    SkipLocket(Span),
543    Default,
544}
545impl OptSpanned for LockWait {
546    fn opt_span(&self) -> Option<Span> {
547        match &self {
548            LockWait::NoWait(v) => v.opt_span(),
549            LockWait::SkipLocket(v) => v.opt_span(),
550            LockWait::Default => None,
551        }
552    }
553}
554
555#[derive(Debug, Clone)]
556pub struct Locking<'a> {
557    /// Span of "FOR"
558    pub for_span: Span,
559    pub strength: LockStrength,
560    pub of: Option<(Span, Vec<Identifier<'a>>)>,
561    pub wait: LockWait,
562}
563impl<'a> Spanned for Locking<'a> {
564    fn span(&self) -> Span {
565        self.for_span
566            .join_span(&self.strength)
567            .join_span(&self.of)
568            .join_span(&self.wait)
569    }
570}
571
572/// Representation of select Statement
573///
574/// ```
575/// # use sql_parse::{SQLDialect, SQLArguments, ParseOptions, parse_statement, Select, Statement, Issues};
576/// # let options = ParseOptions::new().dialect(SQLDialect::MariaDB);
577/// #
578/// let sql = "SELECT f1,f2 FROM t1 WHERE f3<=10 AND f4='y'";
579/// let mut issues = Issues::new(sql);
580/// let stmt = parse_statement(sql, &mut issues, &options);
581///
582/// # assert!(issues.is_ok());
583/// let s: Select = match stmt {
584///     Some(Statement::Select(s)) => s,
585///     _ => panic!("We should get an select statement")
586/// };
587///
588/// println!("{:#?}", s.where_);
589///
590/// let sql = "SELECT CAST(NULL AS CHAR)";
591/// let stmt = parse_statement(sql, &mut issues, &options);
592///
593/// # assert!(issues.is_ok());
594/// let s: Select = match stmt {
595///     Some(Statement::Select(s)) => s,
596///     _ => panic!("We should get an select statement")
597/// };
598///
599/// println!("{:#?}", s.where_);
600///
601/// let sql = "SELECT * FROM t1, d2.t2 FOR SHARE OF t1, t2 NOWAIT";
602/// let stmt = parse_statement(sql, &mut issues, &options);
603///
604/// # assert!(issues.is_ok());
605/// let s: Select = match stmt {
606///     Some(Statement::Select(s)) => s,
607///     _ => panic!("We should get an select statement")
608/// };
609///
610/// assert!(s.locking.is_some());
611/// println!("{:#?}", s.locking);
612/// ```
613#[derive(Debug, Clone)]
614pub struct Select<'a> {
615    /// Span of "SELECT"
616    pub select_span: Span,
617    /// Flags specified after "SELECT"
618    pub flags: Vec<SelectFlag>,
619    /// List of values to select
620    pub select_exprs: Vec<SelectExpr<'a>>,
621    /// Span of "FROM"
622    pub from_span: Option<Span>,
623    /// List of tables to select from
624    pub table_references: Option<Vec<TableReference<'a>>>,
625    /// Where expression and span of "WHERE" if specified
626    pub where_: Option<(Expression<'a>, Span)>,
627    /// Span of "GROUP_BY" and group expression if specified
628    pub group_by: Option<(Span, Vec<Expression<'a>>)>,
629    /// Having expression and span of "HAVING" if specified
630    pub having: Option<(Expression<'a>, Span)>,
631    /// Span of window if specified
632    pub window_span: Option<Span>,
633    /// Span of "ORDER BY" and list of order expression and directions, if specified
634    pub order_by: Option<(Span, Vec<(Expression<'a>, OrderFlag)>)>,
635    /// Span of "LIMIT", offset and count expressions if specified
636    pub limit: Option<(Span, Option<Expression<'a>>, Expression<'a>)>,
637    /// Row locking clause
638    pub locking: Option<Locking<'a>>,
639}
640
641impl<'a> Spanned for Select<'a> {
642    fn span(&self) -> Span {
643        self.select_span
644            .join_span(&self.flags)
645            .join_span(&self.select_exprs)
646            .join_span(&self.from_span)
647            .join_span(&self.table_references)
648            .join_span(&self.where_)
649            .join_span(&self.group_by)
650            .join_span(&self.having)
651            .join_span(&self.window_span)
652            .join_span(&self.order_by)
653            .join_span(&self.limit)
654    }
655}
656
657pub(crate) fn parse_select<'a>(parser: &mut Parser<'a, '_>) -> Result<Select<'a>, ParseError> {
658    let select_span = parser.consume_keyword(Keyword::SELECT)?;
659    let mut flags = Vec::new();
660    let mut select_exprs = Vec::new();
661
662    loop {
663        match &parser.token {
664            Token::Ident(_, Keyword::ALL) => {
665                flags.push(SelectFlag::All(parser.consume_keyword(Keyword::ALL)?))
666            }
667            Token::Ident(_, Keyword::DISTINCT) => flags.push(SelectFlag::Distinct(
668                parser.consume_keyword(Keyword::DISTINCT)?,
669            )),
670            Token::Ident(_, Keyword::DISTINCTROW) => flags.push(SelectFlag::DistinctRow(
671                parser.consume_keyword(Keyword::DISTINCTROW)?,
672            )),
673            Token::Ident(_, Keyword::HIGH_PRIORITY) => flags.push(SelectFlag::HighPriority(
674                parser.consume_keyword(Keyword::HIGH_PRIORITY)?,
675            )),
676            Token::Ident(_, Keyword::STRAIGHT_JOIN) => flags.push(SelectFlag::StraightJoin(
677                parser.consume_keyword(Keyword::STRAIGHT_JOIN)?,
678            )),
679            Token::Ident(_, Keyword::SQL_SMALL_RESULT) => flags.push(SelectFlag::SqlSmallResult(
680                parser.consume_keyword(Keyword::SQL_SMALL_RESULT)?,
681            )),
682            Token::Ident(_, Keyword::SQL_BIG_RESULT) => flags.push(SelectFlag::SqlBigResult(
683                parser.consume_keyword(Keyword::SQL_BIG_RESULT)?,
684            )),
685            Token::Ident(_, Keyword::SQL_BUFFER_RESULT) => flags.push(SelectFlag::SqlBufferResult(
686                parser.consume_keyword(Keyword::SQL_BUFFER_RESULT)?,
687            )),
688            Token::Ident(_, Keyword::SQL_NO_CACHE) => flags.push(SelectFlag::SqlNoCache(
689                parser.consume_keyword(Keyword::SQL_NO_CACHE)?,
690            )),
691            Token::Ident(_, Keyword::SQL_CALC_FOUND_ROWS) => flags.push(
692                SelectFlag::SqlCalcFoundRows(parser.consume_keyword(Keyword::SQL_CALC_FOUND_ROWS)?),
693            ),
694            _ => break,
695        }
696    }
697
698    loop {
699        select_exprs.push(parse_select_expr(parser)?);
700        if parser.skip_token(Token::Comma).is_none() {
701            break;
702        }
703    }
704
705    // TODO [into_option]
706
707    let from_span = match parser.skip_keyword(Keyword::FROM) {
708        Some(v) => Some(v),
709        None => {
710            return Ok(Select {
711                select_span,
712                flags,
713                select_exprs,
714                from_span: None,
715                table_references: None,
716                where_: None,
717                group_by: None,
718                having: None,
719                window_span: None,
720                order_by: None,
721                limit: None,
722                locking: None,
723            })
724        }
725    };
726
727    let mut table_references = Vec::new();
728    loop {
729        table_references.push(parse_table_reference(parser)?);
730        if parser.skip_token(Token::Comma).is_none() {
731            break;
732        }
733    }
734
735    // TODO PARTITION partition_list;
736    let where_ = if let Some(span) = parser.skip_keyword(Keyword::WHERE) {
737        Some((parse_expression(parser, false)?, span))
738    } else {
739        None
740    };
741
742    let group_by = if let Some(group_span) = parser.skip_keyword(Keyword::GROUP) {
743        let span = parser.consume_keyword(Keyword::BY)?.join_span(&group_span);
744        let mut groups = Vec::new();
745        loop {
746            groups.push(parse_expression(parser, false)?);
747            if parser.skip_token(Token::Comma).is_none() {
748                break;
749            }
750        }
751        // TODO [WITH ROLLUP]]
752        Some((span, groups))
753    } else {
754        None
755    };
756
757    let having = if let Some(span) = parser.skip_keyword(Keyword::HAVING) {
758        Some((parse_expression(parser, false)?, span))
759    } else {
760        None
761    };
762
763    let window_span = parser.skip_keyword(Keyword::WINDOW);
764    if window_span.is_some() {
765        //TODO window_name AS (window_spec) [, window_name AS (window_spec)] ...]
766    }
767
768    let order_by = if let Some(span) = parser.skip_keyword(Keyword::ORDER) {
769        let span = parser.consume_keyword(Keyword::BY)?.join_span(&span);
770        let mut order = Vec::new();
771        loop {
772            let e = parse_expression(parser, false)?;
773            let f = match &parser.token {
774                Token::Ident(_, Keyword::ASC) => OrderFlag::Asc(parser.consume()),
775                Token::Ident(_, Keyword::DESC) => OrderFlag::Desc(parser.consume()),
776                _ => OrderFlag::None,
777            };
778            order.push((e, f));
779            if parser.skip_token(Token::Comma).is_none() {
780                break;
781            }
782        }
783        Some((span, order))
784    } else {
785        None
786    };
787
788    let limit = if let Some(span) = parser.skip_keyword(Keyword::LIMIT) {
789        let n = parse_expression(parser, true)?;
790        match parser.token {
791            Token::Comma => {
792                parser.consume();
793                Some((span, Some(n), parse_expression(parser, true)?))
794            }
795            Token::Ident(_, Keyword::OFFSET) => {
796                parser.consume();
797                Some((span, Some(parse_expression(parser, true)?), n))
798            }
799            _ => Some((span, None, n)),
800        }
801    } else {
802        None
803    };
804
805    let locking = if let Some(for_span) = parser.skip_keyword(Keyword::FOR) {
806        let strength = match &parser.token {
807            Token::Ident(_, Keyword::UPDATE) => {
808                LockStrength::Update(parser.consume_keyword(Keyword::UPDATE)?)
809            }
810            Token::Ident(_, Keyword::SHARE) => {
811                LockStrength::Share(parser.consume_keyword(Keyword::SHARE)?)
812            }
813            Token::Ident(_, Keyword::NO) => {
814                LockStrength::NoKeyUpdate(parser.consume_keywords(&[
815                    Keyword::NO,
816                    Keyword::KEY,
817                    Keyword::UPDATE,
818                ])?)
819            }
820            Token::Ident(_, Keyword::KEY) => {
821                LockStrength::KeyShare(parser.consume_keywords(&[Keyword::KEY, Keyword::SHARE])?)
822            }
823            _ => parser.expected_failure("UPDATE, SHARE, NO KEY UPDATE or KEY SHARE here")?,
824        };
825
826        if let LockStrength::NoKeyUpdate(s) | LockStrength::KeyShare(s) = &strength {
827            if !parser.options.dialect.is_postgresql() {
828                parser.err("Only support by PostgreSQL", s);
829            }
830        }
831
832        let of = if let Some(of_span) = parser.skip_keyword(Keyword::OF) {
833            let mut table_references = Vec::new();
834            loop {
835                table_references.push(parser.consume_plain_identifier()?);
836                if parser.skip_token(Token::Comma).is_none() {
837                    break;
838                }
839            }
840            Some((of_span, table_references))
841        } else {
842            None
843        };
844
845        let wait = match &parser.token {
846            Token::Ident(_, Keyword::NOWAIT) => {
847                LockWait::NoWait(parser.consume_keyword(Keyword::NOWAIT)?)
848            }
849            Token::Ident(_, Keyword::SKIP) => {
850                LockWait::SkipLocket(parser.consume_keywords(&[Keyword::SKIP, Keyword::LOCKED])?)
851            }
852            _ => LockWait::Default,
853        };
854        Some(Locking {
855            for_span,
856            strength,
857            of,
858            wait,
859        })
860    } else {
861        None
862    };
863
864    // TODO [into_option]
865    // [into_option]
866
867    // into_option: {
868    // INTO OUTFILE 'file_name'
869    //     [CHARACTER SET charset_name]
870    //     export_options
871    // | INTO DUMPFILE 'file_name'
872    // | INTO var_name [, var_name] ...
873    // }
874
875    Ok(Select {
876        select_span,
877        flags,
878        select_exprs,
879        from_span,
880        table_references: Some(table_references),
881        where_,
882        group_by,
883        having,
884        window_span,
885        order_by,
886        limit,
887        locking,
888    })
889}