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_object_name_double_dot_notation(&self) -> bool {
161 true
162 }
163
164 fn is_identifier_part(&self, ch: char) -> bool {
165 ch.is_ascii_lowercase()
166 || ch.is_ascii_uppercase()
167 || ch.is_ascii_digit()
168 || ch == '$'
169 || ch == '_'
170 }
171
172 fn supports_string_literal_backslash_escape(&self) -> bool {
174 true
175 }
176
177 fn supports_within_after_array_aggregation(&self) -> bool {
178 true
179 }
180
181 fn supports_outer_join_operator(&self) -> bool {
183 true
184 }
185
186 fn supports_connect_by(&self) -> bool {
187 true
188 }
189
190 fn supports_execute_immediate(&self) -> bool {
192 true
193 }
194
195 fn supports_match_recognize(&self) -> bool {
196 true
197 }
198
199 fn supports_dictionary_syntax(&self) -> bool {
204 true
205 }
206
207 fn supports_window_function_null_treatment_arg(&self) -> bool {
210 true
211 }
212
213 fn supports_parenthesized_set_variables(&self) -> bool {
215 true
216 }
217
218 fn supports_comment_on(&self) -> bool {
220 true
221 }
222
223 fn supports_extract_comma_syntax(&self) -> bool {
225 true
226 }
227
228 fn supports_subquery_as_function_arg(&self) -> bool {
230 true
231 }
232
233 fn supports_create_view_comment_syntax(&self) -> bool {
235 true
236 }
237
238 fn supports_array_typedef_without_element_type(&self) -> bool {
240 true
241 }
242
243 fn supports_parens_around_table_factor(&self) -> bool {
245 true
246 }
247
248 fn supports_values_as_table_factor(&self) -> bool {
250 true
251 }
252
253 fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
254 if parser.parse_keyword(Keyword::BEGIN) {
255 if parser
259 .peek_one_of_keywords(&[Keyword::TRANSACTION, Keyword::WORK, Keyword::NAME])
260 .is_some()
261 || matches!(parser.peek_token_ref().token, Token::SemiColon | Token::EOF)
262 {
263 parser.prev_token();
264 return None;
265 }
266 return Some(parser.parse_begin_exception_end());
267 }
268
269 if parser.parse_keywords(&[Keyword::ALTER, Keyword::DYNAMIC, Keyword::TABLE]) {
270 return Some(parse_alter_dynamic_table(parser));
272 }
273
274 if parser.parse_keywords(&[Keyword::ALTER, Keyword::EXTERNAL, Keyword::TABLE]) {
275 return Some(parse_alter_external_table(parser));
277 }
278
279 if parser.parse_keywords(&[Keyword::ALTER, Keyword::SESSION]) {
280 let set = match parser.parse_one_of_keywords(&[Keyword::SET, Keyword::UNSET]) {
282 Some(Keyword::SET) => true,
283 Some(Keyword::UNSET) => false,
284 _ => return Some(parser.expected_ref("SET or UNSET", parser.peek_token_ref())),
285 };
286 return Some(parse_alter_session(parser, set));
287 }
288
289 if parser.parse_keyword(Keyword::CREATE) {
290 let or_replace = parser.parse_keywords(&[Keyword::OR, Keyword::REPLACE]);
293 let global = match parser.parse_one_of_keywords(&[Keyword::LOCAL, Keyword::GLOBAL]) {
295 Some(Keyword::LOCAL) => Some(false),
296 Some(Keyword::GLOBAL) => Some(true),
297 _ => None,
298 };
299
300 let dynamic = parser.parse_keyword(Keyword::DYNAMIC);
301
302 let mut temporary = false;
303 let mut volatile = false;
304 let mut transient = false;
305 let mut iceberg = false;
306
307 match parser.parse_one_of_keywords(&[
308 Keyword::TEMP,
309 Keyword::TEMPORARY,
310 Keyword::VOLATILE,
311 Keyword::TRANSIENT,
312 Keyword::ICEBERG,
313 ]) {
314 Some(Keyword::TEMP | Keyword::TEMPORARY) => temporary = true,
315 Some(Keyword::VOLATILE) => volatile = true,
316 Some(Keyword::TRANSIENT) => transient = true,
317 Some(Keyword::ICEBERG) => iceberg = true,
318 _ => {}
319 }
320
321 if parser.parse_keyword(Keyword::STAGE) {
322 return Some(parse_create_stage(or_replace, temporary, parser));
324 } else if parser.parse_keyword(Keyword::TABLE) {
325 return Some(
326 parse_create_table(
327 or_replace, global, temporary, volatile, transient, iceberg, dynamic,
328 parser,
329 )
330 .map(Into::into),
331 );
332 } else if parser.parse_keyword(Keyword::DATABASE) {
333 return Some(parse_create_database(or_replace, transient, parser));
334 } else if parser.parse_keywords(&[Keyword::FILE, Keyword::FORMAT]) {
335 return Some(parse_create_file_format(
336 or_replace, temporary, volatile, parser,
337 ));
338 } else {
339 let mut back = 1;
341 if or_replace {
342 back += 2
343 }
344 if temporary {
345 back += 1
346 }
347 for _i in 0..back {
348 parser.prev_token();
349 }
350 }
351 }
352 if parser.parse_keywords(&[Keyword::COPY, Keyword::INTO]) {
353 return Some(parse_copy_into(parser));
355 }
356
357 if let Some(kw) = parser.parse_one_of_keywords(&[
358 Keyword::LIST,
359 Keyword::LS,
360 Keyword::REMOVE,
361 Keyword::RM,
362 ]) {
363 return Some(parse_file_staging_command(kw, parser));
364 }
365
366 if parser.parse_keyword(Keyword::PUT) {
367 return Some(parse_put(parser));
368 }
369
370 if parser.parse_keyword(Keyword::SHOW) {
371 let terse = parser.parse_keyword(Keyword::TERSE);
372 if parser.parse_keyword(Keyword::OBJECTS) {
373 return Some(parse_show_objects(terse, parser));
374 }
375 if terse {
377 parser.prev_token();
378 }
379 parser.prev_token();
381 }
382
383 if parser.parse_keyword(Keyword::INSERT) {
386 let insert_token = parser.get_current_token().clone();
387 let overwrite = parser.parse_keyword(Keyword::OVERWRITE);
388
389 if let Some(kw) = parser.parse_one_of_keywords(&[Keyword::ALL, Keyword::FIRST]) {
391 let multi_table_insert_type = match kw {
392 Keyword::FIRST => MultiTableInsertType::First,
393 _ => MultiTableInsertType::All,
394 };
395 return Some(parse_multi_table_insert(
396 parser,
397 insert_token,
398 overwrite,
399 multi_table_insert_type,
400 ));
401 }
402
403 if overwrite {
405 parser.prev_token(); }
407 parser.prev_token(); }
409
410 None
411 }
412
413 fn parse_column_option(
414 &self,
415 parser: &mut Parser,
416 ) -> Result<Option<Result<Option<ColumnOption>, ParserError>>, ParserError> {
417 parser.maybe_parse(|parser| {
418 let with = parser.parse_keyword(Keyword::WITH);
419
420 if parser.parse_keyword(Keyword::IDENTITY) {
421 Ok(parse_identity_property(parser)
422 .map(|p| Some(ColumnOption::Identity(IdentityPropertyKind::Identity(p)))))
423 } else if parser.parse_keyword(Keyword::AUTOINCREMENT) {
424 Ok(parse_identity_property(parser).map(|p| {
425 Some(ColumnOption::Identity(IdentityPropertyKind::Autoincrement(
426 p,
427 )))
428 }))
429 } else if parser.parse_keywords(&[Keyword::MASKING, Keyword::POLICY]) {
430 Ok(parse_column_policy_property(parser, with)
431 .map(|p| Some(ColumnOption::Policy(ColumnPolicy::MaskingPolicy(p)))))
432 } else if parser.parse_keywords(&[Keyword::PROJECTION, Keyword::POLICY]) {
433 Ok(parse_column_policy_property(parser, with)
434 .map(|p| Some(ColumnOption::Policy(ColumnPolicy::ProjectionPolicy(p)))))
435 } else if parser.parse_keywords(&[Keyword::TAG]) {
436 Ok(parse_column_tags(parser, with).map(|p| Some(ColumnOption::Tags(p))))
437 } else {
438 Err(ParserError::ParserError("not found match".to_string()))
439 }
440 })
441 }
442
443 fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
444 let token = parser.peek_token_ref();
445 match &token.token {
447 Token::Colon => Some(Ok(self.prec_value(Precedence::DoubleColon))),
448 _ => None,
449 }
450 }
451
452 fn describe_requires_table_keyword(&self) -> bool {
453 true
454 }
455
456 fn allow_extract_custom(&self) -> bool {
457 true
458 }
459
460 fn allow_extract_single_quotes(&self) -> bool {
461 true
462 }
463
464 fn supports_show_like_before_in(&self) -> bool {
467 true
468 }
469
470 fn supports_left_associative_joins_without_parens(&self) -> bool {
471 false
472 }
473
474 fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {
475 if matches!(kw, Keyword::INTERVAL) {
478 false
479 } else {
480 RESERVED_FOR_IDENTIFIER.contains(&kw)
481 }
482 }
483
484 fn supports_partiql(&self) -> bool {
485 true
486 }
487
488 fn is_column_alias(&self, kw: &Keyword, parser: &mut Parser) -> bool {
489 match kw {
490 Keyword::EXCEPT
494 | Keyword::RETURNING if !matches!(parser.peek_token_ref().token, Token::Comma | Token::EOF) =>
496 {
497 false
498 }
499
500 Keyword::LIMIT | Keyword::OFFSET if peek_for_limit_options(parser) => false,
503
504 Keyword::FETCH if parser.peek_one_of_keywords(&[Keyword::FIRST, Keyword::NEXT]).is_some()
509 || peek_for_limit_options(parser) =>
510 {
511 false
512 }
513
514 Keyword::FROM
518 | Keyword::GROUP
519 | Keyword::HAVING
520 | Keyword::INTERSECT
521 | Keyword::INTO
522 | Keyword::MINUS
523 | Keyword::ORDER
524 | Keyword::SELECT
525 | Keyword::UNION
526 | Keyword::WHERE
527 | Keyword::WITH => false,
528
529 _ => true,
531 }
532 }
533
534 fn is_table_alias(&self, kw: &Keyword, parser: &mut Parser) -> bool {
535 match kw {
536 Keyword::RETURNING
539 | Keyword::INNER
540 | Keyword::USING
541 | Keyword::PIVOT
542 | Keyword::UNPIVOT
543 | Keyword::EXCEPT
544 | Keyword::MATCH_RECOGNIZE
545 if !matches!(parser.peek_token_ref().token, Token::SemiColon | Token::EOF) =>
546 {
547 false
548 }
549
550 Keyword::LIMIT | Keyword::OFFSET if peek_for_limit_options(parser) => false,
554
555 Keyword::FETCH
560 if parser
561 .peek_one_of_keywords(&[Keyword::FIRST, Keyword::NEXT])
562 .is_some()
563 || peek_for_limit_options(parser) =>
564 {
565 false
566 }
567
568 Keyword::RIGHT | Keyword::LEFT | Keyword::SEMI | Keyword::ANTI
571 if parser
572 .peek_one_of_keywords(&[Keyword::JOIN, Keyword::OUTER])
573 .is_some() =>
574 {
575 false
576 }
577
578 Keyword::GLOBAL if parser.peek_keyword(Keyword::FULL) => false,
579
580 Keyword::WITH
584 | Keyword::ORDER
585 | Keyword::SELECT
586 | Keyword::WHERE
587 | Keyword::GROUP
588 | Keyword::HAVING
589 | Keyword::LATERAL
590 | Keyword::UNION
591 | Keyword::INTERSECT
592 | Keyword::MINUS
593 | Keyword::ON
594 | Keyword::JOIN
595 | Keyword::INNER
596 | Keyword::CROSS
597 | Keyword::FULL
598 | Keyword::LEFT
599 | Keyword::RIGHT
600 | Keyword::NATURAL
601 | Keyword::USING
602 | Keyword::ASOF
603 | Keyword::MATCH_CONDITION
604 | Keyword::SET
605 | Keyword::QUALIFY
606 | Keyword::FOR
607 | Keyword::START
608 | Keyword::CONNECT
609 | Keyword::SAMPLE
610 | Keyword::TABLESAMPLE
611 | Keyword::FROM => false,
612
613 _ => true,
615 }
616 }
617
618 fn is_table_factor(&self, kw: &Keyword, parser: &mut Parser) -> bool {
619 match kw {
620 Keyword::LIMIT if peek_for_limit_options(parser) => false,
621 Keyword::TABLE if matches!(parser.peek_token_ref().token, Token::LParen) => true,
623 _ => !RESERVED_KEYWORDS_FOR_TABLE_FACTOR.contains(kw),
624 }
625 }
626
627 fn supports_table_versioning(&self) -> bool {
629 true
630 }
631
632 fn supports_group_by_expr(&self) -> bool {
634 true
635 }
636
637 fn get_reserved_keywords_for_select_item_operator(&self) -> &[Keyword] {
639 &RESERVED_KEYWORDS_FOR_SELECT_ITEM_OPERATOR
640 }
641
642 fn supports_space_separated_column_options(&self) -> bool {
643 true
644 }
645
646 fn supports_comma_separated_drop_column_list(&self) -> bool {
647 true
648 }
649
650 fn is_identifier_generating_function_name(
651 &self,
652 ident: &Ident,
653 name_parts: &[ObjectNamePart],
654 ) -> bool {
655 ident.quote_style.is_none()
656 && ident.value.to_lowercase() == "identifier"
657 && !name_parts
658 .iter()
659 .any(|p| matches!(p, ObjectNamePart::Function(_)))
660 }
661
662 fn supports_select_expr_star(&self) -> bool {
664 true
665 }
666
667 fn supports_select_wildcard_exclude(&self) -> bool {
668 true
669 }
670
671 fn supports_semantic_view_table_factor(&self) -> bool {
672 true
673 }
674
675 fn supports_select_wildcard_replace(&self) -> bool {
677 true
678 }
679
680 fn supports_select_wildcard_ilike(&self) -> bool {
682 true
683 }
684
685 fn supports_select_wildcard_rename(&self) -> bool {
687 true
688 }
689
690 fn supports_lambda_functions(&self) -> bool {
692 true
693 }
694
695 fn supports_comma_separated_trim(&self) -> bool {
696 true
697 }
698}
699
700fn peek_for_limit_options(parser: &Parser) -> bool {
703 match &parser.peek_token_ref().token {
704 Token::Number(_, _) | Token::Placeholder(_) => true,
705 Token::SingleQuotedString(val) if val.is_empty() => true,
706 Token::DollarQuotedString(DollarQuotedString { value, .. }) if value.is_empty() => true,
707 Token::Word(w) if w.keyword == Keyword::NULL => true,
708 _ => false,
709 }
710}
711
712fn parse_put(parser: &mut Parser) -> Result<Statement, ParserError> {
717 let source = parser.parse_literal_string()?;
718 let stage = parse_snowflake_stage_name(parser)?;
719 let options = parser.parse_key_value_options(false, &[])?;
720 Ok(Statement::Put {
721 source,
722 stage,
723 options,
724 })
725}
726
727fn parse_file_staging_command(kw: Keyword, parser: &mut Parser) -> Result<Statement, ParserError> {
728 let stage = parse_snowflake_stage_name(parser)?;
729 let pattern = if parser.parse_keyword(Keyword::PATTERN) {
730 parser.expect_token(&Token::Eq)?;
731 Some(parser.parse_literal_string()?)
732 } else {
733 None
734 };
735
736 match kw {
737 Keyword::LIST | Keyword::LS => Ok(Statement::List(FileStagingCommand { stage, pattern })),
738 Keyword::REMOVE | Keyword::RM => {
739 Ok(Statement::Remove(FileStagingCommand { stage, pattern }))
740 }
741 _ => Err(ParserError::ParserError(
742 "unexpected stage command, expecting LIST, LS, REMOVE or RM".to_string(),
743 )),
744 }
745}
746
747fn parse_alter_dynamic_table(parser: &mut Parser) -> Result<Statement, ParserError> {
750 let table_name = parser.parse_object_name(true)?;
752
753 let operation = if parser.parse_keyword(Keyword::REFRESH) {
755 AlterTableOperation::Refresh { subpath: None }
756 } else if parser.parse_keyword(Keyword::SUSPEND) {
757 AlterTableOperation::Suspend
758 } else if parser.parse_keyword(Keyword::RESUME) {
759 AlterTableOperation::Resume
760 } else {
761 return parser.expected_ref(
762 "REFRESH, SUSPEND, or RESUME after ALTER DYNAMIC TABLE",
763 parser.peek_token_ref(),
764 );
765 };
766
767 let end_token = if parser.peek_token_ref().token == Token::SemiColon {
768 parser.peek_token_ref().clone()
769 } else {
770 parser.get_current_token().clone()
771 };
772
773 Ok(Statement::AlterTable(AlterTable {
774 name: table_name,
775 if_exists: false,
776 only: false,
777 operations: vec![operation],
778 location: None,
779 on_cluster: None,
780 table_type: Some(AlterTableType::Dynamic),
781 end_token: AttachedToken(end_token),
782 }))
783}
784
785fn parse_alter_external_table(parser: &mut Parser) -> Result<Statement, ParserError> {
788 let if_exists = parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
789 let table_name = parser.parse_object_name(true)?;
790
791 let operation = if parser.parse_keyword(Keyword::REFRESH) {
793 let subpath = match parser.peek_token().token {
795 Token::SingleQuotedString(s) => {
796 parser.next_token();
797 Some(s)
798 }
799 _ => None,
800 };
801 AlterTableOperation::Refresh { subpath }
802 } else {
803 return parser.expected_ref(
804 "REFRESH after ALTER EXTERNAL TABLE",
805 parser.peek_token_ref(),
806 );
807 };
808
809 let end_token = if parser.peek_token_ref().token == Token::SemiColon {
810 parser.peek_token_ref().clone()
811 } else {
812 parser.get_current_token().clone()
813 };
814
815 Ok(Statement::AlterTable(AlterTable {
816 name: table_name,
817 if_exists,
818 only: false,
819 operations: vec![operation],
820 location: None,
821 on_cluster: None,
822 table_type: Some(AlterTableType::External),
823 end_token: AttachedToken(end_token),
824 }))
825}
826
827fn parse_alter_session(parser: &mut Parser, set: bool) -> Result<Statement, ParserError> {
830 let session_options = parse_session_options(parser, set)?;
831 Ok(Statement::AlterSession {
832 set,
833 session_params: KeyValueOptions {
834 options: session_options,
835 delimiter: KeyValueOptionsDelimiter::Space,
836 },
837 })
838}
839
840#[allow(clippy::too_many_arguments)]
844pub fn parse_create_table(
845 or_replace: bool,
846 global: Option<bool>,
847 temporary: bool,
848 volatile: bool,
849 transient: bool,
850 iceberg: bool,
851 dynamic: bool,
852 parser: &mut Parser,
853) -> Result<CreateTable, ParserError> {
854 let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
855 let table_name = parser.parse_object_name(false)?;
856
857 let mut builder = CreateTableBuilder::new(table_name)
858 .or_replace(or_replace)
859 .if_not_exists(if_not_exists)
860 .temporary(temporary)
861 .transient(transient)
862 .volatile(volatile)
863 .iceberg(iceberg)
864 .global(global)
865 .dynamic(dynamic)
866 .hive_formats(None);
867
868 let mut plain_options = vec![];
875
876 loop {
877 let next_token = parser.next_token();
878 match &next_token.token {
879 Token::Word(word) => match word.keyword {
880 Keyword::COPY => {
881 parser.expect_keyword_is(Keyword::GRANTS)?;
882 builder = builder.copy_grants(true);
883 }
884 Keyword::COMMENT => {
885 parser.prev_token();
887 if let Some(comment_def) = parser.parse_optional_inline_comment()? {
888 plain_options.push(SqlOption::Comment(comment_def))
889 }
890 }
891 Keyword::AS => {
892 let query = parser.parse_query()?;
893 builder = builder.query(Some(query));
894 }
895 Keyword::CLONE => {
896 let clone = parser.parse_object_name(false).ok();
897 builder = builder.clone_clause(clone);
898 }
899 Keyword::LIKE => {
900 let name = parser.parse_object_name(false)?;
901 builder = builder.like(Some(CreateTableLikeKind::Plain(
902 crate::ast::CreateTableLike {
903 name,
904 defaults: None,
905 },
906 )));
907 }
908 Keyword::CLUSTER => {
909 parser.expect_keyword_is(Keyword::BY)?;
910 parser.expect_token(&Token::LParen)?;
911 let cluster_by = Some(WrappedCollection::Parentheses(
912 parser.parse_comma_separated(|p| p.parse_expr())?,
913 ));
914 parser.expect_token(&Token::RParen)?;
915
916 builder = builder.cluster_by(cluster_by)
917 }
918 Keyword::ENABLE_SCHEMA_EVOLUTION => {
919 parser.expect_token(&Token::Eq)?;
920 builder = builder.enable_schema_evolution(Some(parser.parse_boolean_string()?));
921 }
922 Keyword::CHANGE_TRACKING => {
923 parser.expect_token(&Token::Eq)?;
924 builder = builder.change_tracking(Some(parser.parse_boolean_string()?));
925 }
926 Keyword::DATA_RETENTION_TIME_IN_DAYS => {
927 parser.expect_token(&Token::Eq)?;
928 let data_retention_time_in_days = parser.parse_literal_uint()?;
929 builder =
930 builder.data_retention_time_in_days(Some(data_retention_time_in_days));
931 }
932 Keyword::MAX_DATA_EXTENSION_TIME_IN_DAYS => {
933 parser.expect_token(&Token::Eq)?;
934 let max_data_extension_time_in_days = parser.parse_literal_uint()?;
935 builder = builder
936 .max_data_extension_time_in_days(Some(max_data_extension_time_in_days));
937 }
938 Keyword::DEFAULT_DDL_COLLATION => {
939 parser.expect_token(&Token::Eq)?;
940 let default_ddl_collation = parser.parse_literal_string()?;
941 builder = builder.default_ddl_collation(Some(default_ddl_collation));
942 }
943 Keyword::WITH => {
946 parser.expect_one_of_keywords(&[
947 Keyword::AGGREGATION,
948 Keyword::STORAGE,
949 Keyword::TAG,
950 Keyword::ROW,
951 ])?;
952 parser.prev_token();
953 }
954 Keyword::AGGREGATION => {
955 parser.expect_keyword_is(Keyword::POLICY)?;
956 let aggregation_policy = parser.parse_object_name(false)?;
957 builder = builder.with_aggregation_policy(Some(aggregation_policy));
958 }
959 Keyword::ROW => {
960 parser.expect_keywords(&[Keyword::ACCESS, Keyword::POLICY])?;
961 let policy = parser.parse_object_name(false)?;
962 parser.expect_keyword_is(Keyword::ON)?;
963 parser.expect_token(&Token::LParen)?;
964 let columns = parser.parse_comma_separated(|p| p.parse_identifier())?;
965 parser.expect_token(&Token::RParen)?;
966
967 builder =
968 builder.with_row_access_policy(Some(RowAccessPolicy::new(policy, columns)))
969 }
970 Keyword::STORAGE => {
971 parser.expect_keywords(&[Keyword::LIFECYCLE, Keyword::POLICY])?;
972 let policy = parser.parse_object_name(false)?;
973 parser.expect_keyword_is(Keyword::ON)?;
974 parser.expect_token(&Token::LParen)?;
975 let columns = parser.parse_comma_separated(|p| p.parse_identifier())?;
976 parser.expect_token(&Token::RParen)?;
977
978 builder = builder.with_storage_lifecycle_policy(Some(StorageLifecyclePolicy {
979 policy,
980 on: columns,
981 }))
982 }
983 Keyword::TAG => {
984 parser.expect_token(&Token::LParen)?;
985 let tags = parser.parse_comma_separated(Parser::parse_tag)?;
986 parser.expect_token(&Token::RParen)?;
987 builder = builder.with_tags(Some(tags));
988 }
989 Keyword::ON if parser.parse_keyword(Keyword::COMMIT) => {
990 let on_commit = Some(parser.parse_create_table_on_commit()?);
991 builder = builder.on_commit(on_commit);
992 }
993 Keyword::EXTERNAL_VOLUME => {
994 parser.expect_token(&Token::Eq)?;
995 builder.external_volume = Some(parser.parse_literal_string()?);
996 }
997 Keyword::CATALOG => {
998 parser.expect_token(&Token::Eq)?;
999 builder.catalog = Some(parser.parse_literal_string()?);
1000 }
1001 Keyword::BASE_LOCATION => {
1002 parser.expect_token(&Token::Eq)?;
1003 builder.base_location = Some(parser.parse_literal_string()?);
1004 }
1005 Keyword::CATALOG_SYNC => {
1006 parser.expect_token(&Token::Eq)?;
1007 builder.catalog_sync = Some(parser.parse_literal_string()?);
1008 }
1009 Keyword::STORAGE_SERIALIZATION_POLICY => {
1010 parser.expect_token(&Token::Eq)?;
1011
1012 builder.storage_serialization_policy =
1013 Some(parse_storage_serialization_policy(parser)?);
1014 }
1015 Keyword::IF if parser.parse_keywords(&[Keyword::NOT, Keyword::EXISTS]) => {
1016 builder = builder.if_not_exists(true);
1017 }
1018 Keyword::TARGET_LAG => {
1019 parser.expect_token(&Token::Eq)?;
1020 let target_lag = parser.parse_literal_string()?;
1021 builder = builder.target_lag(Some(target_lag));
1022 }
1023 Keyword::WAREHOUSE => {
1024 parser.expect_token(&Token::Eq)?;
1025 let warehouse = parser.parse_identifier()?;
1026 builder = builder.warehouse(Some(warehouse));
1027 }
1028 Keyword::AT | Keyword::BEFORE => {
1029 parser.prev_token();
1030 let version = parser.maybe_parse_table_version()?;
1031 builder = builder.version(version);
1032 }
1033 Keyword::REFRESH_MODE => {
1034 parser.expect_token(&Token::Eq)?;
1035 let refresh_mode = match parser.parse_one_of_keywords(&[
1036 Keyword::AUTO,
1037 Keyword::FULL,
1038 Keyword::INCREMENTAL,
1039 ]) {
1040 Some(Keyword::AUTO) => Some(RefreshModeKind::Auto),
1041 Some(Keyword::FULL) => Some(RefreshModeKind::Full),
1042 Some(Keyword::INCREMENTAL) => Some(RefreshModeKind::Incremental),
1043 _ => return parser.expected("AUTO, FULL or INCREMENTAL", next_token),
1044 };
1045 builder = builder.refresh_mode(refresh_mode);
1046 }
1047 Keyword::INITIALIZE => {
1048 parser.expect_token(&Token::Eq)?;
1049 let initialize = match parser
1050 .parse_one_of_keywords(&[Keyword::ON_CREATE, Keyword::ON_SCHEDULE])
1051 {
1052 Some(Keyword::ON_CREATE) => Some(InitializeKind::OnCreate),
1053 Some(Keyword::ON_SCHEDULE) => Some(InitializeKind::OnSchedule),
1054 _ => return parser.expected("ON_CREATE or ON_SCHEDULE", next_token),
1055 };
1056 builder = builder.initialize(initialize);
1057 }
1058 Keyword::REQUIRE if parser.parse_keyword(Keyword::USER) => {
1059 builder = builder.require_user(true);
1060 }
1061 _ => {
1062 return parser.expected("end of statement", next_token);
1063 }
1064 },
1065 Token::LParen => {
1066 parser.prev_token();
1067 let (columns, constraints) = parser.parse_columns()?;
1068 builder = builder.columns(columns).constraints(constraints);
1069 }
1070 Token::EOF => {
1071 break;
1072 }
1073 Token::SemiColon => {
1074 parser.prev_token();
1075 break;
1076 }
1077 _ => {
1078 return parser.expected("end of statement", next_token);
1079 }
1080 }
1081 }
1082 let table_options = if !plain_options.is_empty() {
1083 crate::ast::CreateTableOptions::Plain(plain_options)
1084 } else {
1085 crate::ast::CreateTableOptions::None
1086 };
1087
1088 builder = builder.table_options(table_options);
1089
1090 if iceberg && builder.base_location.is_none() {
1091 return Err(ParserError::ParserError(
1092 "BASE_LOCATION is required for ICEBERG tables".to_string(),
1093 ));
1094 }
1095
1096 Ok(builder.build())
1097}
1098
1099pub fn parse_create_database(
1102 or_replace: bool,
1103 transient: bool,
1104 parser: &mut Parser,
1105) -> Result<Statement, ParserError> {
1106 let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
1107 let name = parser.parse_object_name(false)?;
1108
1109 let mut builder = CreateDatabaseBuilder::new(name)
1110 .or_replace(or_replace)
1111 .transient(transient)
1112 .if_not_exists(if_not_exists);
1113
1114 loop {
1115 let next_token = parser.next_token();
1116 match &next_token.token {
1117 Token::Word(word) => match word.keyword {
1118 Keyword::CLONE => {
1119 builder = builder.clone_clause(Some(parser.parse_object_name(false)?));
1120 }
1121 Keyword::DATA_RETENTION_TIME_IN_DAYS => {
1122 parser.expect_token(&Token::Eq)?;
1123 builder =
1124 builder.data_retention_time_in_days(Some(parser.parse_literal_uint()?));
1125 }
1126 Keyword::MAX_DATA_EXTENSION_TIME_IN_DAYS => {
1127 parser.expect_token(&Token::Eq)?;
1128 builder =
1129 builder.max_data_extension_time_in_days(Some(parser.parse_literal_uint()?));
1130 }
1131 Keyword::EXTERNAL_VOLUME => {
1132 parser.expect_token(&Token::Eq)?;
1133 builder = builder.external_volume(Some(parser.parse_literal_string()?));
1134 }
1135 Keyword::CATALOG => {
1136 parser.expect_token(&Token::Eq)?;
1137 builder = builder.catalog(Some(parser.parse_literal_string()?));
1138 }
1139 Keyword::REPLACE_INVALID_CHARACTERS => {
1140 parser.expect_token(&Token::Eq)?;
1141 builder =
1142 builder.replace_invalid_characters(Some(parser.parse_boolean_string()?));
1143 }
1144 Keyword::DEFAULT_DDL_COLLATION => {
1145 parser.expect_token(&Token::Eq)?;
1146 builder = builder.default_ddl_collation(Some(parser.parse_literal_string()?));
1147 }
1148 Keyword::STORAGE_SERIALIZATION_POLICY => {
1149 parser.expect_token(&Token::Eq)?;
1150 let policy = parse_storage_serialization_policy(parser)?;
1151 builder = builder.storage_serialization_policy(Some(policy));
1152 }
1153 Keyword::COMMENT => {
1154 parser.expect_token(&Token::Eq)?;
1155 builder = builder.comment(Some(parser.parse_literal_string()?));
1156 }
1157 Keyword::CATALOG_SYNC => {
1158 parser.expect_token(&Token::Eq)?;
1159 builder = builder.catalog_sync(Some(parser.parse_literal_string()?));
1160 }
1161 Keyword::CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER => {
1162 parser.expect_token(&Token::Eq)?;
1163 builder = builder.catalog_sync_namespace_flatten_delimiter(Some(
1164 parser.parse_literal_string()?,
1165 ));
1166 }
1167 Keyword::CATALOG_SYNC_NAMESPACE_MODE => {
1168 parser.expect_token(&Token::Eq)?;
1169 let mode =
1170 match parser.parse_one_of_keywords(&[Keyword::NEST, Keyword::FLATTEN]) {
1171 Some(Keyword::NEST) => CatalogSyncNamespaceMode::Nest,
1172 Some(Keyword::FLATTEN) => CatalogSyncNamespaceMode::Flatten,
1173 _ => {
1174 return parser.expected("NEST or FLATTEN", next_token);
1175 }
1176 };
1177 builder = builder.catalog_sync_namespace_mode(Some(mode));
1178 }
1179 Keyword::WITH => {
1180 if parser.parse_keyword(Keyword::TAG) {
1181 parser.expect_token(&Token::LParen)?;
1182 let tags = parser.parse_comma_separated(Parser::parse_tag)?;
1183 parser.expect_token(&Token::RParen)?;
1184 builder = builder.with_tags(Some(tags));
1185 } else if parser.parse_keyword(Keyword::CONTACT) {
1186 parser.expect_token(&Token::LParen)?;
1187 let contacts = parser.parse_comma_separated(|p| {
1188 let purpose = p.parse_identifier()?.value;
1189 p.expect_token(&Token::Eq)?;
1190 let contact = p.parse_identifier()?.value;
1191 Ok(ContactEntry { purpose, contact })
1192 })?;
1193 parser.expect_token(&Token::RParen)?;
1194 builder = builder.with_contacts(Some(contacts));
1195 } else {
1196 return parser.expected("TAG or CONTACT", next_token);
1197 }
1198 }
1199 _ => return parser.expected("end of statement", next_token),
1200 },
1201 Token::SemiColon | Token::EOF => break,
1202 _ => return parser.expected("end of statement", next_token),
1203 }
1204 }
1205 Ok(builder.build())
1206}
1207
1208pub fn parse_storage_serialization_policy(
1209 parser: &mut Parser,
1210) -> Result<StorageSerializationPolicy, ParserError> {
1211 let next_token = parser.next_token();
1212 match &next_token.token {
1213 Token::Word(w) => match w.keyword {
1214 Keyword::COMPATIBLE => Ok(StorageSerializationPolicy::Compatible),
1215 Keyword::OPTIMIZED => Ok(StorageSerializationPolicy::Optimized),
1216 _ => parser.expected("storage_serialization_policy", next_token),
1217 },
1218 _ => parser.expected("storage_serialization_policy", next_token),
1219 }
1220}
1221
1222pub fn parse_create_stage(
1223 or_replace: bool,
1224 temporary: bool,
1225 parser: &mut Parser,
1226) -> Result<Statement, ParserError> {
1227 let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
1229 let name = parser.parse_object_name(false)?;
1230 let mut directory_table_params = Vec::new();
1231 let mut file_format = Vec::new();
1232 let mut copy_options = Vec::new();
1233 let mut comment = None;
1234
1235 let stage_params = parse_stage_params(parser)?;
1237
1238 if parser.parse_keyword(Keyword::DIRECTORY) {
1240 parser.expect_token(&Token::Eq)?;
1241 directory_table_params = parser.parse_key_value_options(true, &[])?.options;
1242 }
1243
1244 if parser.parse_keyword(Keyword::FILE_FORMAT) {
1246 parser.expect_token(&Token::Eq)?;
1247 file_format = parser.parse_key_value_options(true, &[])?.options;
1248 }
1249
1250 if parser.parse_keyword(Keyword::COPY_OPTIONS) {
1252 parser.expect_token(&Token::Eq)?;
1253 copy_options = parser.parse_key_value_options(true, &[])?.options;
1254 }
1255
1256 if parser.parse_keyword(Keyword::COMMENT) {
1258 parser.expect_token(&Token::Eq)?;
1259 comment = Some(parser.parse_comment_value()?);
1260 }
1261
1262 Ok(Statement::CreateStage {
1263 or_replace,
1264 temporary,
1265 if_not_exists,
1266 name,
1267 stage_params,
1268 directory_table_params: KeyValueOptions {
1269 options: directory_table_params,
1270 delimiter: KeyValueOptionsDelimiter::Space,
1271 },
1272 file_format: KeyValueOptions {
1273 options: file_format,
1274 delimiter: KeyValueOptionsDelimiter::Space,
1275 },
1276 copy_options: KeyValueOptions {
1277 options: copy_options,
1278 delimiter: KeyValueOptionsDelimiter::Space,
1279 },
1280 comment,
1281 })
1282}
1283
1284pub fn parse_create_file_format(
1287 or_replace: bool,
1288 temporary: bool,
1289 volatile: bool,
1290 parser: &mut Parser,
1291) -> Result<Statement, ParserError> {
1292 let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
1293 let name = parser.parse_object_name(true)?;
1294 let options = parser.parse_key_value_options(false, &[Keyword::COMMENT])?;
1295 let comment = if parser.parse_keyword(Keyword::COMMENT) {
1296 parser.expect_token(&Token::Eq)?;
1297 Some(parser.parse_comment_value()?)
1298 } else {
1299 None
1300 };
1301
1302 Ok(Statement::CreateFileFormat {
1303 or_replace,
1304 temporary,
1305 volatile,
1306 if_not_exists,
1307 name,
1308 options,
1309 comment,
1310 })
1311}
1312
1313pub fn parse_stage_name_identifier(parser: &mut Parser) -> Result<Ident, ParserError> {
1314 let mut ident = String::new();
1315 while let Some(next_token) = parser.next_token_no_skip() {
1316 match &next_token.token {
1317 Token::Whitespace(_) | Token::SemiColon => break,
1318 Token::Period => {
1319 parser.prev_token();
1320 break;
1321 }
1322 Token::LParen | Token::RParen => {
1323 parser.prev_token();
1324 break;
1325 }
1326 Token::AtSign => ident.push('@'),
1327 Token::Tilde => ident.push('~'),
1328 Token::Mod => ident.push('%'),
1329 Token::Div => ident.push('/'),
1330 Token::Plus => ident.push('+'),
1331 Token::Minus => ident.push('-'),
1332 Token::Eq => ident.push('='),
1333 Token::Colon => ident.push(':'),
1334 Token::Number(n, _) => ident.push_str(n),
1335 Token::Word(w) => ident.push_str(&w.to_string()),
1336 _ => return parser.expected_ref("stage name identifier", parser.peek_token_ref()),
1337 }
1338 }
1339 Ok(Ident::new(ident))
1340}
1341
1342pub fn parse_snowflake_stage_name(parser: &mut Parser) -> Result<ObjectName, ParserError> {
1345 match parser.next_token().token {
1346 Token::AtSign => {
1347 parser.prev_token();
1348 let mut idents = vec![];
1349 loop {
1350 idents.push(parse_stage_name_identifier(parser)?);
1351 if !parser.consume_token(&Token::Period) {
1352 break;
1353 }
1354 }
1355 Ok(ObjectName::from(idents))
1356 }
1357 _ => {
1358 parser.prev_token();
1359 Ok(parser.parse_object_name(false)?)
1360 }
1361 }
1362}
1363
1364pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
1367 let kind = match &parser.peek_token_ref().token {
1368 Token::AtSign => CopyIntoSnowflakeKind::Location,
1370 Token::SingleQuotedString(s) if s.contains("://") => CopyIntoSnowflakeKind::Location,
1372 _ => CopyIntoSnowflakeKind::Table,
1373 };
1374
1375 let mut files: Vec<String> = vec![];
1376 let mut from_transformations: Option<Vec<StageLoadSelectItemKind>> = None;
1377 let mut from_stage_alias = None;
1378 let mut from_stage = None;
1379 let mut stage_params = StageParamsObject {
1380 url: None,
1381 encryption: KeyValueOptions {
1382 options: vec![],
1383 delimiter: KeyValueOptionsDelimiter::Space,
1384 },
1385 endpoint: None,
1386 storage_integration: None,
1387 credentials: KeyValueOptions {
1388 options: vec![],
1389 delimiter: KeyValueOptionsDelimiter::Space,
1390 },
1391 };
1392 let mut from_query = None;
1393 let mut partition = None;
1394 let mut file_format = Vec::new();
1395 let mut pattern = None;
1396 let mut validation_mode = None;
1397 let mut copy_options = Vec::new();
1398
1399 let into: ObjectName = parse_snowflake_stage_name(parser)?;
1400 if kind == CopyIntoSnowflakeKind::Location {
1401 stage_params = parse_stage_params(parser)?;
1402 }
1403
1404 let into_columns = match &parser.peek_token().token {
1405 Token::LParen => Some(parser.parse_parenthesized_column_list(IsOptional::Optional, true)?),
1406 _ => None,
1407 };
1408
1409 parser.expect_keyword_is(Keyword::FROM)?;
1410 match parser.next_token().token {
1411 Token::LParen if kind == CopyIntoSnowflakeKind::Table => {
1412 parser.expect_keyword_is(Keyword::SELECT)?;
1414 from_transformations = parse_select_items_for_data_load(parser)?;
1415
1416 parser.expect_keyword_is(Keyword::FROM)?;
1417 from_stage = Some(parse_snowflake_stage_name(parser)?);
1418 stage_params = parse_stage_params(parser)?;
1419
1420 from_stage_alias = parser
1422 .maybe_parse_table_alias()?
1423 .map(|table_alias| table_alias.name);
1424 parser.expect_token(&Token::RParen)?;
1425 }
1426 Token::LParen if kind == CopyIntoSnowflakeKind::Location => {
1427 from_query = Some(parser.parse_query()?);
1429 parser.expect_token(&Token::RParen)?;
1430 }
1431 _ => {
1432 parser.prev_token();
1433 from_stage = Some(parse_snowflake_stage_name(parser)?);
1434 stage_params = parse_stage_params(parser)?;
1435
1436 from_stage_alias = if parser.parse_keyword(Keyword::AS) {
1438 Some(match parser.next_token().token {
1439 Token::Word(w) => Ok(Ident::new(w.value)),
1440 _ => parser.expected_ref("stage alias", parser.peek_token_ref()),
1441 }?)
1442 } else {
1443 None
1444 };
1445 }
1446 }
1447
1448 loop {
1449 if parser.parse_keyword(Keyword::FILE_FORMAT) {
1451 parser.expect_token(&Token::Eq)?;
1452 file_format = parser.parse_key_value_options(true, &[])?.options;
1453 } else if parser.parse_keywords(&[Keyword::PARTITION, Keyword::BY]) {
1455 partition = Some(Box::new(parser.parse_expr()?))
1456 } else if parser.parse_keyword(Keyword::FILES) {
1458 parser.expect_token(&Token::Eq)?;
1459 parser.expect_token(&Token::LParen)?;
1460 let mut continue_loop = true;
1461 while continue_loop {
1462 continue_loop = false;
1463 let next_token = parser.next_token();
1464 match next_token.token {
1465 Token::SingleQuotedString(s) => files.push(s),
1466 _ => parser.expected("file token", next_token)?,
1467 };
1468 if parser.next_token().token.eq(&Token::Comma) {
1469 continue_loop = true;
1470 } else {
1471 parser.prev_token(); }
1473 }
1474 parser.expect_token(&Token::RParen)?;
1475 } else if parser.parse_keyword(Keyword::PATTERN) {
1477 parser.expect_token(&Token::Eq)?;
1478 let next_token = parser.next_token();
1479 pattern = Some(match next_token.token {
1480 Token::SingleQuotedString(s) => s,
1481 _ => parser.expected("pattern", next_token)?,
1482 });
1483 } else if parser.parse_keyword(Keyword::VALIDATION_MODE) {
1485 parser.expect_token(&Token::Eq)?;
1486 validation_mode = Some(parser.next_token().token.to_string());
1487 } else if parser.parse_keyword(Keyword::COPY_OPTIONS) {
1489 parser.expect_token(&Token::Eq)?;
1490 copy_options = parser.parse_key_value_options(true, &[])?.options;
1491 } else {
1492 match parser.next_token().token {
1493 Token::SemiColon | Token::EOF => break,
1494 Token::Comma => continue,
1495 Token::Word(key) => copy_options.push(parser.parse_key_value_option(&key)?),
1498 _ => {
1499 return parser
1500 .expected_ref("another copy option, ; or EOF'", parser.peek_token_ref())
1501 }
1502 }
1503 }
1504 }
1505
1506 Ok(Statement::CopyIntoSnowflake {
1507 kind,
1508 into,
1509 into_columns,
1510 from_obj: from_stage,
1511 from_obj_alias: from_stage_alias,
1512 stage_params,
1513 from_transformations,
1514 from_query,
1515 files: if files.is_empty() { None } else { Some(files) },
1516 pattern,
1517 file_format: KeyValueOptions {
1518 options: file_format,
1519 delimiter: KeyValueOptionsDelimiter::Space,
1520 },
1521 copy_options: KeyValueOptions {
1522 options: copy_options,
1523 delimiter: KeyValueOptionsDelimiter::Space,
1524 },
1525 validation_mode,
1526 partition,
1527 })
1528}
1529
1530fn parse_select_items_for_data_load(
1531 parser: &mut Parser,
1532) -> Result<Option<Vec<StageLoadSelectItemKind>>, ParserError> {
1533 let mut select_items: Vec<StageLoadSelectItemKind> = vec![];
1534 loop {
1535 match parser.maybe_parse(parse_select_item_for_data_load)? {
1536 Some(item) => select_items.push(StageLoadSelectItemKind::StageLoadSelectItem(item)),
1538 None => select_items.push(StageLoadSelectItemKind::SelectItem(
1540 parser.parse_select_item()?,
1541 )),
1542 }
1543 if matches!(parser.peek_token_ref().token, Token::Comma) {
1544 parser.advance_token();
1545 } else {
1546 break;
1547 }
1548 }
1549 Ok(Some(select_items))
1550}
1551
1552fn parse_select_item_for_data_load(
1553 parser: &mut Parser,
1554) -> Result<StageLoadSelectItem, ParserError> {
1555 let mut alias: Option<Ident> = None;
1556 let mut file_col_num: i32 = 0;
1557 let mut element: Option<Ident> = None;
1558 let mut item_as: Option<Ident> = None;
1559
1560 let next_token = parser.next_token();
1561 match next_token.token {
1562 Token::Placeholder(w) => {
1563 file_col_num = w.to_string().split_off(1).parse::<i32>().map_err(|e| {
1564 ParserError::ParserError(format!("Could not parse '{w}' as i32: {e}"))
1565 })?;
1566 Ok(())
1567 }
1568 Token::Word(w) => {
1569 alias = Some(Ident::new(w.value));
1570 Ok(())
1571 }
1572 _ => parser.expected("alias or file_col_num", next_token),
1573 }?;
1574
1575 if alias.is_some() {
1576 parser.expect_token(&Token::Period)?;
1577 let col_num_token = parser.next_token();
1579 match col_num_token.token {
1580 Token::Placeholder(w) => {
1581 file_col_num = w.to_string().split_off(1).parse::<i32>().map_err(|e| {
1582 ParserError::ParserError(format!("Could not parse '{w}' as i32: {e}"))
1583 })?;
1584 Ok(())
1585 }
1586 _ => parser.expected("file_col_num", col_num_token),
1587 }?;
1588 }
1589
1590 match parser.next_token().token {
1592 Token::Colon => {
1593 element = Some(Ident::new(match parser.next_token().token {
1595 Token::Word(w) => Ok(w.value),
1596 _ => parser.expected_ref("file_col_num", parser.peek_token_ref()),
1597 }?));
1598 }
1599 _ => {
1600 parser.prev_token();
1602 }
1603 }
1604
1605 if matches!(parser.peek_token_ref().token, Token::DoubleColon) {
1608 return parser.expected("stage load select item", parser.peek_token());
1609 }
1610
1611 if parser.parse_keyword(Keyword::AS) {
1613 item_as = Some(match parser.next_token().token {
1614 Token::Word(w) => Ok(Ident::new(w.value)),
1615 _ => parser.expected_ref("column item alias", parser.peek_token_ref()),
1616 }?);
1617 }
1618
1619 Ok(StageLoadSelectItem {
1620 alias,
1621 file_col_num,
1622 element,
1623 item_as,
1624 })
1625}
1626
1627fn parse_stage_params(parser: &mut Parser) -> Result<StageParamsObject, ParserError> {
1628 let (mut url, mut storage_integration, mut endpoint) = (None, None, None);
1629 let mut encryption: KeyValueOptions = KeyValueOptions {
1630 options: vec![],
1631 delimiter: KeyValueOptionsDelimiter::Space,
1632 };
1633 let mut credentials: KeyValueOptions = KeyValueOptions {
1634 options: vec![],
1635 delimiter: KeyValueOptionsDelimiter::Space,
1636 };
1637
1638 if parser.parse_keyword(Keyword::URL) {
1640 parser.expect_token(&Token::Eq)?;
1641 url = Some(match parser.next_token().token {
1642 Token::SingleQuotedString(word) => Ok(word),
1643 _ => parser.expected_ref("a URL statement", parser.peek_token_ref()),
1644 }?)
1645 }
1646
1647 if parser.parse_keyword(Keyword::STORAGE_INTEGRATION) {
1649 parser.expect_token(&Token::Eq)?;
1650 storage_integration = Some(parser.next_token().token.to_string());
1651 }
1652
1653 if parser.parse_keyword(Keyword::ENDPOINT) {
1655 parser.expect_token(&Token::Eq)?;
1656 endpoint = Some(match parser.next_token().token {
1657 Token::SingleQuotedString(word) => Ok(word),
1658 _ => parser.expected_ref("an endpoint statement", parser.peek_token_ref()),
1659 }?)
1660 }
1661
1662 if parser.parse_keyword(Keyword::CREDENTIALS) {
1664 parser.expect_token(&Token::Eq)?;
1665 credentials = KeyValueOptions {
1666 options: parser.parse_key_value_options(true, &[])?.options,
1667 delimiter: KeyValueOptionsDelimiter::Space,
1668 };
1669 }
1670
1671 if parser.parse_keyword(Keyword::ENCRYPTION) {
1673 parser.expect_token(&Token::Eq)?;
1674 encryption = KeyValueOptions {
1675 options: parser.parse_key_value_options(true, &[])?.options,
1676 delimiter: KeyValueOptionsDelimiter::Space,
1677 };
1678 }
1679
1680 Ok(StageParamsObject {
1681 url,
1682 encryption,
1683 endpoint,
1684 storage_integration,
1685 credentials,
1686 })
1687}
1688
1689fn parse_session_options(
1694 parser: &mut Parser,
1695 set: bool,
1696) -> Result<Vec<KeyValueOption>, ParserError> {
1697 let mut options: Vec<KeyValueOption> = Vec::new();
1698 let empty = String::new;
1699 loop {
1700 let peeked_token = parser.peek_token();
1701 match peeked_token.token {
1702 Token::SemiColon | Token::EOF => break,
1703 Token::Comma => {
1704 parser.advance_token();
1705 continue;
1706 }
1707 Token::Word(key) => {
1708 parser.advance_token();
1709 if set {
1710 let option = parser.parse_key_value_option(&key)?;
1711 options.push(option);
1712 } else {
1713 options.push(KeyValueOption {
1714 option_name: key.value,
1715 option_value: KeyValueOptionKind::Single(
1716 Value::Placeholder(empty()).with_span(Span {
1717 start: peeked_token.span.end,
1718 end: peeked_token.span.end,
1719 }),
1720 ),
1721 });
1722 }
1723 }
1724 _ => {
1725 return parser.expected("another option or end of statement", peeked_token);
1726 }
1727 }
1728 }
1729 if options.is_empty() {
1730 Err(ParserError::ParserError(
1731 "expected at least one option".to_string(),
1732 ))
1733 } else {
1734 Ok(options)
1735 }
1736}
1737
1738fn parse_identity_property(parser: &mut Parser) -> Result<IdentityProperty, ParserError> {
1745 let parameters = if parser.consume_token(&Token::LParen) {
1746 let seed = parser.parse_number()?;
1747 parser.expect_token(&Token::Comma)?;
1748 let increment = parser.parse_number()?;
1749 parser.expect_token(&Token::RParen)?;
1750
1751 Some(IdentityPropertyFormatKind::FunctionCall(
1752 IdentityParameters { seed, increment },
1753 ))
1754 } else if parser.parse_keyword(Keyword::START) {
1755 let seed = parser.parse_number()?;
1756 parser.expect_keyword_is(Keyword::INCREMENT)?;
1757 let increment = parser.parse_number()?;
1758
1759 Some(IdentityPropertyFormatKind::StartAndIncrement(
1760 IdentityParameters { seed, increment },
1761 ))
1762 } else {
1763 None
1764 };
1765 let order = match parser.parse_one_of_keywords(&[Keyword::ORDER, Keyword::NOORDER]) {
1766 Some(Keyword::ORDER) => Some(IdentityPropertyOrder::Order),
1767 Some(Keyword::NOORDER) => Some(IdentityPropertyOrder::NoOrder),
1768 _ => None,
1769 };
1770 Ok(IdentityProperty { parameters, order })
1771}
1772
1773fn parse_column_policy_property(
1780 parser: &mut Parser,
1781 with: bool,
1782) -> Result<ColumnPolicyProperty, ParserError> {
1783 let policy_name = parser.parse_object_name(false)?;
1784 let using_columns = if parser.parse_keyword(Keyword::USING) {
1785 parser.expect_token(&Token::LParen)?;
1786 let columns = parser.parse_comma_separated(|p| p.parse_identifier())?;
1787 parser.expect_token(&Token::RParen)?;
1788 Some(columns)
1789 } else {
1790 None
1791 };
1792
1793 Ok(ColumnPolicyProperty {
1794 with,
1795 policy_name,
1796 using_columns,
1797 })
1798}
1799
1800fn parse_column_tags(parser: &mut Parser, with: bool) -> Result<TagsColumnOption, ParserError> {
1807 parser.expect_token(&Token::LParen)?;
1808 let tags = parser.parse_comma_separated(Parser::parse_tag)?;
1809 parser.expect_token(&Token::RParen)?;
1810
1811 Ok(TagsColumnOption { with, tags })
1812}
1813
1814fn parse_show_objects(terse: bool, parser: &mut Parser) -> Result<Statement, ParserError> {
1817 let show_options = parser.parse_show_stmt_options()?;
1818 Ok(Statement::ShowObjects(ShowObjects {
1819 terse,
1820 show_options,
1821 }))
1822}
1823
1824fn parse_multi_table_insert(
1843 parser: &mut Parser,
1844 insert_token: TokenWithSpan,
1845 overwrite: bool,
1846 multi_table_insert_type: MultiTableInsertType,
1847) -> Result<Statement, ParserError> {
1848 let is_conditional = parser.peek_keyword(Keyword::WHEN);
1850
1851 let (multi_table_into_clauses, multi_table_when_clauses, multi_table_else_clause) =
1852 if is_conditional {
1853 let (when_clauses, else_clause) = parse_multi_table_insert_when_clauses(parser)?;
1855 (vec![], when_clauses, else_clause)
1856 } else {
1857 let into_clauses = parse_multi_table_insert_into_clauses(parser)?;
1859 (into_clauses, vec![], None)
1860 };
1861
1862 let source = parser.parse_query()?;
1864
1865 Ok(Statement::Insert(Insert {
1866 insert_token: insert_token.into(),
1867 optimizer_hints: vec![],
1868 or: None,
1869 ignore: false,
1870 into: false,
1871 table: TableObject::TableName(ObjectName(vec![])), table_alias: None,
1873 columns: vec![],
1874 overwrite,
1875 source: Some(source),
1876 assignments: vec![],
1877 partitioned: None,
1878 after_columns: vec![],
1879 has_table_keyword: false,
1880 on: None,
1881 returning: None,
1882 output: None,
1883 replace_into: false,
1884 priority: None,
1885 insert_alias: None,
1886 settings: None,
1887 format_clause: None,
1888 multi_table_insert_type: Some(multi_table_insert_type),
1889 multi_table_into_clauses,
1890 multi_table_when_clauses,
1891 multi_table_else_clause,
1892 }))
1893}
1894
1895fn parse_multi_table_insert_into_clauses(
1897 parser: &mut Parser,
1898) -> Result<Vec<MultiTableInsertIntoClause>, ParserError> {
1899 let mut into_clauses = vec![];
1900 while parser.parse_keyword(Keyword::INTO) {
1901 into_clauses.push(parse_multi_table_insert_into_clause(parser)?);
1902 }
1903 if into_clauses.is_empty() {
1904 return parser.expected_ref("INTO clause in multi-table INSERT", parser.peek_token_ref());
1905 }
1906 Ok(into_clauses)
1907}
1908
1909fn parse_multi_table_insert_into_clause(
1913 parser: &mut Parser,
1914) -> Result<MultiTableInsertIntoClause, ParserError> {
1915 let table_name = parser.parse_object_name(false)?;
1916
1917 let columns = parser
1919 .maybe_parse(|p| p.parse_parenthesized_column_list(IsOptional::Mandatory, false))?
1920 .unwrap_or_default();
1921
1922 let values = if parser.parse_keyword(Keyword::VALUES) {
1924 parser.expect_token(&Token::LParen)?;
1925 let values = parser.parse_comma_separated(parse_multi_table_insert_value)?;
1926 parser.expect_token(&Token::RParen)?;
1927 Some(MultiTableInsertValues { values })
1928 } else {
1929 None
1930 };
1931
1932 Ok(MultiTableInsertIntoClause {
1933 table_name,
1934 columns,
1935 values,
1936 })
1937}
1938
1939fn parse_multi_table_insert_value(
1941 parser: &mut Parser,
1942) -> Result<MultiTableInsertValue, ParserError> {
1943 if parser.parse_keyword(Keyword::DEFAULT) {
1944 Ok(MultiTableInsertValue::Default)
1945 } else {
1946 Ok(MultiTableInsertValue::Expr(parser.parse_expr()?))
1947 }
1948}
1949
1950fn parse_multi_table_insert_when_clauses(
1952 parser: &mut Parser,
1953) -> Result<
1954 (
1955 Vec<MultiTableInsertWhenClause>,
1956 Option<Vec<MultiTableInsertIntoClause>>,
1957 ),
1958 ParserError,
1959> {
1960 let mut when_clauses = vec![];
1961 let mut else_clause = None;
1962
1963 while parser.parse_keyword(Keyword::WHEN) {
1965 let condition = parser.parse_expr()?;
1966 parser.expect_keyword(Keyword::THEN)?;
1967
1968 let into_clauses = parse_multi_table_insert_into_clauses(parser)?;
1970
1971 when_clauses.push(MultiTableInsertWhenClause {
1972 condition,
1973 into_clauses,
1974 });
1975 }
1976
1977 if parser.parse_keyword(Keyword::ELSE) {
1979 else_clause = Some(parse_multi_table_insert_into_clauses(parser)?);
1980 }
1981
1982 if when_clauses.is_empty() {
1983 return parser.expected_ref(
1984 "at least one WHEN clause in conditional multi-table INSERT",
1985 parser.peek_token_ref(),
1986 );
1987 }
1988
1989 Ok((when_clauses, else_clause))
1990}