1#[cfg(not(feature = "std"))]
19use crate::alloc::string::ToString;
20use crate::ast::helpers::attached_token::AttachedToken;
21use crate::ast::helpers::key_value_options::{
22 KeyValueOption, KeyValueOptionKind, KeyValueOptions, KeyValueOptionsDelimiter,
23};
24use crate::ast::helpers::stmt_create_database::CreateDatabaseBuilder;
25use crate::ast::helpers::stmt_create_table::CreateTableBuilder;
26use crate::ast::helpers::stmt_data_loading::{
27 FileStagingCommand, StageLoadSelectItem, StageLoadSelectItemKind, StageParamsObject,
28};
29use crate::ast::{
30 AlterTable, AlterTableOperation, AlterTableType, CatalogSyncNamespaceMode, ColumnOption,
31 ColumnPolicy, ColumnPolicyProperty, ContactEntry, CopyIntoSnowflakeKind, CreateTable,
32 CreateTableLikeKind, DollarQuotedString, Ident, IdentityParameters, IdentityProperty,
33 IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, InitializeKind,
34 Insert, MultiTableInsertIntoClause, MultiTableInsertType, MultiTableInsertValue,
35 MultiTableInsertValues, MultiTableInsertWhenClause, ObjectName, ObjectNamePart,
36 RefreshModeKind, RowAccessPolicy, ShowObjects, SqlOption, Statement, StorageLifecyclePolicy,
37 StorageSerializationPolicy, TableObject, TagsColumnOption, Value, WrappedCollection,
38};
39use crate::dialect::{Dialect, Precedence};
40use crate::keywords::Keyword;
41use crate::parser::{IsOptional, Parser, ParserError};
42use crate::tokenizer::TokenWithSpan;
43use crate::tokenizer::{Span, Token};
44#[cfg(not(feature = "std"))]
45use alloc::boxed::Box;
46#[cfg(not(feature = "std"))]
47use alloc::string::String;
48#[cfg(not(feature = "std"))]
49use alloc::vec::Vec;
50#[cfg(not(feature = "std"))]
51use alloc::{format, vec};
52
53use super::keywords::RESERVED_FOR_IDENTIFIER;
54
55const RESERVED_KEYWORDS_FOR_SELECT_ITEM_OPERATOR: [Keyword; 1] = [Keyword::CONNECT_BY_ROOT];
56
57const RESERVED_KEYWORDS_FOR_TABLE_FACTOR: &[Keyword] = &[
59 Keyword::ALL,
60 Keyword::ALTER,
61 Keyword::AND,
62 Keyword::ANY,
63 Keyword::AS,
64 Keyword::BETWEEN,
65 Keyword::BY,
66 Keyword::CHECK,
67 Keyword::COLUMN,
68 Keyword::CONNECT,
69 Keyword::CREATE,
70 Keyword::CROSS,
71 Keyword::CURRENT,
72 Keyword::DELETE,
73 Keyword::DISTINCT,
74 Keyword::DROP,
75 Keyword::ELSE,
76 Keyword::EXISTS,
77 Keyword::FOLLOWING,
78 Keyword::FOR,
79 Keyword::FROM,
80 Keyword::FULL,
81 Keyword::GRANT,
82 Keyword::GROUP,
83 Keyword::HAVING,
84 Keyword::ILIKE,
85 Keyword::IN,
86 Keyword::INCREMENT,
87 Keyword::INNER,
88 Keyword::INSERT,
89 Keyword::INTERSECT,
90 Keyword::INTO,
91 Keyword::IS,
92 Keyword::JOIN,
93 Keyword::LEFT,
94 Keyword::LIKE,
95 Keyword::MINUS,
96 Keyword::NATURAL,
97 Keyword::NOT,
98 Keyword::NULL,
99 Keyword::OF,
100 Keyword::ON,
101 Keyword::OR,
102 Keyword::ORDER,
103 Keyword::QUALIFY,
104 Keyword::REGEXP,
105 Keyword::REVOKE,
106 Keyword::RIGHT,
107 Keyword::RLIKE,
108 Keyword::ROW,
109 Keyword::ROWS,
110 Keyword::SAMPLE,
111 Keyword::SELECT,
112 Keyword::SET,
113 Keyword::SOME,
114 Keyword::START,
115 Keyword::TABLE,
116 Keyword::TABLESAMPLE,
117 Keyword::THEN,
118 Keyword::TO,
119 Keyword::TRIGGER,
120 Keyword::UNION,
121 Keyword::UNIQUE,
122 Keyword::UPDATE,
123 Keyword::USING,
124 Keyword::VALUES,
125 Keyword::WHEN,
126 Keyword::WHENEVER,
127 Keyword::WHERE,
128 Keyword::WINDOW,
129 Keyword::WITH,
130];
131
132#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
134#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
135pub struct SnowflakeDialect;
136
137impl Dialect for SnowflakeDialect {
138 fn is_identifier_start(&self, ch: char) -> bool {
140 ch.is_ascii_lowercase() || ch.is_ascii_uppercase() || ch == '_'
141 }
142
143 fn identifier_quote_style(&self, _identifier: &str) -> Option<char> {
145 Some('"')
146 }
147
148 fn supports_projection_trailing_commas(&self) -> bool {
149 true
150 }
151
152 fn supports_from_trailing_commas(&self) -> bool {
153 true
154 }
155
156 fn supports_order_by_all(&self) -> bool {
158 true
159 }
160
161 fn supports_object_name_double_dot_notation(&self) -> bool {
166 true
167 }
168
169 fn is_identifier_part(&self, ch: char) -> bool {
170 ch.is_ascii_lowercase()
171 || ch.is_ascii_uppercase()
172 || ch.is_ascii_digit()
173 || ch == '$'
174 || ch == '_'
175 }
176
177 fn supports_string_literal_backslash_escape(&self) -> bool {
179 true
180 }
181
182 fn supports_within_after_array_aggregation(&self) -> bool {
183 true
184 }
185
186 fn supports_outer_join_operator(&self) -> bool {
188 true
189 }
190
191 fn supports_connect_by(&self) -> bool {
192 true
193 }
194
195 fn supports_execute_immediate(&self) -> bool {
197 true
198 }
199
200 fn supports_match_recognize(&self) -> bool {
201 true
202 }
203
204 fn supports_dictionary_syntax(&self) -> bool {
209 true
210 }
211
212 fn supports_window_function_null_treatment_arg(&self) -> bool {
215 true
216 }
217
218 fn supports_parenthesized_set_variables(&self) -> bool {
220 true
221 }
222
223 fn supports_comment_on(&self) -> bool {
225 true
226 }
227
228 fn supports_extract_comma_syntax(&self) -> bool {
230 true
231 }
232
233 fn supports_subquery_as_function_arg(&self) -> bool {
235 true
236 }
237
238 fn supports_create_view_comment_syntax(&self) -> bool {
240 true
241 }
242
243 fn supports_array_typedef_without_element_type(&self) -> bool {
245 true
246 }
247
248 fn supports_array_typedef_with_parentheses(&self) -> bool {
250 true
251 }
252
253 fn supports_array_element_not_null(&self) -> bool {
254 true
255 }
256
257 fn supports_map_typedef_with_parentheses(&self) -> bool {
258 true
259 }
260
261 fn supports_map_value_not_null(&self) -> bool {
262 true
263 }
264
265 fn supports_parens_around_table_factor(&self) -> bool {
267 true
268 }
269
270 fn supports_values_as_table_factor(&self) -> bool {
272 true
273 }
274
275 fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
276 if parser.parse_keyword(Keyword::BEGIN) {
277 if parser
281 .peek_one_of_keywords(&[Keyword::TRANSACTION, Keyword::WORK, Keyword::NAME])
282 .is_some()
283 || matches!(parser.peek_token_ref().token, Token::SemiColon | Token::EOF)
284 {
285 parser.prev_token();
286 return None;
287 }
288 return Some(parser.parse_begin_exception_end());
289 }
290
291 if parser.parse_keywords(&[Keyword::ALTER, Keyword::DYNAMIC, Keyword::TABLE]) {
292 return Some(parse_alter_dynamic_table(parser));
294 }
295
296 if parser.parse_keywords(&[Keyword::ALTER, Keyword::EXTERNAL, Keyword::TABLE]) {
297 return Some(parse_alter_external_table(parser));
299 }
300
301 if parser.parse_keywords(&[Keyword::ALTER, Keyword::SESSION]) {
302 let set = match parser.parse_one_of_keywords(&[Keyword::SET, Keyword::UNSET]) {
304 Some(Keyword::SET) => true,
305 Some(Keyword::UNSET) => false,
306 _ => return Some(parser.expected_ref("SET or UNSET", parser.peek_token_ref())),
307 };
308 return Some(parse_alter_session(parser, set));
309 }
310
311 if parser.parse_keyword(Keyword::CREATE) {
312 let or_replace = parser.parse_keywords(&[Keyword::OR, Keyword::REPLACE]);
315 let global = match parser.parse_one_of_keywords(&[Keyword::LOCAL, Keyword::GLOBAL]) {
317 Some(Keyword::LOCAL) => Some(false),
318 Some(Keyword::GLOBAL) => Some(true),
319 _ => None,
320 };
321
322 let dynamic = parser.parse_keyword(Keyword::DYNAMIC);
323
324 let mut temporary = false;
325 let mut volatile = false;
326 let mut transient = false;
327 let mut iceberg = false;
328
329 match parser.parse_one_of_keywords(&[
330 Keyword::TEMP,
331 Keyword::TEMPORARY,
332 Keyword::VOLATILE,
333 Keyword::TRANSIENT,
334 Keyword::ICEBERG,
335 ]) {
336 Some(Keyword::TEMP | Keyword::TEMPORARY) => temporary = true,
337 Some(Keyword::VOLATILE) => volatile = true,
338 Some(Keyword::TRANSIENT) => transient = true,
339 Some(Keyword::ICEBERG) => iceberg = true,
340 _ => {}
341 }
342
343 if parser.parse_keyword(Keyword::STAGE) {
344 return Some(parse_create_stage(or_replace, temporary, parser));
346 } else if parser.parse_keyword(Keyword::TABLE) {
347 return Some(
348 parse_create_table(
349 or_replace, global, temporary, volatile, transient, iceberg, dynamic,
350 parser,
351 )
352 .map(Into::into),
353 );
354 } else if parser.parse_keyword(Keyword::DATABASE) {
355 return Some(parse_create_database(or_replace, transient, parser));
356 } else if parser.parse_keywords(&[Keyword::FILE, Keyword::FORMAT]) {
357 return Some(parse_create_file_format(
358 or_replace, temporary, volatile, parser,
359 ));
360 } else {
361 let mut back = 1;
363 if or_replace {
364 back += 2
365 }
366 if temporary {
367 back += 1
368 }
369 for _i in 0..back {
370 parser.prev_token();
371 }
372 }
373 }
374 if parser.parse_keywords(&[Keyword::COPY, Keyword::INTO]) {
375 return Some(parse_copy_into(parser));
377 }
378
379 if let Some(kw) = parser.parse_one_of_keywords(&[
380 Keyword::LIST,
381 Keyword::LS,
382 Keyword::REMOVE,
383 Keyword::RM,
384 ]) {
385 return Some(parse_file_staging_command(kw, parser));
386 }
387
388 if parser.parse_keyword(Keyword::PUT) {
389 return Some(parse_put(parser));
390 }
391
392 if parser.parse_keyword(Keyword::SHOW) {
393 let terse = parser.parse_keyword(Keyword::TERSE);
394 if parser.parse_keyword(Keyword::OBJECTS) {
395 return Some(parse_show_objects(terse, parser));
396 }
397 if terse {
399 parser.prev_token();
400 }
401 parser.prev_token();
403 }
404
405 if parser.parse_keyword(Keyword::INSERT) {
408 let insert_token = parser.get_current_token().clone();
409 let overwrite = parser.parse_keyword(Keyword::OVERWRITE);
410
411 if let Some(kw) = parser.parse_one_of_keywords(&[Keyword::ALL, Keyword::FIRST]) {
413 let multi_table_insert_type = match kw {
414 Keyword::FIRST => MultiTableInsertType::First,
415 _ => MultiTableInsertType::All,
416 };
417 return Some(parse_multi_table_insert(
418 parser,
419 insert_token,
420 overwrite,
421 multi_table_insert_type,
422 ));
423 }
424
425 if overwrite {
427 parser.prev_token(); }
429 parser.prev_token(); }
431
432 None
433 }
434
435 fn parse_column_option(
436 &self,
437 parser: &mut Parser,
438 ) -> Result<Option<Result<Option<ColumnOption>, ParserError>>, ParserError> {
439 parser.maybe_parse(|parser| {
440 let with = parser.parse_keyword(Keyword::WITH);
441
442 if parser.parse_keyword(Keyword::IDENTITY) {
443 Ok(parse_identity_property(parser)
444 .map(|p| Some(ColumnOption::Identity(IdentityPropertyKind::Identity(p)))))
445 } else if parser.parse_keyword(Keyword::AUTOINCREMENT) {
446 Ok(parse_identity_property(parser).map(|p| {
447 Some(ColumnOption::Identity(IdentityPropertyKind::Autoincrement(
448 p,
449 )))
450 }))
451 } else if parser.parse_keywords(&[Keyword::MASKING, Keyword::POLICY]) {
452 Ok(parse_column_policy_property(parser, with)
453 .map(|p| Some(ColumnOption::Policy(ColumnPolicy::MaskingPolicy(p)))))
454 } else if parser.parse_keywords(&[Keyword::PROJECTION, Keyword::POLICY]) {
455 Ok(parse_column_policy_property(parser, with)
456 .map(|p| Some(ColumnOption::Policy(ColumnPolicy::ProjectionPolicy(p)))))
457 } else if parser.parse_keywords(&[Keyword::TAG]) {
458 Ok(parse_column_tags(parser, with).map(|p| Some(ColumnOption::Tags(p))))
459 } else {
460 Err(ParserError::ParserError("not found match".to_string()))
461 }
462 })
463 }
464
465 fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
466 let token = parser.peek_token_ref();
467 match &token.token {
469 Token::Colon => Some(Ok(self.prec_value(Precedence::DoubleColon))),
470 _ => None,
471 }
472 }
473
474 fn describe_requires_table_keyword(&self) -> bool {
475 true
476 }
477
478 fn allow_extract_custom(&self) -> bool {
479 true
480 }
481
482 fn allow_extract_single_quotes(&self) -> bool {
483 true
484 }
485
486 fn supports_show_like_before_in(&self) -> bool {
489 true
490 }
491
492 fn supports_left_associative_joins_without_parens(&self) -> bool {
493 false
494 }
495
496 fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {
497 if matches!(kw, Keyword::INTERVAL) {
500 false
501 } else {
502 RESERVED_FOR_IDENTIFIER.contains(&kw)
503 }
504 }
505
506 fn supports_partiql(&self) -> bool {
507 true
508 }
509
510 fn is_column_alias(&self, kw: &Keyword, parser: &mut Parser) -> bool {
511 match kw {
512 Keyword::EXCEPT
516 | Keyword::RETURNING if !matches!(parser.peek_token_ref().token, Token::Comma | Token::EOF) =>
518 {
519 false
520 }
521
522 Keyword::LIMIT | Keyword::OFFSET if peek_for_limit_options(parser) => false,
525
526 Keyword::FETCH if parser.peek_one_of_keywords(&[Keyword::FIRST, Keyword::NEXT]).is_some()
531 || peek_for_limit_options(parser) =>
532 {
533 false
534 }
535
536 Keyword::FROM
540 | Keyword::GROUP
541 | Keyword::HAVING
542 | Keyword::INTERSECT
543 | Keyword::INTO
544 | Keyword::MINUS
545 | Keyword::ORDER
546 | Keyword::SELECT
547 | Keyword::UNION
548 | Keyword::WHERE
549 | Keyword::WITH => false,
550
551 _ => true,
553 }
554 }
555
556 fn is_table_alias(&self, kw: &Keyword, parser: &mut Parser) -> bool {
557 match kw {
558 Keyword::RETURNING
561 | Keyword::INNER
562 | Keyword::USING
563 | Keyword::PIVOT
564 | Keyword::UNPIVOT
565 | Keyword::EXCEPT
566 | Keyword::MATCH_RECOGNIZE
567 if !matches!(parser.peek_token_ref().token, Token::SemiColon | Token::EOF) =>
568 {
569 false
570 }
571
572 Keyword::LIMIT | Keyword::OFFSET if peek_for_limit_options(parser) => false,
576
577 Keyword::FETCH
582 if parser
583 .peek_one_of_keywords(&[Keyword::FIRST, Keyword::NEXT])
584 .is_some()
585 || peek_for_limit_options(parser) =>
586 {
587 false
588 }
589
590 Keyword::RIGHT | Keyword::LEFT | Keyword::SEMI | Keyword::ANTI
593 if parser
594 .peek_one_of_keywords(&[Keyword::JOIN, Keyword::OUTER])
595 .is_some() =>
596 {
597 false
598 }
599
600 Keyword::GLOBAL if parser.peek_keyword(Keyword::FULL) => false,
601
602 Keyword::WITH
606 | Keyword::ORDER
607 | Keyword::SELECT
608 | Keyword::WHERE
609 | Keyword::GROUP
610 | Keyword::HAVING
611 | Keyword::LATERAL
612 | Keyword::UNION
613 | Keyword::INTERSECT
614 | Keyword::MINUS
615 | Keyword::ON
616 | Keyword::JOIN
617 | Keyword::INNER
618 | Keyword::CROSS
619 | Keyword::FULL
620 | Keyword::LEFT
621 | Keyword::RIGHT
622 | Keyword::NATURAL
623 | Keyword::USING
624 | Keyword::ASOF
625 | Keyword::MATCH_CONDITION
626 | Keyword::SET
627 | Keyword::QUALIFY
628 | Keyword::FOR
629 | Keyword::START
630 | Keyword::CONNECT
631 | Keyword::SAMPLE
632 | Keyword::TABLESAMPLE
633 | Keyword::FROM => false,
634
635 _ => true,
637 }
638 }
639
640 fn is_table_factor(&self, kw: &Keyword, parser: &mut Parser) -> bool {
641 match kw {
642 Keyword::LIMIT if peek_for_limit_options(parser) => false,
643 Keyword::TABLE if matches!(parser.peek_token_ref().token, Token::LParen) => true,
645 _ => !RESERVED_KEYWORDS_FOR_TABLE_FACTOR.contains(kw),
646 }
647 }
648
649 fn supports_table_versioning(&self) -> bool {
651 true
652 }
653
654 fn supports_group_by_expr(&self) -> bool {
656 true
657 }
658
659 fn get_reserved_keywords_for_select_item_operator(&self) -> &[Keyword] {
661 &RESERVED_KEYWORDS_FOR_SELECT_ITEM_OPERATOR
662 }
663
664 fn supports_space_separated_column_options(&self) -> bool {
665 true
666 }
667
668 fn supports_comma_separated_drop_column_list(&self) -> bool {
669 true
670 }
671
672 fn is_identifier_generating_function_name(
673 &self,
674 ident: &Ident,
675 name_parts: &[ObjectNamePart],
676 ) -> bool {
677 ident.quote_style.is_none()
678 && ident.value.to_lowercase() == "identifier"
679 && !name_parts
680 .iter()
681 .any(|p| matches!(p, ObjectNamePart::Function(_)))
682 }
683
684 fn supports_select_expr_star(&self) -> bool {
686 true
687 }
688
689 fn supports_select_wildcard_exclude(&self) -> bool {
690 true
691 }
692
693 fn supports_semantic_view_table_factor(&self) -> bool {
694 true
695 }
696
697 fn supports_stages(&self) -> bool {
698 true
699 }
700
701 fn supports_select_wildcard_replace(&self) -> bool {
703 true
704 }
705
706 fn supports_select_wildcard_ilike(&self) -> bool {
708 true
709 }
710
711 fn supports_select_wildcard_rename(&self) -> bool {
713 true
714 }
715
716 fn supports_lambda_functions(&self) -> bool {
718 true
719 }
720
721 fn supports_comma_separated_trim(&self) -> bool {
722 true
723 }
724}
725
726fn peek_for_limit_options(parser: &Parser) -> bool {
729 match &parser.peek_token_ref().token {
730 Token::Number(_, _) | Token::Placeholder(_) => true,
731 Token::SingleQuotedString(val) if val.is_empty() => true,
732 Token::DollarQuotedString(DollarQuotedString { value, .. }) if value.is_empty() => true,
733 Token::Word(w) if w.keyword == Keyword::NULL => true,
734 _ => false,
735 }
736}
737
738fn parse_put(parser: &mut Parser) -> Result<Statement, ParserError> {
743 let source = parser.parse_literal_string()?;
744 let stage = parse_snowflake_stage_name(parser)?;
745 let options = parser.parse_key_value_options(false, &[])?;
746 Ok(Statement::Put {
747 source,
748 stage,
749 options,
750 })
751}
752
753fn parse_file_staging_command(kw: Keyword, parser: &mut Parser) -> Result<Statement, ParserError> {
754 let stage = parse_snowflake_stage_name(parser)?;
755 let pattern = if parser.parse_keyword(Keyword::PATTERN) {
756 parser.expect_token(&Token::Eq)?;
757 Some(parser.parse_literal_string()?)
758 } else {
759 None
760 };
761
762 match kw {
763 Keyword::LIST | Keyword::LS => Ok(Statement::List(FileStagingCommand { stage, pattern })),
764 Keyword::REMOVE | Keyword::RM => {
765 Ok(Statement::Remove(FileStagingCommand { stage, pattern }))
766 }
767 _ => Err(ParserError::ParserError(
768 "unexpected stage command, expecting LIST, LS, REMOVE or RM".to_string(),
769 )),
770 }
771}
772
773fn parse_alter_dynamic_table(parser: &mut Parser) -> Result<Statement, ParserError> {
776 let table_name = parser.parse_object_name(true)?;
778
779 let operation = if parser.parse_keyword(Keyword::REFRESH) {
781 AlterTableOperation::Refresh { subpath: None }
782 } else if parser.parse_keyword(Keyword::SUSPEND) {
783 AlterTableOperation::Suspend
784 } else if parser.parse_keyword(Keyword::RESUME) {
785 AlterTableOperation::Resume
786 } else {
787 return parser.expected_ref(
788 "REFRESH, SUSPEND, or RESUME after ALTER DYNAMIC TABLE",
789 parser.peek_token_ref(),
790 );
791 };
792
793 let end_token = if parser.peek_token_ref().token == Token::SemiColon {
794 parser.peek_token_ref().clone()
795 } else {
796 parser.get_current_token().clone()
797 };
798
799 Ok(Statement::AlterTable(AlterTable {
800 name: table_name,
801 if_exists: false,
802 only: false,
803 operations: vec![operation],
804 location: None,
805 on_cluster: None,
806 table_type: Some(AlterTableType::Dynamic),
807 end_token: AttachedToken(end_token),
808 }))
809}
810
811fn parse_alter_external_table(parser: &mut Parser) -> Result<Statement, ParserError> {
814 let if_exists = parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
815 let table_name = parser.parse_object_name(true)?;
816
817 let operation = if parser.parse_keyword(Keyword::REFRESH) {
819 let subpath = match parser.peek_token().token {
821 Token::SingleQuotedString(s) => {
822 parser.next_token();
823 Some(s)
824 }
825 _ => None,
826 };
827 AlterTableOperation::Refresh { subpath }
828 } else {
829 return parser.expected_ref(
830 "REFRESH after ALTER EXTERNAL TABLE",
831 parser.peek_token_ref(),
832 );
833 };
834
835 let end_token = if parser.peek_token_ref().token == Token::SemiColon {
836 parser.peek_token_ref().clone()
837 } else {
838 parser.get_current_token().clone()
839 };
840
841 Ok(Statement::AlterTable(AlterTable {
842 name: table_name,
843 if_exists,
844 only: false,
845 operations: vec![operation],
846 location: None,
847 on_cluster: None,
848 table_type: Some(AlterTableType::External),
849 end_token: AttachedToken(end_token),
850 }))
851}
852
853fn parse_alter_session(parser: &mut Parser, set: bool) -> Result<Statement, ParserError> {
856 let session_options = parse_session_options(parser, set)?;
857 Ok(Statement::AlterSession {
858 set,
859 session_params: KeyValueOptions {
860 options: session_options,
861 delimiter: KeyValueOptionsDelimiter::Space,
862 },
863 })
864}
865
866#[allow(clippy::too_many_arguments)]
870pub fn parse_create_table(
871 or_replace: bool,
872 global: Option<bool>,
873 temporary: bool,
874 volatile: bool,
875 transient: bool,
876 iceberg: bool,
877 dynamic: bool,
878 parser: &mut Parser,
879) -> Result<CreateTable, ParserError> {
880 let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
881 let table_name = parser.parse_object_name(false)?;
882
883 let mut builder = CreateTableBuilder::new(table_name)
884 .or_replace(or_replace)
885 .if_not_exists(if_not_exists)
886 .temporary(temporary)
887 .transient(transient)
888 .volatile(volatile)
889 .iceberg(iceberg)
890 .global(global)
891 .dynamic(dynamic)
892 .hive_formats(None);
893
894 let mut plain_options = vec![];
901
902 loop {
903 let next_token = parser.next_token();
904 match &next_token.token {
905 Token::Word(word) => match word.keyword {
906 Keyword::COPY => {
907 parser.expect_keyword_is(Keyword::GRANTS)?;
908 builder = builder.copy_grants(true);
909 }
910 Keyword::COMMENT => {
911 parser.prev_token();
913 if let Some(comment_def) = parser.parse_optional_inline_comment()? {
914 plain_options.push(SqlOption::Comment(comment_def))
915 }
916 }
917 Keyword::AS => {
918 let query = parser.parse_query()?;
919 builder = builder.query(Some(query));
920 }
921 Keyword::CLONE => {
922 let clone = parser.parse_object_name(false).ok();
923 builder = builder.clone_clause(clone);
924 }
925 Keyword::LIKE => {
926 let name = parser.parse_object_name(false)?;
927 builder = builder.like(Some(CreateTableLikeKind::Plain(
928 crate::ast::CreateTableLike {
929 name,
930 defaults: None,
931 },
932 )));
933 }
934 Keyword::CLUSTER => {
935 parser.expect_keyword_is(Keyword::BY)?;
936 parser.expect_token(&Token::LParen)?;
937 let cluster_by = Some(WrappedCollection::Parentheses(
938 parser.parse_comma_separated(|p| p.parse_expr())?,
939 ));
940 parser.expect_token(&Token::RParen)?;
941
942 builder = builder.cluster_by(cluster_by)
943 }
944 Keyword::ENABLE_SCHEMA_EVOLUTION => {
945 parser.expect_token(&Token::Eq)?;
946 builder = builder.enable_schema_evolution(Some(parser.parse_boolean_string()?));
947 }
948 Keyword::CHANGE_TRACKING => {
949 parser.expect_token(&Token::Eq)?;
950 builder = builder.change_tracking(Some(parser.parse_boolean_string()?));
951 }
952 Keyword::DATA_RETENTION_TIME_IN_DAYS => {
953 parser.expect_token(&Token::Eq)?;
954 let data_retention_time_in_days = parser.parse_literal_uint()?;
955 builder =
956 builder.data_retention_time_in_days(Some(data_retention_time_in_days));
957 }
958 Keyword::MAX_DATA_EXTENSION_TIME_IN_DAYS => {
959 parser.expect_token(&Token::Eq)?;
960 let max_data_extension_time_in_days = parser.parse_literal_uint()?;
961 builder = builder
962 .max_data_extension_time_in_days(Some(max_data_extension_time_in_days));
963 }
964 Keyword::DEFAULT_DDL_COLLATION => {
965 parser.expect_token(&Token::Eq)?;
966 let default_ddl_collation = parser.parse_literal_string()?;
967 builder = builder.default_ddl_collation(Some(default_ddl_collation));
968 }
969 Keyword::WITH => {
972 parser.expect_one_of_keywords(&[
973 Keyword::AGGREGATION,
974 Keyword::STORAGE,
975 Keyword::TAG,
976 Keyword::ROW,
977 ])?;
978 parser.prev_token();
979 }
980 Keyword::AGGREGATION => {
981 parser.expect_keyword_is(Keyword::POLICY)?;
982 let aggregation_policy = parser.parse_object_name(false)?;
983 builder = builder.with_aggregation_policy(Some(aggregation_policy));
984 }
985 Keyword::ROW => {
986 parser.expect_keywords(&[Keyword::ACCESS, Keyword::POLICY])?;
987 let policy = parser.parse_object_name(false)?;
988 parser.expect_keyword_is(Keyword::ON)?;
989 parser.expect_token(&Token::LParen)?;
990 let columns = parser.parse_comma_separated(|p| p.parse_identifier())?;
991 parser.expect_token(&Token::RParen)?;
992
993 builder =
994 builder.with_row_access_policy(Some(RowAccessPolicy::new(policy, columns)))
995 }
996 Keyword::STORAGE => {
997 parser.expect_keywords(&[Keyword::LIFECYCLE, Keyword::POLICY])?;
998 let policy = parser.parse_object_name(false)?;
999 parser.expect_keyword_is(Keyword::ON)?;
1000 parser.expect_token(&Token::LParen)?;
1001 let columns = parser.parse_comma_separated(|p| p.parse_identifier())?;
1002 parser.expect_token(&Token::RParen)?;
1003
1004 builder = builder.with_storage_lifecycle_policy(Some(StorageLifecyclePolicy {
1005 policy,
1006 on: columns,
1007 }))
1008 }
1009 Keyword::TAG => {
1010 parser.expect_token(&Token::LParen)?;
1011 let tags = parser.parse_comma_separated(Parser::parse_tag)?;
1012 parser.expect_token(&Token::RParen)?;
1013 builder = builder.with_tags(Some(tags));
1014 }
1015 Keyword::ON if parser.parse_keyword(Keyword::COMMIT) => {
1016 let on_commit = Some(parser.parse_create_table_on_commit()?);
1017 builder = builder.on_commit(on_commit);
1018 }
1019 Keyword::EXTERNAL_VOLUME => {
1020 parser.expect_token(&Token::Eq)?;
1021 builder.external_volume = Some(parser.parse_literal_string()?);
1022 }
1023 Keyword::CATALOG => {
1024 parser.expect_token(&Token::Eq)?;
1025 builder.catalog = Some(parser.parse_literal_string()?);
1026 }
1027 Keyword::BASE_LOCATION => {
1028 parser.expect_token(&Token::Eq)?;
1029 builder.base_location = Some(parser.parse_literal_string()?);
1030 }
1031 Keyword::CATALOG_SYNC => {
1032 parser.expect_token(&Token::Eq)?;
1033 builder.catalog_sync = Some(parser.parse_literal_string()?);
1034 }
1035 Keyword::STORAGE_SERIALIZATION_POLICY => {
1036 parser.expect_token(&Token::Eq)?;
1037
1038 builder.storage_serialization_policy =
1039 Some(parse_storage_serialization_policy(parser)?);
1040 }
1041 Keyword::IF if parser.parse_keywords(&[Keyword::NOT, Keyword::EXISTS]) => {
1042 builder = builder.if_not_exists(true);
1043 }
1044 Keyword::TARGET_LAG => {
1045 parser.expect_token(&Token::Eq)?;
1046 let target_lag = parser.parse_literal_string()?;
1047 builder = builder.target_lag(Some(target_lag));
1048 }
1049 Keyword::WAREHOUSE => {
1050 parser.expect_token(&Token::Eq)?;
1051 let warehouse = parser.parse_identifier()?;
1052 builder = builder.warehouse(Some(warehouse));
1053 }
1054 Keyword::AT | Keyword::BEFORE => {
1055 parser.prev_token();
1056 let version = parser.maybe_parse_table_version()?;
1057 builder = builder.version(version);
1058 }
1059 Keyword::REFRESH_MODE => {
1060 parser.expect_token(&Token::Eq)?;
1061 let refresh_mode = match parser.parse_one_of_keywords(&[
1062 Keyword::AUTO,
1063 Keyword::FULL,
1064 Keyword::INCREMENTAL,
1065 ]) {
1066 Some(Keyword::AUTO) => Some(RefreshModeKind::Auto),
1067 Some(Keyword::FULL) => Some(RefreshModeKind::Full),
1068 Some(Keyword::INCREMENTAL) => Some(RefreshModeKind::Incremental),
1069 _ => return parser.expected("AUTO, FULL or INCREMENTAL", next_token),
1070 };
1071 builder = builder.refresh_mode(refresh_mode);
1072 }
1073 Keyword::INITIALIZE => {
1074 parser.expect_token(&Token::Eq)?;
1075 let initialize = match parser
1076 .parse_one_of_keywords(&[Keyword::ON_CREATE, Keyword::ON_SCHEDULE])
1077 {
1078 Some(Keyword::ON_CREATE) => Some(InitializeKind::OnCreate),
1079 Some(Keyword::ON_SCHEDULE) => Some(InitializeKind::OnSchedule),
1080 _ => return parser.expected("ON_CREATE or ON_SCHEDULE", next_token),
1081 };
1082 builder = builder.initialize(initialize);
1083 }
1084 Keyword::REQUIRE if parser.parse_keyword(Keyword::USER) => {
1085 builder = builder.require_user(true);
1086 }
1087 _ => {
1088 return parser.expected("end of statement", next_token);
1089 }
1090 },
1091 Token::LParen => {
1092 parser.prev_token();
1093 let (columns, constraints) = parser.parse_columns()?;
1094 builder = builder.columns(columns).constraints(constraints);
1095 }
1096 Token::EOF => {
1097 break;
1098 }
1099 Token::SemiColon => {
1100 parser.prev_token();
1101 break;
1102 }
1103 _ => {
1104 return parser.expected("end of statement", next_token);
1105 }
1106 }
1107 }
1108 let table_options = if !plain_options.is_empty() {
1109 crate::ast::CreateTableOptions::Plain(plain_options)
1110 } else {
1111 crate::ast::CreateTableOptions::None
1112 };
1113
1114 builder = builder.table_options(table_options);
1115
1116 if iceberg && builder.base_location.is_none() {
1117 return Err(ParserError::ParserError(
1118 "BASE_LOCATION is required for ICEBERG tables".to_string(),
1119 ));
1120 }
1121
1122 Ok(builder.build())
1123}
1124
1125pub fn parse_create_database(
1128 or_replace: bool,
1129 transient: bool,
1130 parser: &mut Parser,
1131) -> Result<Statement, ParserError> {
1132 let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
1133 let name = parser.parse_object_name(false)?;
1134
1135 let mut builder = CreateDatabaseBuilder::new(name)
1136 .or_replace(or_replace)
1137 .transient(transient)
1138 .if_not_exists(if_not_exists);
1139
1140 loop {
1141 let next_token = parser.next_token();
1142 match &next_token.token {
1143 Token::Word(word) => match word.keyword {
1144 Keyword::CLONE => {
1145 builder = builder.clone_clause(Some(parser.parse_object_name(false)?));
1146 }
1147 Keyword::DATA_RETENTION_TIME_IN_DAYS => {
1148 parser.expect_token(&Token::Eq)?;
1149 builder =
1150 builder.data_retention_time_in_days(Some(parser.parse_literal_uint()?));
1151 }
1152 Keyword::MAX_DATA_EXTENSION_TIME_IN_DAYS => {
1153 parser.expect_token(&Token::Eq)?;
1154 builder =
1155 builder.max_data_extension_time_in_days(Some(parser.parse_literal_uint()?));
1156 }
1157 Keyword::EXTERNAL_VOLUME => {
1158 parser.expect_token(&Token::Eq)?;
1159 builder = builder.external_volume(Some(parser.parse_literal_string()?));
1160 }
1161 Keyword::CATALOG => {
1162 parser.expect_token(&Token::Eq)?;
1163 builder = builder.catalog(Some(parser.parse_literal_string()?));
1164 }
1165 Keyword::REPLACE_INVALID_CHARACTERS => {
1166 parser.expect_token(&Token::Eq)?;
1167 builder =
1168 builder.replace_invalid_characters(Some(parser.parse_boolean_string()?));
1169 }
1170 Keyword::DEFAULT_DDL_COLLATION => {
1171 parser.expect_token(&Token::Eq)?;
1172 builder = builder.default_ddl_collation(Some(parser.parse_literal_string()?));
1173 }
1174 Keyword::STORAGE_SERIALIZATION_POLICY => {
1175 parser.expect_token(&Token::Eq)?;
1176 let policy = parse_storage_serialization_policy(parser)?;
1177 builder = builder.storage_serialization_policy(Some(policy));
1178 }
1179 Keyword::COMMENT => {
1180 parser.expect_token(&Token::Eq)?;
1181 builder = builder.comment(Some(parser.parse_literal_string()?));
1182 }
1183 Keyword::CATALOG_SYNC => {
1184 parser.expect_token(&Token::Eq)?;
1185 builder = builder.catalog_sync(Some(parser.parse_literal_string()?));
1186 }
1187 Keyword::CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER => {
1188 parser.expect_token(&Token::Eq)?;
1189 builder = builder.catalog_sync_namespace_flatten_delimiter(Some(
1190 parser.parse_literal_string()?,
1191 ));
1192 }
1193 Keyword::CATALOG_SYNC_NAMESPACE_MODE => {
1194 parser.expect_token(&Token::Eq)?;
1195 let mode =
1196 match parser.parse_one_of_keywords(&[Keyword::NEST, Keyword::FLATTEN]) {
1197 Some(Keyword::NEST) => CatalogSyncNamespaceMode::Nest,
1198 Some(Keyword::FLATTEN) => CatalogSyncNamespaceMode::Flatten,
1199 _ => {
1200 return parser.expected("NEST or FLATTEN", next_token);
1201 }
1202 };
1203 builder = builder.catalog_sync_namespace_mode(Some(mode));
1204 }
1205 Keyword::WITH => {
1206 if parser.parse_keyword(Keyword::TAG) {
1207 parser.expect_token(&Token::LParen)?;
1208 let tags = parser.parse_comma_separated(Parser::parse_tag)?;
1209 parser.expect_token(&Token::RParen)?;
1210 builder = builder.with_tags(Some(tags));
1211 } else if parser.parse_keyword(Keyword::CONTACT) {
1212 parser.expect_token(&Token::LParen)?;
1213 let contacts = parser.parse_comma_separated(|p| {
1214 let purpose = p.parse_identifier()?.value;
1215 p.expect_token(&Token::Eq)?;
1216 let contact = p.parse_identifier()?.value;
1217 Ok(ContactEntry { purpose, contact })
1218 })?;
1219 parser.expect_token(&Token::RParen)?;
1220 builder = builder.with_contacts(Some(contacts));
1221 } else {
1222 return parser.expected("TAG or CONTACT", next_token);
1223 }
1224 }
1225 _ => return parser.expected("end of statement", next_token),
1226 },
1227 Token::SemiColon | Token::EOF => break,
1228 _ => return parser.expected("end of statement", next_token),
1229 }
1230 }
1231 Ok(builder.build())
1232}
1233
1234pub fn parse_storage_serialization_policy(
1235 parser: &mut Parser,
1236) -> Result<StorageSerializationPolicy, ParserError> {
1237 let next_token = parser.next_token();
1238 match &next_token.token {
1239 Token::Word(w) => match w.keyword {
1240 Keyword::COMPATIBLE => Ok(StorageSerializationPolicy::Compatible),
1241 Keyword::OPTIMIZED => Ok(StorageSerializationPolicy::Optimized),
1242 _ => parser.expected("storage_serialization_policy", next_token),
1243 },
1244 _ => parser.expected("storage_serialization_policy", next_token),
1245 }
1246}
1247
1248pub fn parse_create_stage(
1249 or_replace: bool,
1250 temporary: bool,
1251 parser: &mut Parser,
1252) -> Result<Statement, ParserError> {
1253 let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
1255 let name = parser.parse_object_name(false)?;
1256 let mut directory_table_params = Vec::new();
1257 let mut file_format = Vec::new();
1258 let mut copy_options = Vec::new();
1259 let mut comment = None;
1260
1261 let stage_params = parse_stage_params(parser)?;
1263
1264 if parser.parse_keyword(Keyword::DIRECTORY) {
1266 parser.expect_token(&Token::Eq)?;
1267 directory_table_params = parser.parse_key_value_options(true, &[])?.options;
1268 }
1269
1270 if parser.parse_keyword(Keyword::FILE_FORMAT) {
1272 parser.expect_token(&Token::Eq)?;
1273 file_format = parser.parse_key_value_options(true, &[])?.options;
1274 }
1275
1276 if parser.parse_keyword(Keyword::COPY_OPTIONS) {
1278 parser.expect_token(&Token::Eq)?;
1279 copy_options = parser.parse_key_value_options(true, &[])?.options;
1280 }
1281
1282 if parser.parse_keyword(Keyword::COMMENT) {
1284 parser.expect_token(&Token::Eq)?;
1285 comment = Some(parser.parse_comment_value()?);
1286 }
1287
1288 Ok(Statement::CreateStage {
1289 or_replace,
1290 temporary,
1291 if_not_exists,
1292 name,
1293 stage_params,
1294 directory_table_params: KeyValueOptions {
1295 options: directory_table_params,
1296 delimiter: KeyValueOptionsDelimiter::Space,
1297 },
1298 file_format: KeyValueOptions {
1299 options: file_format,
1300 delimiter: KeyValueOptionsDelimiter::Space,
1301 },
1302 copy_options: KeyValueOptions {
1303 options: copy_options,
1304 delimiter: KeyValueOptionsDelimiter::Space,
1305 },
1306 comment,
1307 })
1308}
1309
1310pub fn parse_create_file_format(
1313 or_replace: bool,
1314 temporary: bool,
1315 volatile: bool,
1316 parser: &mut Parser,
1317) -> Result<Statement, ParserError> {
1318 let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
1319 let name = parser.parse_object_name(true)?;
1320 let options = parser.parse_key_value_options(false, &[Keyword::COMMENT])?;
1321 let comment = if parser.parse_keyword(Keyword::COMMENT) {
1322 parser.expect_token(&Token::Eq)?;
1323 Some(parser.parse_comment_value()?)
1324 } else {
1325 None
1326 };
1327
1328 Ok(Statement::CreateFileFormat {
1329 or_replace,
1330 temporary,
1331 volatile,
1332 if_not_exists,
1333 name,
1334 options,
1335 comment,
1336 })
1337}
1338
1339pub fn parse_stage_name_identifier(parser: &mut Parser) -> Result<Ident, ParserError> {
1340 let mut ident = String::new();
1341 while let Some(next_token) = parser.next_token_no_skip() {
1342 match &next_token.token {
1343 Token::Whitespace(_) => break,
1344 Token::Period | Token::Comma | Token::SemiColon | Token::LParen | Token::RParen => {
1345 parser.prev_token();
1346 break;
1347 }
1348 Token::AtSign => ident.push('@'),
1349 Token::Tilde => ident.push('~'),
1350 Token::Mod => ident.push('%'),
1351 Token::Div => ident.push('/'),
1352 Token::Plus => ident.push('+'),
1353 Token::Minus => ident.push('-'),
1354 Token::Eq => ident.push('='),
1355 Token::Colon => ident.push(':'),
1356 Token::Number(n, _) => ident.push_str(n),
1357 Token::Word(w) => ident.push_str(&w.to_string()),
1358 _ => return parser.expected_ref("stage name identifier", parser.peek_token_ref()),
1359 }
1360 }
1361 if ident.is_empty() || ident == "@" {
1362 return parser.expected_ref("stage name identifier", parser.peek_token_ref());
1363 }
1364 Ok(Ident::new(ident))
1365}
1366
1367pub fn parse_snowflake_stage_name(parser: &mut Parser) -> Result<ObjectName, ParserError> {
1370 match parser.next_token().token {
1371 Token::AtSign => {
1372 parser.prev_token();
1373 let mut idents = vec![];
1374 loop {
1375 idents.push(parse_stage_name_identifier(parser)?);
1376 if !parser.consume_token(&Token::Period) {
1377 break;
1378 }
1379 }
1380 Ok(ObjectName::from(idents))
1381 }
1382 _ => {
1383 parser.prev_token();
1384 Ok(parser.parse_object_name(false)?)
1385 }
1386 }
1387}
1388
1389pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
1392 let kind = match &parser.peek_token_ref().token {
1393 Token::AtSign => CopyIntoSnowflakeKind::Location,
1395 Token::SingleQuotedString(s) if s.contains("://") => CopyIntoSnowflakeKind::Location,
1397 _ => CopyIntoSnowflakeKind::Table,
1398 };
1399
1400 let mut files: Vec<String> = vec![];
1401 let mut from_transformations: Option<Vec<StageLoadSelectItemKind>> = None;
1402 let mut from_stage_alias = None;
1403 let mut from_stage = None;
1404 let mut stage_params = StageParamsObject {
1405 url: None,
1406 encryption: KeyValueOptions {
1407 options: vec![],
1408 delimiter: KeyValueOptionsDelimiter::Space,
1409 },
1410 endpoint: None,
1411 storage_integration: None,
1412 credentials: KeyValueOptions {
1413 options: vec![],
1414 delimiter: KeyValueOptionsDelimiter::Space,
1415 },
1416 };
1417 let mut from_query = None;
1418 let mut partition = None;
1419 let mut file_format = Vec::new();
1420 let mut pattern = None;
1421 let mut validation_mode = None;
1422 let mut copy_options = Vec::new();
1423
1424 let into: ObjectName = parse_snowflake_stage_name(parser)?;
1425 if kind == CopyIntoSnowflakeKind::Location {
1426 stage_params = parse_stage_params(parser)?;
1427 }
1428
1429 let into_columns = match &parser.peek_token().token {
1430 Token::LParen => Some(parser.parse_parenthesized_column_list(IsOptional::Optional, true)?),
1431 _ => None,
1432 };
1433
1434 parser.expect_keyword_is(Keyword::FROM)?;
1435 match parser.next_token().token {
1436 Token::LParen if kind == CopyIntoSnowflakeKind::Table => {
1437 parser.expect_keyword_is(Keyword::SELECT)?;
1439 from_transformations = parse_select_items_for_data_load(parser)?;
1440
1441 parser.expect_keyword_is(Keyword::FROM)?;
1442 from_stage = Some(parse_snowflake_stage_name(parser)?);
1443 stage_params = parse_stage_params(parser)?;
1444
1445 from_stage_alias = parser
1447 .maybe_parse_table_alias()?
1448 .map(|table_alias| table_alias.name);
1449 parser.expect_token(&Token::RParen)?;
1450 }
1451 Token::LParen if kind == CopyIntoSnowflakeKind::Location => {
1452 from_query = Some(parser.parse_query()?);
1454 parser.expect_token(&Token::RParen)?;
1455 }
1456 _ => {
1457 parser.prev_token();
1458 from_stage = Some(parse_snowflake_stage_name(parser)?);
1459 stage_params = parse_stage_params(parser)?;
1460
1461 from_stage_alias = if parser.parse_keyword(Keyword::AS) {
1463 Some(match parser.next_token().token {
1464 Token::Word(w) => Ok(Ident::new(w.value)),
1465 _ => parser.expected_ref("stage alias", parser.peek_token_ref()),
1466 }?)
1467 } else {
1468 None
1469 };
1470 }
1471 }
1472
1473 loop {
1474 if parser.parse_keyword(Keyword::FILE_FORMAT) {
1476 parser.expect_token(&Token::Eq)?;
1477 file_format = parser.parse_key_value_options(true, &[])?.options;
1478 } else if parser.parse_keywords(&[Keyword::PARTITION, Keyword::BY]) {
1480 partition = Some(Box::new(parser.parse_expr()?))
1481 } else if parser.parse_keyword(Keyword::FILES) {
1483 parser.expect_token(&Token::Eq)?;
1484 parser.expect_token(&Token::LParen)?;
1485 let mut continue_loop = true;
1486 while continue_loop {
1487 continue_loop = false;
1488 let next_token = parser.next_token();
1489 match next_token.token {
1490 Token::SingleQuotedString(s) => files.push(s),
1491 _ => parser.expected("file token", next_token)?,
1492 };
1493 if parser.next_token().token.eq(&Token::Comma) {
1494 continue_loop = true;
1495 } else {
1496 parser.prev_token(); }
1498 }
1499 parser.expect_token(&Token::RParen)?;
1500 } else if parser.parse_keyword(Keyword::PATTERN) {
1502 parser.expect_token(&Token::Eq)?;
1503 let next_token = parser.next_token();
1504 pattern = Some(match next_token.token {
1505 Token::SingleQuotedString(s) => s,
1506 _ => parser.expected("pattern", next_token)?,
1507 });
1508 } else if parser.parse_keyword(Keyword::VALIDATION_MODE) {
1510 parser.expect_token(&Token::Eq)?;
1511 validation_mode = Some(parser.next_token().token.to_string());
1512 } else if parser.parse_keyword(Keyword::COPY_OPTIONS) {
1514 parser.expect_token(&Token::Eq)?;
1515 copy_options = parser.parse_key_value_options(true, &[])?.options;
1516 } else {
1517 match parser.next_token().token {
1518 Token::SemiColon | Token::EOF => break,
1519 Token::Comma => continue,
1520 Token::Word(key) => copy_options.push(parser.parse_key_value_option(&key)?),
1523 _ => {
1524 return parser
1525 .expected_ref("another copy option, ; or EOF'", parser.peek_token_ref())
1526 }
1527 }
1528 }
1529 }
1530
1531 Ok(Statement::CopyIntoSnowflake {
1532 kind,
1533 into,
1534 into_columns,
1535 from_obj: from_stage,
1536 from_obj_alias: from_stage_alias,
1537 stage_params,
1538 from_transformations,
1539 from_query,
1540 files: if files.is_empty() { None } else { Some(files) },
1541 pattern,
1542 file_format: KeyValueOptions {
1543 options: file_format,
1544 delimiter: KeyValueOptionsDelimiter::Space,
1545 },
1546 copy_options: KeyValueOptions {
1547 options: copy_options,
1548 delimiter: KeyValueOptionsDelimiter::Space,
1549 },
1550 validation_mode,
1551 partition,
1552 })
1553}
1554
1555fn parse_select_items_for_data_load(
1556 parser: &mut Parser,
1557) -> Result<Option<Vec<StageLoadSelectItemKind>>, ParserError> {
1558 let mut select_items: Vec<StageLoadSelectItemKind> = vec![];
1559 loop {
1560 match parser.maybe_parse(parse_select_item_for_data_load)? {
1561 Some(item) => select_items.push(StageLoadSelectItemKind::StageLoadSelectItem(item)),
1563 None => select_items.push(StageLoadSelectItemKind::SelectItem(
1565 parser.parse_select_item()?,
1566 )),
1567 }
1568 if matches!(parser.peek_token_ref().token, Token::Comma) {
1569 parser.advance_token();
1570 } else {
1571 break;
1572 }
1573 }
1574 Ok(Some(select_items))
1575}
1576
1577fn parse_select_item_for_data_load(
1578 parser: &mut Parser,
1579) -> Result<StageLoadSelectItem, ParserError> {
1580 let mut alias: Option<Ident> = None;
1581 let mut file_col_num: i32 = 0;
1582 let mut element: Option<Ident> = None;
1583 let mut item_as: Option<Ident> = None;
1584
1585 let next_token = parser.next_token();
1586 match next_token.token {
1587 Token::Placeholder(w) => {
1588 file_col_num = w.to_string().split_off(1).parse::<i32>().map_err(|e| {
1589 ParserError::ParserError(format!("Could not parse '{w}' as i32: {e}"))
1590 })?;
1591 Ok(())
1592 }
1593 Token::Word(w) => {
1594 alias = Some(Ident::new(w.value));
1595 Ok(())
1596 }
1597 _ => parser.expected("alias or file_col_num", next_token),
1598 }?;
1599
1600 if alias.is_some() {
1601 parser.expect_token(&Token::Period)?;
1602 let col_num_token = parser.next_token();
1604 match col_num_token.token {
1605 Token::Placeholder(w) => {
1606 file_col_num = w.to_string().split_off(1).parse::<i32>().map_err(|e| {
1607 ParserError::ParserError(format!("Could not parse '{w}' as i32: {e}"))
1608 })?;
1609 Ok(())
1610 }
1611 _ => parser.expected("file_col_num", col_num_token),
1612 }?;
1613 }
1614
1615 match parser.next_token().token {
1617 Token::Colon => {
1618 element = Some(Ident::new(match parser.next_token().token {
1620 Token::Word(w) => Ok(w.value),
1621 _ => parser.expected_ref("file_col_num", parser.peek_token_ref()),
1622 }?));
1623 }
1624 _ => {
1625 parser.prev_token();
1627 }
1628 }
1629
1630 if matches!(
1633 parser.peek_token_ref().token,
1634 Token::Colon | Token::Period | Token::LBracket | Token::DoubleColon
1635 ) {
1636 let token = parser.next_token();
1637 return parser.expected("end of simple staged field", token);
1638 }
1639
1640 if parser.parse_keyword(Keyword::AS) {
1642 item_as = Some(match parser.next_token().token {
1643 Token::Word(w) => Ok(Ident::new(w.value)),
1644 _ => parser.expected_ref("column item alias", parser.peek_token_ref()),
1645 }?);
1646 }
1647
1648 Ok(StageLoadSelectItem {
1649 alias,
1650 file_col_num,
1651 element,
1652 item_as,
1653 })
1654}
1655
1656fn parse_stage_params(parser: &mut Parser) -> Result<StageParamsObject, ParserError> {
1657 let (mut url, mut storage_integration, mut endpoint) = (None, None, None);
1658 let mut encryption: KeyValueOptions = KeyValueOptions {
1659 options: vec![],
1660 delimiter: KeyValueOptionsDelimiter::Space,
1661 };
1662 let mut credentials: KeyValueOptions = KeyValueOptions {
1663 options: vec![],
1664 delimiter: KeyValueOptionsDelimiter::Space,
1665 };
1666
1667 if parser.parse_keyword(Keyword::URL) {
1669 parser.expect_token(&Token::Eq)?;
1670 url = Some(match parser.next_token().token {
1671 Token::SingleQuotedString(word) => Ok(word),
1672 _ => parser.expected_ref("a URL statement", parser.peek_token_ref()),
1673 }?)
1674 }
1675
1676 if parser.parse_keyword(Keyword::STORAGE_INTEGRATION) {
1678 parser.expect_token(&Token::Eq)?;
1679 storage_integration = Some(parser.next_token().token.to_string());
1680 }
1681
1682 if parser.parse_keyword(Keyword::ENDPOINT) {
1684 parser.expect_token(&Token::Eq)?;
1685 endpoint = Some(match parser.next_token().token {
1686 Token::SingleQuotedString(word) => Ok(word),
1687 _ => parser.expected_ref("an endpoint statement", parser.peek_token_ref()),
1688 }?)
1689 }
1690
1691 if parser.parse_keyword(Keyword::CREDENTIALS) {
1693 parser.expect_token(&Token::Eq)?;
1694 credentials = KeyValueOptions {
1695 options: parser.parse_key_value_options(true, &[])?.options,
1696 delimiter: KeyValueOptionsDelimiter::Space,
1697 };
1698 }
1699
1700 if parser.parse_keyword(Keyword::ENCRYPTION) {
1702 parser.expect_token(&Token::Eq)?;
1703 encryption = KeyValueOptions {
1704 options: parser.parse_key_value_options(true, &[])?.options,
1705 delimiter: KeyValueOptionsDelimiter::Space,
1706 };
1707 }
1708
1709 Ok(StageParamsObject {
1710 url,
1711 encryption,
1712 endpoint,
1713 storage_integration,
1714 credentials,
1715 })
1716}
1717
1718fn parse_session_options(
1723 parser: &mut Parser,
1724 set: bool,
1725) -> Result<Vec<KeyValueOption>, ParserError> {
1726 let mut options: Vec<KeyValueOption> = Vec::new();
1727 let empty = String::new;
1728 loop {
1729 let peeked_token = parser.peek_token();
1730 match peeked_token.token {
1731 Token::SemiColon | Token::EOF => break,
1732 Token::Comma => {
1733 parser.advance_token();
1734 continue;
1735 }
1736 Token::Word(key) => {
1737 parser.advance_token();
1738 if set {
1739 let option = parser.parse_key_value_option(&key)?;
1740 options.push(option);
1741 } else {
1742 options.push(KeyValueOption {
1743 option_name: key.value,
1744 option_value: KeyValueOptionKind::Single(
1745 Value::Placeholder(empty()).with_span(Span {
1746 start: peeked_token.span.end,
1747 end: peeked_token.span.end,
1748 }),
1749 ),
1750 });
1751 }
1752 }
1753 _ => {
1754 return parser.expected("another option or end of statement", peeked_token);
1755 }
1756 }
1757 }
1758 if options.is_empty() {
1759 Err(ParserError::ParserError(
1760 "expected at least one option".to_string(),
1761 ))
1762 } else {
1763 Ok(options)
1764 }
1765}
1766
1767fn parse_identity_property(parser: &mut Parser) -> Result<IdentityProperty, ParserError> {
1774 let parameters = if parser.consume_token(&Token::LParen) {
1775 let seed = parser.parse_number()?;
1776 parser.expect_token(&Token::Comma)?;
1777 let increment = parser.parse_number()?;
1778 parser.expect_token(&Token::RParen)?;
1779
1780 Some(IdentityPropertyFormatKind::FunctionCall(
1781 IdentityParameters { seed, increment },
1782 ))
1783 } else if parser.parse_keyword(Keyword::START) {
1784 let seed = parser.parse_number()?;
1785 parser.expect_keyword_is(Keyword::INCREMENT)?;
1786 let increment = parser.parse_number()?;
1787
1788 Some(IdentityPropertyFormatKind::StartAndIncrement(
1789 IdentityParameters { seed, increment },
1790 ))
1791 } else {
1792 None
1793 };
1794 let order = match parser.parse_one_of_keywords(&[Keyword::ORDER, Keyword::NOORDER]) {
1795 Some(Keyword::ORDER) => Some(IdentityPropertyOrder::Order),
1796 Some(Keyword::NOORDER) => Some(IdentityPropertyOrder::NoOrder),
1797 _ => None,
1798 };
1799 Ok(IdentityProperty { parameters, order })
1800}
1801
1802fn parse_column_policy_property(
1809 parser: &mut Parser,
1810 with: bool,
1811) -> Result<ColumnPolicyProperty, ParserError> {
1812 let policy_name = parser.parse_object_name(false)?;
1813 let using_columns = if parser.parse_keyword(Keyword::USING) {
1814 parser.expect_token(&Token::LParen)?;
1815 let columns = parser.parse_comma_separated(|p| p.parse_identifier())?;
1816 parser.expect_token(&Token::RParen)?;
1817 Some(columns)
1818 } else {
1819 None
1820 };
1821
1822 Ok(ColumnPolicyProperty {
1823 with,
1824 policy_name,
1825 using_columns,
1826 })
1827}
1828
1829fn parse_column_tags(parser: &mut Parser, with: bool) -> Result<TagsColumnOption, ParserError> {
1836 parser.expect_token(&Token::LParen)?;
1837 let tags = parser.parse_comma_separated(Parser::parse_tag)?;
1838 parser.expect_token(&Token::RParen)?;
1839
1840 Ok(TagsColumnOption { with, tags })
1841}
1842
1843fn parse_show_objects(terse: bool, parser: &mut Parser) -> Result<Statement, ParserError> {
1846 let show_options = parser.parse_show_stmt_options()?;
1847 Ok(Statement::ShowObjects(ShowObjects {
1848 terse,
1849 show_options,
1850 }))
1851}
1852
1853fn parse_multi_table_insert(
1872 parser: &mut Parser,
1873 insert_token: TokenWithSpan,
1874 overwrite: bool,
1875 multi_table_insert_type: MultiTableInsertType,
1876) -> Result<Statement, ParserError> {
1877 let is_conditional = parser.peek_keyword(Keyword::WHEN);
1879
1880 let (multi_table_into_clauses, multi_table_when_clauses, multi_table_else_clause) =
1881 if is_conditional {
1882 let (when_clauses, else_clause) = parse_multi_table_insert_when_clauses(parser)?;
1884 (vec![], when_clauses, else_clause)
1885 } else {
1886 let into_clauses = parse_multi_table_insert_into_clauses(parser)?;
1888 (into_clauses, vec![], None)
1889 };
1890
1891 let source = parser.parse_query()?;
1893
1894 Ok(Statement::Insert(Insert {
1895 insert_token: insert_token.into(),
1896 optimizer_hints: vec![],
1897 or: None,
1898 ignore: false,
1899 into: false,
1900 table: TableObject::TableName(ObjectName(vec![])), table_alias: None,
1902 columns: vec![],
1903 by_name: false,
1904 overwrite,
1905 source: Some(source),
1906 assignments: vec![],
1907 partitioned: None,
1908 after_columns: vec![],
1909 has_table_keyword: false,
1910 on: None,
1911 returning: None,
1912 output: None,
1913 replace_into: false,
1914 priority: None,
1915 insert_alias: None,
1916 settings: None,
1917 format_clause: None,
1918 multi_table_insert_type: Some(multi_table_insert_type),
1919 multi_table_into_clauses,
1920 multi_table_when_clauses,
1921 multi_table_else_clause,
1922 }))
1923}
1924
1925fn parse_multi_table_insert_into_clauses(
1927 parser: &mut Parser,
1928) -> Result<Vec<MultiTableInsertIntoClause>, ParserError> {
1929 let mut into_clauses = vec![];
1930 while parser.parse_keyword(Keyword::INTO) {
1931 into_clauses.push(parse_multi_table_insert_into_clause(parser)?);
1932 }
1933 if into_clauses.is_empty() {
1934 return parser.expected_ref("INTO clause in multi-table INSERT", parser.peek_token_ref());
1935 }
1936 Ok(into_clauses)
1937}
1938
1939fn parse_multi_table_insert_into_clause(
1943 parser: &mut Parser,
1944) -> Result<MultiTableInsertIntoClause, ParserError> {
1945 let table_name = parser.parse_object_name(false)?;
1946
1947 let columns = parser
1949 .maybe_parse(|p| p.parse_parenthesized_column_list(IsOptional::Mandatory, false))?
1950 .unwrap_or_default();
1951
1952 let values = if parser.parse_keyword(Keyword::VALUES) {
1954 parser.expect_token(&Token::LParen)?;
1955 let values = parser.parse_comma_separated(parse_multi_table_insert_value)?;
1956 parser.expect_token(&Token::RParen)?;
1957 Some(MultiTableInsertValues { values })
1958 } else {
1959 None
1960 };
1961
1962 Ok(MultiTableInsertIntoClause {
1963 table_name,
1964 columns,
1965 values,
1966 })
1967}
1968
1969fn parse_multi_table_insert_value(
1971 parser: &mut Parser,
1972) -> Result<MultiTableInsertValue, ParserError> {
1973 if parser.parse_keyword(Keyword::DEFAULT) {
1974 Ok(MultiTableInsertValue::Default)
1975 } else {
1976 Ok(MultiTableInsertValue::Expr(parser.parse_expr()?))
1977 }
1978}
1979
1980fn parse_multi_table_insert_when_clauses(
1982 parser: &mut Parser,
1983) -> Result<
1984 (
1985 Vec<MultiTableInsertWhenClause>,
1986 Option<Vec<MultiTableInsertIntoClause>>,
1987 ),
1988 ParserError,
1989> {
1990 let mut when_clauses = vec![];
1991 let mut else_clause = None;
1992
1993 while parser.parse_keyword(Keyword::WHEN) {
1995 let condition = parser.parse_expr()?;
1996 parser.expect_keyword(Keyword::THEN)?;
1997
1998 let into_clauses = parse_multi_table_insert_into_clauses(parser)?;
2000
2001 when_clauses.push(MultiTableInsertWhenClause {
2002 condition,
2003 into_clauses,
2004 });
2005 }
2006
2007 if parser.parse_keyword(Keyword::ELSE) {
2009 else_clause = Some(parse_multi_table_insert_into_clauses(parser)?);
2010 }
2011
2012 if when_clauses.is_empty() {
2013 return parser.expected_ref(
2014 "at least one WHEN clause in conditional multi-table INSERT",
2015 parser.peek_token_ref(),
2016 );
2017 }
2018
2019 Ok((when_clauses, else_clause))
2020}