1use 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#[derive(Debug, Clone)]
28pub struct SelectExpr<'a> {
29 pub expr: Expression<'a>,
31 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#[derive(Debug, Clone)]
55pub enum JoinSpecification<'a> {
56 On(Expression<'a>, Span),
58 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#[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#[derive(Debug, Clone)]
172pub enum TableReference<'a> {
173 Table {
175 identifier: QualifiedName<'a>,
177 as_span: Option<Span>,
179 as_: Option<Identifier<'a>>,
181 index_hints: Vec<IndexHint<'a>>,
183 },
184 Query {
186 query: Box<Statement<'a>>,
188 as_span: Option<Span>,
190 as_: Option<Identifier<'a>>,
192 },
194 Join {
196 join: JoinType,
198 left: Box<TableReference<'a>>,
200 right: Box<TableReference<'a>>,
202 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 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 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#[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#[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#[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 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#[derive(Debug, Clone)]
614pub struct Select<'a> {
615 pub select_span: Span,
617 pub flags: Vec<SelectFlag>,
619 pub select_exprs: Vec<SelectExpr<'a>>,
621 pub from_span: Option<Span>,
623 pub table_references: Option<Vec<TableReference<'a>>>,
625 pub where_: Option<(Expression<'a>, Span)>,
627 pub group_by: Option<(Span, Vec<Expression<'a>>)>,
629 pub having: Option<(Expression<'a>, Span)>,
631 pub window_span: Option<Span>,
633 pub order_by: Option<(Span, Vec<(Expression<'a>, OrderFlag)>)>,
635 pub limit: Option<(Span, Option<Expression<'a>>, Expression<'a>)>,
637 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 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 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 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 }
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 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}