1use alloc::boxed::Box;
2
3use crate::{
4 SString, Span, Spanned, Statement,
5 expression::{Expression, PRIORITY_MAX, parse_expression_unreserved},
6 keywords::Keyword,
7 lexer::Token,
8 parser::{ParseError, Parser},
9 qualified_name::parse_qualified_name_unreserved,
10};
11
12#[derive(Clone, Debug)]
29pub struct ShowTables<'a> {
30 pub show_span: Span,
31 pub tables_span: Span,
32 pub extended: Option<Span>,
33 pub full: Option<Span>,
34 pub db: Option<crate::QualifiedName<'a>>,
35 pub like: Option<SString<'a>>,
36 pub where_expr: Option<Expression<'a>>,
37}
38
39impl<'a> Spanned for ShowTables<'a> {
40 fn span(&self) -> Span {
41 self.show_span
42 .join_span(&self.tables_span)
43 .join_span(&self.extended)
44 .join_span(&self.full)
45 .join_span(&self.db)
46 .join_span(&self.like)
47 .join_span(&self.where_expr)
48 }
49}
50
51fn parse_show_tables<'a>(
52 parser: &mut Parser<'a, '_>,
53 show_span: Span,
54 extended: Option<Span>,
55 full: Option<Span>,
56) -> Result<ShowTables<'a>, ParseError> {
57 let tables_span = parser.consume_keyword(Keyword::TABLES)?;
58
59 let mut db = None;
61 match &parser.token {
62 Token::Ident(_, Keyword::FROM) => {
63 parser.consume_keyword(Keyword::FROM)?;
64 let q = parse_qualified_name_unreserved(parser)?;
66 db = Some(q);
67 }
68 Token::Ident(_, Keyword::IN) => {
69 parser.consume_keyword(Keyword::IN)?;
70 let q = parse_qualified_name_unreserved(parser)?;
71 db = Some(q);
72 }
73 _ => {}
74 }
75
76 let like = if parser.skip_keyword(Keyword::LIKE).is_some() {
78 Some(parser.consume_string()?)
79 } else {
80 None
81 };
82 let where_expr = if like.is_none() && parser.skip_keyword(Keyword::WHERE).is_some() {
83 Some(parse_expression_unreserved(parser, PRIORITY_MAX)?)
84 } else {
85 None
86 };
87
88 Ok(ShowTables {
89 show_span,
90 tables_span,
91 extended,
92 full,
93 db,
94 like,
95 where_expr,
96 })
97}
98
99#[derive(Clone, Debug)]
114pub struct ShowDatabases {
115 pub show_span: Span,
116 pub databases_span: Span,
117}
118
119impl Spanned for ShowDatabases {
120 fn span(&self) -> Span {
121 self.show_span.clone().join_span(&self.databases_span)
122 }
123}
124
125fn parse_show_databases<'a>(
126 parser: &mut Parser<'a, '_>,
127 show_span: Span,
128) -> Result<ShowDatabases, ParseError> {
129 let databases_span = parser.consume_keyword(Keyword::DATABASES)?;
130 Ok(ShowDatabases {
131 show_span,
132 databases_span,
133 })
134}
135
136#[derive(Clone, Debug)]
152pub struct ShowProcessList {
153 pub show_span: Span,
154 pub process_span: Span,
155}
156
157impl Spanned for ShowProcessList {
158 fn span(&self) -> Span {
159 self.show_span.clone().join_span(&self.process_span)
160 }
161}
162
163fn parse_show_processlist<'a>(
164 parser: &mut Parser<'a, '_>,
165 show_span: Span,
166 _full: Option<Span>,
167) -> Result<ShowProcessList, ParseError> {
168 match &parser.token {
169 Token::Ident(_, Keyword::PROCESSLIST) => {
170 let process_span = parser.consume_keyword(Keyword::PROCESSLIST)?;
171 Ok(ShowProcessList {
172 show_span,
173 process_span,
174 })
175 }
176 Token::Ident(_, Keyword::PROCESS) => {
177 let process_span = parser.consume_keyword(Keyword::PROCESS)?;
178 Ok(ShowProcessList {
179 show_span,
180 process_span,
181 })
182 }
183 _ => parser.expected_failure("'PROCESS' | 'PROCESSLIST'"),
184 }
185}
186
187#[derive(Clone, Debug)]
204pub struct ShowVariables<'a> {
205 pub show_span: Span,
206 pub variables_span: Span,
207 pub global_span: Option<Span>,
208 pub session_span: Option<Span>,
209 pub like: Option<SString<'a>>,
210 pub where_expr: Option<Expression<'a>>,
211}
212
213impl<'a> Spanned for ShowVariables<'a> {
214 fn span(&self) -> Span {
215 self.show_span
216 .join_span(&self.variables_span)
217 .join_span(&self.global_span)
218 .join_span(&self.session_span)
219 .join_span(&self.like)
220 .join_span(&self.where_expr)
221 }
222}
223
224fn parse_show_variables<'a>(
225 parser: &mut Parser<'a, '_>,
226 show_span: Span,
227 global_span: Option<Span>,
228 session_span: Option<Span>,
229) -> Result<ShowVariables<'a>, ParseError> {
230 let variables_span = parser.consume_keyword(Keyword::VARIABLES)?;
231 let like = if parser.skip_keyword(Keyword::LIKE).is_some() {
232 Some(parser.consume_string()?)
233 } else {
234 None
235 };
236 let where_expr = if parser.skip_keyword(Keyword::WHERE).is_some() {
237 Some(parse_expression_unreserved(parser, PRIORITY_MAX)?)
238 } else {
239 None
240 };
241 Ok(ShowVariables {
242 show_span,
243 variables_span,
244 global_span,
245 session_span,
246 like,
247 where_expr,
248 })
249}
250
251#[derive(Clone, Debug)]
266pub struct ShowStatus<'a> {
267 pub show_span: Span,
268 pub status_span: Span,
269 pub global_span: Option<Span>,
270 pub session_span: Option<Span>,
271 pub like: Option<SString<'a>>,
272 pub where_expr: Option<Expression<'a>>,
273}
274
275impl<'a> Spanned for ShowStatus<'a> {
276 fn span(&self) -> Span {
277 self.show_span
278 .join_span(&self.status_span)
279 .join_span(&self.like)
280 .join_span(&self.where_expr)
281 }
282}
283
284fn parse_show_status<'a>(
285 parser: &mut Parser<'a, '_>,
286 show_span: Span,
287 global_span: Option<Span>,
288 session_span: Option<Span>,
289) -> Result<ShowStatus<'a>, ParseError> {
290 let status_span = parser.consume_keyword(Keyword::STATUS)?;
291 let like = if parser.skip_keyword(Keyword::LIKE).is_some() {
292 Some(parser.consume_string()?)
293 } else {
294 None
295 };
296 let where_expr = if parser.skip_keyword(Keyword::WHERE).is_some() {
297 Some(parse_expression_unreserved(parser, PRIORITY_MAX)?)
298 } else {
299 None
300 };
301 Ok(ShowStatus {
302 show_span,
303 status_span,
304 global_span,
305 session_span,
306 like,
307 where_expr,
308 })
309}
310
311#[derive(Clone, Debug)]
328pub struct ShowColumns<'a> {
329 pub show_span: Span,
330 pub columns_span: Span,
331 pub extended: Option<Span>,
332 pub full: Option<Span>,
333 pub table: Option<crate::QualifiedName<'a>>,
334 pub db: Option<crate::QualifiedName<'a>>,
335 pub like: Option<SString<'a>>,
336 pub where_expr: Option<Expression<'a>>,
337}
338
339impl<'a> Spanned for ShowColumns<'a> {
340 fn span(&self) -> Span {
341 self.show_span
342 .join_span(&self.columns_span)
343 .join_span(&self.table)
344 .join_span(&self.db)
345 .join_span(&self.like)
346 .join_span(&self.where_expr)
347 }
348}
349
350fn parse_show_columns<'a>(
351 parser: &mut Parser<'a, '_>,
352 show_span: Span,
353 extended: Option<Span>,
354 full: Option<Span>,
355) -> Result<ShowColumns<'a>, ParseError> {
356 let columns_span = match &parser.token {
357 Token::Ident(_, Keyword::COLUMNS) => parser.consume_keyword(Keyword::COLUMNS)?,
358 _ => parser.consume_keyword(Keyword::FIELDS)?,
359 };
360 let mut table = None;
361 let mut db = None;
362 if parser.skip_keyword(Keyword::FROM).is_some() || parser.skip_keyword(Keyword::IN).is_some() {
364 let q = parse_qualified_name_unreserved(parser)?;
365 table = Some(q);
366 }
367 if table.is_some() {
369 match &parser.token {
370 Token::Ident(_, Keyword::FROM) => {
371 parser.consume_keyword(Keyword::FROM)?;
372 let q = parse_qualified_name_unreserved(parser)?;
373 db = Some(q);
374 }
375 Token::Ident(_, Keyword::IN) => {
376 parser.consume_keyword(Keyword::IN)?;
377 let q = parse_qualified_name_unreserved(parser)?;
378 db = Some(q);
379 }
380 _ => {}
381 }
382 }
383 let like = if parser.skip_keyword(Keyword::LIKE).is_some() {
384 Some(parser.consume_string()?)
385 } else {
386 None
387 };
388 let where_expr = if like.is_none() && parser.skip_keyword(Keyword::WHERE).is_some() {
389 Some(parse_expression_unreserved(parser, PRIORITY_MAX)?)
390 } else {
391 None
392 };
393 Ok(ShowColumns {
394 show_span,
395 columns_span,
396 extended,
397 full,
398 table,
399 db,
400 like,
401 where_expr,
402 })
403}
404
405#[derive(Clone, Debug)]
422pub struct ShowCharacterSet<'a> {
423 pub show_span: Span,
424 pub character_span: Option<Span>,
425 pub set_span: Span,
426 pub like: Option<SString<'a>>,
427 pub where_expr: Option<Expression<'a>>,
428}
429
430impl<'a> Spanned for ShowCharacterSet<'a> {
431 fn span(&self) -> Span {
432 self.show_span
433 .join_span(&self.character_span)
434 .join_span(&self.set_span)
435 .join_span(&self.like)
436 .join_span(&self.where_expr)
437 }
438}
439
440fn parse_show_character_set<'a>(
441 parser: &mut Parser<'a, '_>,
442 show_span: Span,
443) -> Result<ShowCharacterSet<'a>, ParseError> {
444 let mut character_span: Option<Span> = None;
446 let set_span = match &parser.token {
447 Token::Ident(_, Keyword::CHARSET) => parser.consume_keyword(Keyword::CHARSET)?,
448 Token::Ident(_, Keyword::CHARACTER) => {
449 character_span = Some(parser.consume_keyword(Keyword::CHARACTER)?);
450 parser.consume_keyword(Keyword::SET)?
451 }
452 _ => return parser.expected_failure("'CHARSET' | 'CHARACTER'"),
453 };
454
455 let mut like: Option<SString<'a>> = None;
456 let mut where_expr: Option<Expression<'a>> = None;
457 if parser.skip_keyword(Keyword::LIKE).is_some() {
458 like = Some(parser.consume_string()?);
459 } else if parser.skip_keyword(Keyword::WHERE).is_some() {
460 where_expr = Some(parse_expression_unreserved(parser, PRIORITY_MAX)?);
461 }
462
463 Ok(ShowCharacterSet {
464 show_span,
465 character_span,
466 set_span,
467 like,
468 where_expr,
469 })
470}
471
472#[derive(Clone, Debug)]
489pub struct ShowCreateTable<'a> {
490 pub show_span: Span,
491 pub create_span: Span,
492 pub object_span: Span,
493 pub table: crate::QualifiedName<'a>,
494}
495
496impl<'a> Spanned for ShowCreateTable<'a> {
497 fn span(&self) -> Span {
498 self.show_span
499 .join_span(&self.create_span)
500 .join_span(&self.object_span)
501 .join_span(&self.table)
502 }
503}
504
505#[derive(Clone, Debug)]
522pub struct ShowCreateDatabase<'a> {
523 pub show_span: Span,
524 pub create_span: Span,
525 pub object_span: Span,
526 pub db: crate::QualifiedName<'a>,
527}
528
529impl<'a> Spanned for ShowCreateDatabase<'a> {
530 fn span(&self) -> Span {
531 self.show_span
532 .join_span(&self.create_span)
533 .join_span(&self.object_span)
534 .join_span(&self.db)
535 }
536}
537
538#[derive(Clone, Debug)]
555pub struct ShowCreateView<'a> {
556 pub show_span: Span,
557 pub create_span: Span,
558 pub object_span: Span,
559 pub view: crate::QualifiedName<'a>,
560}
561
562impl<'a> Spanned for ShowCreateView<'a> {
563 fn span(&self) -> Span {
564 self.show_span
565 .join_span(&self.create_span)
566 .join_span(&self.object_span)
567 .join_span(&self.view)
568 }
569}
570
571fn parse_show_create<'a>(
572 parser: &mut Parser<'a, '_>,
573 show_span: Span,
574) -> Result<crate::Statement<'a>, ParseError> {
575 let create_span = parser.consume_keyword(Keyword::CREATE)?;
576 match &parser.token {
577 Token::Ident(_, Keyword::TABLE) => {
578 let object_span = parser.consume_keyword(Keyword::TABLE)?;
579 let table = parse_qualified_name_unreserved(parser)?;
580 Ok(crate::Statement::ShowCreateTable(Box::new(
581 ShowCreateTable {
582 show_span,
583 create_span,
584 object_span,
585 table,
586 },
587 )))
588 }
589 Token::Ident(_, Keyword::DATABASE) => {
590 let object_span = parser.consume_keyword(Keyword::DATABASE)?;
591 let db = parse_qualified_name_unreserved(parser)?;
592 Ok(crate::Statement::ShowCreateDatabase(Box::new(
593 ShowCreateDatabase {
594 show_span,
595 create_span,
596 object_span,
597 db,
598 },
599 )))
600 }
601 Token::Ident(_, Keyword::VIEW) => {
602 let object_span = parser.consume_keyword(Keyword::VIEW)?;
603 let view = parse_qualified_name_unreserved(parser)?;
604 Ok(crate::Statement::ShowCreateView(Box::new(ShowCreateView {
605 show_span,
606 create_span,
607 object_span,
608 view,
609 })))
610 }
611 _ => parser.expected_failure("'TABLE' | 'DATABASE' | 'VIEW'"),
612 }
613}
614
615#[derive(Clone, Debug)]
632pub struct ShowCollation<'a> {
633 pub show_span: Span,
634 pub collation_span: Span,
635 pub like: Option<SString<'a>>,
636 pub where_expr: Option<Expression<'a>>,
637}
638
639impl<'a> Spanned for ShowCollation<'a> {
640 fn span(&self) -> Span {
641 self.show_span
642 .join_span(&self.collation_span)
643 .join_span(&self.like)
644 .join_span(&self.where_expr)
645 }
646}
647
648fn parse_show_collation<'a>(
649 parser: &mut Parser<'a, '_>,
650 show_span: Span,
651) -> Result<ShowCollation<'a>, ParseError> {
652 let collation_span = parser.consume_keyword(Keyword::COLLATION)?;
653 let mut like: Option<SString<'a>> = None;
654 let mut where_expr: Option<Expression<'a>> = None;
655 if parser.skip_keyword(Keyword::LIKE).is_some() {
656 like = Some(parser.consume_string()?);
657 } else if parser.skip_keyword(Keyword::WHERE).is_some() {
658 where_expr = Some(parse_expression_unreserved(parser, PRIORITY_MAX)?);
659 }
660 Ok(ShowCollation {
661 show_span,
662 collation_span,
663 like,
664 where_expr,
665 })
666}
667
668#[derive(Clone, Debug)]
685pub struct ShowEngines {
686 pub show_span: Span,
687 pub engines_span: Span,
688}
689
690impl Spanned for ShowEngines {
691 fn span(&self) -> Span {
692 self.show_span.join_span(&self.engines_span)
693 }
694}
695
696fn parse_show_engines<'a>(
697 parser: &mut Parser<'a, '_>,
698 show_span: Span,
699) -> Result<ShowEngines, ParseError> {
700 let engines_span = parser.consume_keyword(Keyword::ENGINES)?;
701 Ok(ShowEngines {
702 show_span,
703 engines_span,
704 })
705}
706
707pub(crate) fn parse_show<'a>(
708 parser: &mut Parser<'a, '_>,
709) -> Result<crate::Statement<'a>, ParseError> {
710 let show_span = parser.consume_keyword(Keyword::SHOW)?;
711 let mut extended: Option<Span> = None;
713 let mut full: Option<Span> = None;
714 let mut global: Option<Span> = None;
715 let mut session: Option<Span> = None;
716 loop {
717 match &parser.token {
718 Token::Ident(_, Keyword::EXTENDED) => extended = Some(parser.consume()),
719 Token::Ident(_, Keyword::FULL) => full = Some(parser.consume()),
720 Token::Ident(_, Keyword::GLOBAL) => global = Some(parser.consume()),
721 Token::Ident(_, Keyword::SESSION) => session = Some(parser.consume()),
722 _ => break,
723 }
724 }
725
726 let stmt = match &parser.token {
727 Token::Ident(_, Keyword::TABLES) => Statement::ShowTables(Box::new(parse_show_tables(parser, show_span, extended.clone(), full.clone())?)),
728 Token::Ident(_, Keyword::CREATE) => parse_show_create(parser, show_span)?,
729 Token::Ident(_, Keyword::DATABASES) => Statement::ShowDatabases(Box::new(parse_show_databases(parser, show_span)?)),
730 Token::Ident(_, Keyword::PROCESSLIST | Keyword::PROCESS) => {
731 Statement::ShowProcessList(Box::new(parse_show_processlist(parser, show_span, full.clone())?))
732 }
733 Token::Ident(_, Keyword::VARIABLES) => Statement::ShowVariables(Box::new(parse_show_variables(parser, show_span, global.clone(), session.clone())?)),
734 Token::Ident(_, Keyword::STATUS) => Statement::ShowStatus(Box::new(parse_show_status(parser, show_span, global.clone(), session.clone())?)),
735 Token::Ident(_, Keyword::COLUMNS | Keyword::FIELDS) => {
736 Statement::ShowColumns(Box::new(parse_show_columns(parser, show_span, extended.clone(), full.clone())?))
737 }
738 Token::Ident(_, Keyword::CHARSET | Keyword::CHARACTER) => {
739 Statement::ShowCharacterSet(Box::new(parse_show_character_set(parser, show_span)?))
740 }
741 Token::Ident(_, Keyword::COLLATION) => Statement::ShowCollation(Box::new(parse_show_collation(parser, show_span)?)),
742 Token::Ident(_, Keyword::ENGINES) => Statement::ShowEngines(Box::new(parse_show_engines(parser, show_span)?)),
743 _ if parser.options.dialect.is_postgresql() => {
744 let var_span = parser.consume_plain_identifier_unreserved()?;
746 Statement::ShowVariables(Box::new(ShowVariables {
747 show_span: show_span.clone(),
748 variables_span: var_span.span(),
749 global_span: global.clone(),
750 session_span: session.clone(),
751 like: None,
752 where_expr: None,
753 }))
754 }
755 _ => return parser.expected_failure("'TABLES' | 'DATABASES' | 'PROCESS' | 'PROCESSLIST' | 'VARIABLES' | 'STATUS' | 'COLUMNS' | 'FIELDS' | 'CHARSET' | 'CHARACTER' | 'COLLATION' | 'ENGINES'"),
756 };
757
758 if let Some(span) = &extended {
760 match &stmt {
761 crate::Statement::ShowTables(_) => {}
762 crate::Statement::ShowColumns(_) => {}
763 _ => {
764 parser.warn(
765 "Modifier EXTENDED not supported for this SHOW variant",
766 span,
767 );
768 }
769 }
770 }
771
772 if let Some(span) = &full {
773 match &stmt {
774 crate::Statement::ShowTables(_) => {}
775 crate::Statement::ShowProcessList(_) => {}
776 crate::Statement::ShowColumns(_) => {}
777 _ => {
778 parser.warn("Modifier FULL not supported for this SHOW variant", span);
779 }
780 }
781 }
782
783 if let Some(span) = &global {
784 match &stmt {
785 crate::Statement::ShowStatus(_) => {}
786 crate::Statement::ShowVariables(_) => {}
787 _ => {
788 parser.warn("Modifier GLOBAL not supported for this SHOW variant", span);
789 }
790 }
791 }
792
793 if let Some(span) = &session {
794 match &stmt {
795 crate::Statement::ShowStatus(_) => {}
796 crate::Statement::ShowVariables(_) => {}
797 _ => {
798 parser.warn("Modifier SESSION not supported for this SHOW variant", span);
799 }
800 }
801 }
802
803 Ok(stmt)
804}