1use std::collections::BTreeMap;
16use std::time::Duration;
17
18use educe::Educe;
19use nom::branch::alt;
20use nom::combinator::consumed;
21use nom::combinator::map;
22use nom::combinator::not;
23use nom::combinator::value;
24use nom::Slice;
25use nom_rule::rule;
26
27use super::sequence::sequence;
28use crate::ast::*;
29use crate::parser::comment::comment;
30use crate::parser::common::*;
31use crate::parser::copy::copy_into;
32use crate::parser::copy::copy_into_table;
33use crate::parser::data_mask::data_mask_policy;
34use crate::parser::dynamic_table::dynamic_table;
35use crate::parser::expr::subexpr;
36use crate::parser::expr::*;
37use crate::parser::input::Input;
38use crate::parser::query::*;
39use crate::parser::stage::*;
40use crate::parser::stream::stream_table;
41use crate::parser::token::*;
42use crate::parser::Error;
43use crate::parser::ErrorKind;
44use crate::span::merge_span;
45
46pub enum ShowGrantOption {
47 PrincipalIdentity(PrincipalIdentity),
48 GrantObjectName(GrantObjectName),
49 OfRole(String),
50}
51
52pub type ShareDatabaseParams = (ShareNameIdent, Identifier);
54
55#[derive(Clone)]
56pub enum CreateDatabaseOption {
57 DatabaseEngine(DatabaseEngine),
58}
59
60pub fn statement_body(i: Input) -> IResult<Statement> {
61 let explain = map_res(
62 rule! {
63 EXPLAIN ~ ( "(" ~ #comma_separated_list1(explain_option) ~ ")" )? ~ ( AST | SYNTAX | PIPELINE | JOIN | GRAPH | FRAGMENTS | RAW | OPTIMIZED | MEMO | DECORRELATED | PERF)? ~ #statement
64 },
65 |(_, options, opt_kind, statement)| {
66 Ok(Statement::Explain {
67 kind: match opt_kind.map(|token| token.kind) {
68 Some(TokenKind::SYNTAX) | Some(TokenKind::AST) => {
69 let pretty_stmt = statement.stmt.to_string();
70 ExplainKind::Syntax(pretty_stmt)
71 }
72 Some(TokenKind::PIPELINE) => ExplainKind::Pipeline,
73 Some(TokenKind::JOIN) => ExplainKind::Join,
74 Some(TokenKind::GRAPH) => ExplainKind::Graph,
75 Some(TokenKind::FRAGMENTS) => ExplainKind::Fragments,
76 Some(TokenKind::RAW) => ExplainKind::Raw,
77 Some(TokenKind::OPTIMIZED) => ExplainKind::Optimized,
78 Some(TokenKind::DECORRELATED) => ExplainKind::Decorrelated,
79 Some(TokenKind::MEMO) => ExplainKind::Memo("".to_string()),
80 Some(TokenKind::GRAPHICAL) => ExplainKind::Graphical,
81 Some(TokenKind::PERF) => ExplainKind::Perf,
82 None => ExplainKind::Plan,
83 _ => unreachable!(),
84 },
85 options: options
86 .map(|(a, opts, b)| (merge_span(Some(a.span), Some(b.span)), opts))
87 .unwrap_or_default(),
88 query: Box::new(statement.stmt),
89 })
90 },
91 );
92
93 let query_setting = map_res(
94 rule! {
95 SETTINGS ~ #query_statement_setting? ~ #statement_body
96 },
97 |(_, opt_settings, statement)| {
98 Ok(Statement::StatementWithSettings {
99 settings: opt_settings,
100 stmt: Box::new(statement),
101 })
102 },
103 );
104 let explain_analyze = map(
105 rule! {
106 EXPLAIN ~ ANALYZE ~ (PARTIAL|GRAPHICAL)? ~ #statement
107 },
108 |(_, _, opt_partial_or_graphical, statement)| {
109 let (partial, graphical) = match opt_partial_or_graphical {
110 Some(Token {
111 kind: TokenKind::PARTIAL,
112 ..
113 }) => (true, false),
114 Some(Token {
115 kind: TokenKind::GRAPHICAL,
116 ..
117 }) => (false, true),
118 _ => (false, false),
119 };
120 Statement::ExplainAnalyze {
121 partial,
122 graphical,
123 query: Box::new(statement.stmt),
124 }
125 },
126 );
127
128 let report = map_res(rule! { REPORT ~ ISSUE ~ #rest_str }, |(_, _, (sql, _))| {
129 Ok(Statement::ReportIssue(sql))
130 });
131
132 let create_task = map_res(
133 rule! {
134 CREATE ~ ( OR ~ ^REPLACE )? ~ TASK ~ ( IF ~ ^NOT ~ ^EXISTS )?
135 ~ #ident
136 ~ #create_task_option*
137 ~ #set_table_option?
138 ~ AS ~ #task_sql_block
139 },
140 |(
141 _,
142 opt_or_replace,
143 _,
144 opt_if_not_exists,
145 task,
146 create_task_opts,
147 session_opts,
148 _,
149 sql,
150 )| {
151 let session_opts = session_opts.unwrap_or_default();
152 let create_option =
153 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
154
155 let mut stmt = CreateTaskStmt {
156 create_option,
157 name: task.to_string(),
158 warehouse: None,
159 schedule_opts: None,
160 suspend_task_after_num_failures: None,
161 comments: None,
162 after: vec![],
163 error_integration: None,
164 when_condition: None,
165 sql,
166 session_parameters: session_opts,
167 };
168 for opt in create_task_opts {
169 stmt.apply_opt(opt);
170 }
171 Ok(Statement::CreateTask(stmt))
172 },
173 );
174
175 let alter_task = map(
176 rule! {
177 ALTER ~ TASK ~ ( IF ~ ^EXISTS )?
178 ~ #ident ~ #alter_task_option
179 },
180 |(_, _, opt_if_exists, task, options)| {
181 Statement::AlterTask(AlterTaskStmt {
182 if_exists: opt_if_exists.is_some(),
183 name: task.to_string(),
184 options,
185 })
186 },
187 );
188
189 let drop_task = map(
190 rule! {
191 DROP ~ TASK ~ ( IF ~ ^EXISTS )?
192 ~ #ident
193 },
194 |(_, _, opt_if_exists, task)| {
195 Statement::DropTask(DropTaskStmt {
196 if_exists: opt_if_exists.is_some(),
197 name: task.to_string(),
198 })
199 },
200 );
201 let show_tasks = map(
202 rule! {
203 SHOW ~ TASKS ~ #show_limit?
204 },
205 |(_, _, limit)| Statement::ShowTasks(ShowTasksStmt { limit }),
206 );
207
208 let execute_task = map(
209 rule! {
210 EXECUTE ~ TASK ~ #ident
211 },
212 |(_, _, task)| {
213 Statement::ExecuteTask(ExecuteTaskStmt {
214 name: task.to_string(),
215 })
216 },
217 );
218
219 let desc_task = map(
220 rule! {
221 ( DESC | DESCRIBE ) ~ TASK ~ #ident
222 },
223 |(_, _, task)| {
224 Statement::DescribeTask(DescribeTaskStmt {
225 name: task.to_string(),
226 })
227 },
228 );
229
230 let merge = map(
231 rule! {
232 MERGE ~ #hint?
233 ~ INTO ~ #dot_separated_idents_1_to_3 ~ #table_alias?
234 ~ USING ~ #mutation_source
235 ~ ON ~ #expr ~ (#match_clause | #unmatch_clause)*
236 },
237 |(
238 _,
239 opt_hints,
240 _,
241 (catalog, database, table),
242 target_alias,
243 _,
244 source,
245 _,
246 join_expr,
247 merge_options,
248 )| {
249 Statement::MergeInto(MergeIntoStmt {
250 hints: opt_hints,
251 catalog,
252 database,
253 table_ident: table,
254 source,
255 target_alias,
256 join_expr,
257 merge_options,
258 })
259 },
260 );
261
262 let delete = map(
263 rule! {
264 #with? ~ DELETE ~ #hint? ~ FROM ~ #table_reference_with_alias ~ ( WHERE ~ ^#expr )?
265 },
266 |(with, _, hints, _, table, opt_selection)| {
267 Statement::Delete(DeleteStmt {
268 hints,
269 table,
270 selection: opt_selection.map(|(_, selection)| selection),
271 with,
272 })
273 },
274 );
275
276 let update = map(
277 rule! {
278 #with? ~ UPDATE ~ #hint? ~ #dot_separated_idents_1_to_3 ~ #table_alias?
279 ~ SET ~ ^#comma_separated_list1(mutation_update_expr)
280 ~ ( FROM ~ #mutation_source )?
281 ~ ( WHERE ~ ^#expr )?
282 },
283 |(
284 with,
285 _,
286 hints,
287 (catalog, database, table),
288 table_alias,
289 _,
290 update_list,
291 from,
292 opt_selection,
293 )| {
294 Statement::Update(UpdateStmt {
295 hints,
296 catalog,
297 database,
298 table,
299 table_alias,
300 update_list,
301 from: from.map(|(_, table)| table),
302 selection: opt_selection.map(|(_, selection)| selection),
303 with,
304 })
305 },
306 );
307
308 let show_settings = map(
309 rule! {
310 SHOW ~ SETTINGS ~ #show_options?
311 },
312 |(_, _, show_options)| Statement::ShowSettings { show_options },
313 );
314 let show_variables = map(
315 rule! {
316 SHOW ~ VARIABLES ~ #show_options?
317 },
318 |(_, _, show_options)| Statement::ShowVariables { show_options },
319 );
320 let show_stages = map(
321 rule! {
322 SHOW ~ STAGES ~ #show_options?
323 },
324 |(_, _, show_options)| Statement::ShowStages { show_options },
325 );
326 let show_process_list = map(
327 rule! {
328 SHOW ~ PROCESSLIST ~ #show_options?
329 },
330 |(_, _, show_options)| Statement::ShowProcessList { show_options },
331 );
332 let show_metrics = map(
333 rule! {
334 SHOW ~ METRICS ~ #show_options?
335 },
336 |(_, _, show_options)| Statement::ShowMetrics { show_options },
337 );
338 let show_engines = map(
339 rule! {
340 SHOW ~ ENGINES ~ #show_options?
341 },
342 |(_, _, show_options)| Statement::ShowEngines { show_options },
343 );
344 let show_functions = map(
345 rule! {
346 SHOW ~ FUNCTIONS ~ #show_options?
347 },
348 |(_, _, show_options)| Statement::ShowFunctions { show_options },
349 );
350 let show_user_functions = map(
351 rule! {
352 SHOW ~ USER ~ FUNCTIONS ~ #show_options?
353 },
354 |(_, _, _, show_options)| Statement::ShowUserFunctions { show_options },
355 );
356 let show_table_functions = map(
357 rule! {
358 SHOW ~ TABLE_FUNCTIONS ~ #show_options?
359 },
360 |(_, _, show_options)| Statement::ShowTableFunctions { show_options },
361 );
362 let show_indexes = map(
363 rule! {
364 SHOW ~ INDEXES ~ #show_options?
365 },
366 |(_, _, show_options)| Statement::ShowIndexes { show_options },
367 );
368 let show_locks = map(
369 rule! {
370 SHOW ~ LOCKS ~ ( IN ~ ^ACCOUNT )? ~ #limit_where?
371 },
372 |(_, _, opt_in_account, limit)| {
373 Statement::ShowLocks(ShowLocksStmt {
374 in_account: opt_in_account.is_some(),
375 limit,
376 })
377 },
378 );
379
380 let kill_stmt = map(
382 rule! {
383 KILL ~ #kill_target ~ #parameter_to_string
384 },
385 |(_, kill_target, object_id)| Statement::KillStmt {
386 kill_target,
387 object_id,
388 },
389 );
390
391 let set_priority = map(
392 rule! {
393 SET ~ PRIORITY ~ #priority ~ #parameter_to_string
394 },
395 |(_, _, priority, object_id)| Statement::SetPriority {
396 object_id,
397 priority,
398 },
399 );
400
401 let unset_stmt = map(
402 rule! {
403 UNSET ~ #set_type ~ #unset_source
404 },
405 |(_, unset_type, identifiers)| Statement::UnSetStmt {
406 settings: Settings {
407 set_type: unset_type,
408 identifiers,
409 values: SetValues::None,
410 },
411 },
412 );
413
414 let set_role = map(
415 rule! {
416 SET ~ DEFAULT? ~ ROLE ~ #role_name
417 },
418 |(_, opt_is_default, _, role_name)| Statement::SetRole {
419 is_default: opt_is_default.is_some(),
420 role_name,
421 },
422 );
423
424 let set_secondary_roles = map(
425 rule! {
426 SET ~ SECONDARY ~ ROLES ~ (ALL | NONE)
427 },
428 |(_, _, _, token)| {
429 let option = match token.kind {
430 TokenKind::ALL => SecondaryRolesOption::All,
431 TokenKind::NONE => SecondaryRolesOption::None,
432 _ => unreachable!(),
433 };
434 Statement::SetSecondaryRoles { option }
435 },
436 );
437
438 let set_secondary_specify_roles = map(
439 rule! {
440 SET ~ SECONDARY ~ ROLES ~ #comma_separated_list1(role_name)
441 },
442 |(_, _, _, roles)| Statement::SetSecondaryRoles {
443 option: SecondaryRolesOption::SpecifyRole(roles),
444 },
445 );
446
447 let set_stmt = alt((
448 map(
449 rule! {
450 SET ~ #set_type ~ #ident ~ "=" ~ #subexpr(0)
451 },
452 |(_, set_type, var, _, value)| Statement::SetStmt {
453 settings: Settings {
454 set_type,
455 identifiers: vec![var],
456 values: SetValues::Expr(vec![Box::new(value)]),
457 },
458 },
459 ),
460 map_res(
461 rule! {
462 SET ~ #set_type ~ "(" ~ #comma_separated_list0(ident) ~ ")" ~ "="
463 ~ "(" ~ #comma_separated_list0(subexpr(0)) ~ ")"
464 },
465 |(_, set_type, _, ids, _, _, _, values, _)| {
466 if ids.len() == values.len() {
467 Ok(Statement::SetStmt {
468 settings: Settings {
469 set_type,
470 identifiers: ids,
471 values: SetValues::Expr(values.into_iter().map(|x| x.into()).collect()),
472 },
473 })
474 } else {
475 Err(nom::Err::Failure(ErrorKind::Other(
476 "inconsistent number of variables and values",
477 )))
478 }
479 },
480 ),
481 map(
482 rule! {
483 SET ~ #set_type ~ #ident ~ "=" ~ #query
484 },
485 |(_, set_type, var, _, query)| Statement::SetStmt {
486 settings: Settings {
487 set_type,
488 identifiers: vec![var],
489 values: SetValues::Query(Box::new(query)),
490 },
491 },
492 ),
493 map(
494 rule! {
495 SET ~ #set_type ~ "(" ~ #comma_separated_list0(ident) ~ ")" ~ "=" ~ #query
496 },
497 |(_, set_type, _, vars, _, _, query)| Statement::SetStmt {
498 settings: Settings {
499 set_type,
500 identifiers: vars,
501 values: SetValues::Query(Box::new(query)),
502 },
503 },
504 ),
505 ));
506
507 let show_catalogs = map(
509 rule! {
510 SHOW ~ CATALOGS ~ #show_limit?
511 },
512 |(_, _, limit)| Statement::ShowCatalogs(ShowCatalogsStmt { limit }),
513 );
514 let show_create_catalog = map(
515 rule! {
516 SHOW ~ CREATE ~ CATALOG ~ #ident
517 },
518 |(_, _, _, catalog)| Statement::ShowCreateCatalog(ShowCreateCatalogStmt { catalog }),
519 );
520 let create_catalog = map(
523 rule! {
524 CREATE ~ CATALOG ~ ( IF ~ ^NOT ~ ^EXISTS )?
525 ~ #ident
526 ~ TYPE ~ "=" ~ #catalog_type
527 ~ CONNECTION ~ "=" ~ #connection_options
528 },
529 |(_, _, opt_if_not_exists, catalog, _, _, ty, _, _, options)| {
530 Statement::CreateCatalog(CreateCatalogStmt {
531 if_not_exists: opt_if_not_exists.is_some(),
532 catalog_name: catalog.to_string(),
533 catalog_type: ty,
534 catalog_options: options,
535 })
536 },
537 );
538 let drop_catalog = map(
539 rule! {
540 DROP ~ CATALOG ~ ( IF ~ ^EXISTS )? ~ #ident
541 },
542 |(_, _, opt_if_exists, catalog)| {
543 Statement::DropCatalog(DropCatalogStmt {
544 if_exists: opt_if_exists.is_some(),
545 catalog,
546 })
547 },
548 );
549 let use_catalog = map(
550 rule! {
551 (SET | USE)? ~ CATALOG ~ #ident
552 },
553 |(_, _, catalog)| Statement::UseCatalog { catalog },
554 );
555
556 let show_online_nodes = map(
557 rule! {
558 SHOW ~ ONLINE ~ NODES
559 },
560 |(_, _, _)| Statement::ShowOnlineNodes(ShowOnlineNodesStmt {}),
561 );
562
563 let show_warehouses = map(
564 rule! {
565 SHOW ~ WAREHOUSES
566 },
567 |(_, _)| Statement::ShowWarehouses(ShowWarehousesStmt {}),
568 );
569
570 let use_warehouse = map(
571 rule! {
572 USE ~ WAREHOUSE ~ #ident
573 },
574 |(_, _, warehouse)| Statement::UseWarehouse(UseWarehouseStmt { warehouse }),
575 );
576
577 let create_warehouse = map(
578 rule! {
579 CREATE ~ WAREHOUSE ~ #ident ~ ("(" ~ #assign_nodes_list ~ ")")? ~ (WITH ~ #warehouse_cluster_option)?
580 },
581 |(_, _, warehouse, nodes, options)| {
582 Statement::CreateWarehouse(CreateWarehouseStmt {
583 warehouse,
584 node_list: nodes.map(|(_, nodes, _)| nodes).unwrap_or_else(Vec::new),
585 options: options.map(|(_, x)| x).unwrap_or_else(BTreeMap::new),
586 })
587 },
588 );
589
590 let drop_warehouse = map(
591 rule! {
592 DROP ~ WAREHOUSE ~ #ident
593 },
594 |(_, _, warehouse)| Statement::DropWarehouse(DropWarehouseStmt { warehouse }),
595 );
596
597 let rename_warehouse = map(
598 rule! {
599 RENAME ~ WAREHOUSE ~ #ident ~ TO ~ #ident
600 },
601 |(_, _, warehouse, _, new_warehouse)| {
602 Statement::RenameWarehouse(RenameWarehouseStmt {
603 warehouse,
604 new_warehouse,
605 })
606 },
607 );
608
609 let resume_warehouse = map(
610 rule! {
611 RESUME ~ WAREHOUSE ~ #ident
612 },
613 |(_, _, warehouse)| Statement::ResumeWarehouse(ResumeWarehouseStmt { warehouse }),
614 );
615
616 let suspend_warehouse = map(
617 rule! {
618 SUSPEND ~ WAREHOUSE ~ #ident
619 },
620 |(_, _, warehouse)| Statement::SuspendWarehouse(SuspendWarehouseStmt { warehouse }),
621 );
622
623 let inspect_warehouse = map(
624 rule! {
625 INSPECT ~ WAREHOUSE ~ #ident
626 },
627 |(_, _, warehouse)| Statement::InspectWarehouse(InspectWarehouseStmt { warehouse }),
628 );
629
630 let add_warehouse_cluster = map(
631 rule! {
632 ALTER ~ WAREHOUSE ~ #ident ~ ADD ~ CLUSTER ~ #ident ~ ("(" ~ #assign_nodes_list ~ ")")? ~ (WITH ~ #warehouse_cluster_option)?
633 },
634 |(_, _, warehouse, _, _, cluster, nodes, options)| {
635 Statement::AddWarehouseCluster(AddWarehouseClusterStmt {
636 warehouse,
637 cluster,
638 node_list: nodes.map(|(_, nodes, _)| nodes).unwrap_or_else(Vec::new),
639 options: options.map(|(_, x)| x).unwrap_or_else(BTreeMap::new),
640 })
641 },
642 );
643
644 let drop_warehouse_cluster = map(
645 rule! {
646 ALTER ~ WAREHOUSE ~ #ident ~ DROP ~ CLUSTER ~ #ident
647 },
648 |(_, _, warehouse, _, _, cluster)| {
649 Statement::DropWarehouseCluster(DropWarehouseClusterStmt { warehouse, cluster })
650 },
651 );
652
653 let rename_warehouse_cluster = map(
654 rule! {
655 ALTER ~ WAREHOUSE ~ #ident ~ RENAME ~ CLUSTER ~ #ident ~ TO ~ #ident
656 },
657 |(_, _, warehouse, _, _, cluster, _, new_cluster)| {
658 Statement::RenameWarehouseCluster(RenameWarehouseClusterStmt {
659 warehouse,
660 cluster,
661 new_cluster,
662 })
663 },
664 );
665
666 let assign_warehouse_nodes = map(
667 rule! {
668 ALTER ~ WAREHOUSE ~ #ident ~ ASSIGN ~ NODES ~ "(" ~ #assign_warehouse_nodes_list ~ ")"
669 },
670 |(_, _, warehouse, _, _, _, nodes, _)| {
671 Statement::AssignWarehouseNodes(AssignWarehouseNodesStmt {
672 warehouse,
673 node_list: nodes,
674 })
675 },
676 );
677
678 let unassign_warehouse_nodes = map(
679 rule! {
680 ALTER ~ WAREHOUSE ~ #ident ~ UNASSIGN ~ NODES ~ "(" ~ #unassign_warehouse_nodes_list ~ ")"
681 },
682 |(_, _, warehouse, _, _, _, nodes, _)| {
683 Statement::UnassignWarehouseNodes(UnassignWarehouseNodesStmt {
684 warehouse,
685 node_list: nodes,
686 })
687 },
688 );
689
690 let show_workload_groups = map(
691 rule! {
692 SHOW ~ WORKLOAD ~ GROUPS
693 },
694 |(_, _, _)| Statement::ShowWorkloadGroups(ShowWorkloadGroupsStmt {}),
695 );
696
697 let create_workload_group = map(
698 rule! {
699 CREATE ~ WORKLOAD ~ GROUP ~ ( IF ~ ^NOT ~ ^EXISTS )? ~ #ident ~ WITH ~ #workload_quotas
700 },
701 |(_, _, _, if_not_exists, name, _, quotas)| {
702 Statement::CreateWorkloadGroup(CreateWorkloadGroupStmt {
703 name,
704 quotas,
705 if_not_exists: if_not_exists.is_some(),
706 })
707 },
708 );
709
710 let drop_workload_group = map(
711 rule! {
712 DROP ~ WORKLOAD ~ GROUP ~ ( IF ~ ^EXISTS )? ~ #ident
713 },
714 |(_, _, _, if_exists, name)| {
715 Statement::DropWorkloadGroup(DropWorkloadGroupStmt {
716 name,
717 if_exists: if_exists.is_some(),
718 })
719 },
720 );
721
722 let rename_workload_group = map(
723 rule! {
724 RENAME ~ WORKLOAD ~ GROUP ~ #ident ~ TO ~ #ident
725 },
726 |(_, _, _, name, _, new_name)| {
727 Statement::RenameWorkloadGroup(RenameWorkloadGroupStmt { name, new_name })
728 },
729 );
730
731 let set_workload_group_quotas = map(
732 rule! {
733 ALTER ~ WORKLOAD ~ GROUP ~ #ident ~ SET ~ #workload_quotas
734 },
735 |(_, _, _, name, _, quotas)| {
736 Statement::SetWorkloadQuotasGroup(SetWorkloadGroupQuotasStmt { name, quotas })
737 },
738 );
739
740 let unset_workload_group_quotas = map(
741 rule! {
742 ALTER ~ WORKLOAD ~ GROUP ~ #ident ~ UNSET ~ #unset_source
743 },
744 |(_, _, _, name, _, quotas)| {
745 Statement::UnsetWorkloadQuotasGroup(UnsetWorkloadGroupQuotasStmt { name, quotas })
746 },
747 );
748
749 let show_databases = map(
750 rule! {
751 SHOW ~ FULL? ~ ( DATABASES | SCHEMAS ) ~ ( ( FROM | IN ) ~ ^#ident )? ~ #show_limit?
752 },
753 |(_, opt_full, _, opt_catalog, limit)| {
754 Statement::ShowDatabases(ShowDatabasesStmt {
755 catalog: opt_catalog.map(|(_, catalog)| catalog),
756 full: opt_full.is_some(),
757 limit,
758 })
759 },
760 );
761
762 let show_drop_databases = map(
763 rule! {
764 SHOW ~ DROP ~ ( DATABASES | DATABASES ) ~ ( FROM ~ ^#ident )? ~ #show_limit?
765 },
766 |(_, _, _, opt_catalog, limit)| {
767 Statement::ShowDropDatabases(ShowDropDatabasesStmt {
768 catalog: opt_catalog.map(|(_, catalog)| catalog),
769 limit,
770 })
771 },
772 );
773
774 let show_create_database = map(
775 rule! {
776 SHOW ~ CREATE ~ ( DATABASE | SCHEMA ) ~ #dot_separated_idents_1_to_2
777 },
778 |(_, _, _, (catalog, database))| {
779 Statement::ShowCreateDatabase(ShowCreateDatabaseStmt { catalog, database })
780 },
781 );
782
783 let create_database = map_res(
784 rule! {
785 CREATE
786 ~ ( OR ~ ^REPLACE )?
787 ~ ( DATABASE | SCHEMA )
788 ~ ( IF ~ ^NOT ~ ^EXISTS )?
789 ~ #database_ref
790 ~ #create_database_option?
791 },
792 |(_, opt_or_replace, _, opt_if_not_exists, database, create_database_option)| {
793 let create_option =
794 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
795
796 let statement = match create_database_option {
797 Some(CreateDatabaseOption::DatabaseEngine(engine)) => {
798 Statement::CreateDatabase(CreateDatabaseStmt {
799 create_option,
800 database,
801 engine: Some(engine),
802 options: vec![],
803 })
804 }
805 None => Statement::CreateDatabase(CreateDatabaseStmt {
806 create_option,
807 database,
808 engine: None,
809 options: vec![],
810 }),
811 };
812
813 Ok(statement)
814 },
815 );
816
817 let drop_database = map(
818 rule! {
819 DROP ~ ( DATABASE | SCHEMA ) ~ ( IF ~ ^EXISTS )? ~ #dot_separated_idents_1_to_2
820 },
821 |(_, _, opt_if_exists, (catalog, database))| {
822 Statement::DropDatabase(DropDatabaseStmt {
823 if_exists: opt_if_exists.is_some(),
824 catalog,
825 database,
826 })
827 },
828 );
829
830 let undrop_database = map(
831 rule! {
832 UNDROP ~ DATABASE ~ #dot_separated_idents_1_to_2
833 },
834 |(_, _, (catalog, database))| {
835 Statement::UndropDatabase(UndropDatabaseStmt { catalog, database })
836 },
837 );
838
839 let alter_database = map(
840 rule! {
841 ALTER ~ DATABASE ~ ( IF ~ ^EXISTS )? ~ #dot_separated_idents_1_to_2 ~ #alter_database_action
842 },
843 |(_, _, opt_if_exists, (catalog, database), action)| {
844 Statement::AlterDatabase(AlterDatabaseStmt {
845 if_exists: opt_if_exists.is_some(),
846 catalog,
847 database,
848 action,
849 })
850 },
851 );
852 let use_database = map(
853 rule! {
854 USE ~ #ident
855 },
856 |(_, database)| Statement::UseDatabase { database },
857 );
858 let show_tables = map(
859 rule! {
860 SHOW ~ FULL? ~ TABLES ~ HISTORY? ~ ( ( FROM | IN ) ~ #dot_separated_idents_1_to_2 )? ~ #show_limit?
861 },
862 |(_, opt_full, _, opt_history, ctl_db, limit)| {
863 let (catalog, database) = match ctl_db {
864 Some((_, (Some(c), d))) => (Some(c), Some(d)),
865 Some((_, (None, d))) => (None, Some(d)),
866 _ => (None, None),
867 };
868 Statement::ShowTables(ShowTablesStmt {
869 catalog,
870 database,
871 full: opt_full.is_some(),
872 limit,
873 with_history: opt_history.is_some(),
874 })
875 },
876 );
877
878 pub fn from_tables(i: Input) -> IResult<(Option<Identifier>, Option<Identifier>, Identifier)> {
879 let from_dot_table = map(
880 rule! {
881 ( FROM | IN ) ~ ^#dot_separated_idents_1_to_3
882 },
883 |(_, (catalog, database, table))| (catalog, database, table),
884 );
885
886 let from_table = map(
887 rule! {
888 ( FROM | IN ) ~ #ident
889 ~ ( FROM | IN ) ~ ^#dot_separated_idents_1_to_2
890 },
891 |(_, table, _, (catalog, database))| (catalog, Some(database), table),
892 );
893
894 rule!(
895 #from_table
896 | #from_dot_table
897 )(i)
898 }
899
900 let show_columns = map(
901 rule! {
902 SHOW
903 ~ FULL? ~ COLUMNS
904 ~ #from_tables
905 ~ #show_limit?
906 },
907 |(_, opt_full, _, (catalog, database, table), limit)| {
908 Statement::ShowColumns(ShowColumnsStmt {
909 catalog,
910 database,
911 table,
912 full: opt_full.is_some(),
913 limit,
914 })
915 },
916 );
917 let show_create_table = map(
918 rule! {
919 SHOW ~ CREATE ~ TABLE ~ #dot_separated_idents_1_to_3 ~ ( WITH ~ ^QUOTED_IDENTIFIERS )?
920 },
921 |(_, _, _, (catalog, database, table), comment_opt)| {
922 Statement::ShowCreateTable(ShowCreateTableStmt {
923 catalog,
924 database,
925 table,
926 with_quoted_ident: comment_opt.is_some(),
927 })
928 },
929 );
930 let describe_table = map(
931 rule! {
932 ( DESC | DESCRIBE ) ~ TABLE? ~ #dot_separated_idents_1_to_3
933 },
934 |(_, _, (catalog, database, table))| {
935 Statement::DescribeTable(DescribeTableStmt {
936 catalog,
937 database,
938 table,
939 })
940 },
941 );
942
943 let show_fields = map(
945 rule! {
946 SHOW ~ FIELDS ~ FROM ~ #dot_separated_idents_1_to_3
947 },
948 |(_, _, _, (catalog, database, table))| {
949 Statement::DescribeTable(DescribeTableStmt {
950 catalog,
951 database,
952 table,
953 })
954 },
955 );
956
957 let show_tables_status = map(
958 rule! {
959 SHOW ~ ( TABLES | TABLE ) ~ STATUS ~ ( FROM ~ ^#ident )? ~ #show_limit?
960 },
961 |(_, _, _, opt_database, limit)| {
962 Statement::ShowTablesStatus(ShowTablesStatusStmt {
963 database: opt_database.map(|(_, database)| database),
964 limit,
965 })
966 },
967 );
968 let show_drop_tables_status = map(
969 rule! {
970 SHOW ~ DROP ~ ( TABLES | TABLE ) ~ ( FROM ~ ^#ident )? ~ #show_limit?
971 },
972 |(_, _, _, opt_database, limit)| {
973 Statement::ShowDropTables(ShowDropTablesStmt {
974 database: opt_database.map(|(_, database)| database),
975 limit,
976 })
977 },
978 );
979
980 let attach_table = map(
981 rule! {
982 ATTACH ~ TABLE ~ #dot_separated_idents_1_to_3 ~ ("(" ~ #comma_separated_list1(ident) ~ ")")? ~ #uri_location
983 },
984 |(_, _, (catalog, database, table), columns_opt, uri_location)| {
985 let columns_opt = columns_opt.map(|(_, v, _)| v);
986 Statement::AttachTable(AttachTableStmt {
987 catalog,
988 database,
989 table,
990 columns_opt,
991 uri_location,
992 })
993 },
994 );
995 let create_table = map_res(
996 rule! {
997 CREATE ~ ( OR ~ ^REPLACE )? ~ (TEMP| TEMPORARY|TRANSIENT)? ~ TABLE ~ ( IF ~ ^NOT ~ ^EXISTS )?
998 ~ #dot_separated_idents_1_to_3
999 ~ #create_table_source?
1000 ~ ( #engine )?
1001 ~ ( #uri_location )?
1002 ~ ( CLUSTER ~ ^BY ~ ( #cluster_type )? ~ ^"(" ~ ^#comma_separated_list1(expr) ~ ^")" )?
1003 ~ ( #table_option )?
1004 ~ ( PARTITION ~ ^BY ~ ^"(" ~ ^#comma_separated_list1(ident) ~ ^")" )?
1005 ~ ( PROPERTIES ~ #connection_options )?
1006 ~ ( AS ~ ^#query )?
1007 },
1008 |(
1009 _,
1010 opt_or_replace,
1011 opt_type,
1012 _,
1013 opt_if_not_exists,
1014 (catalog, database, table),
1015 source,
1016 engine,
1017 uri_location,
1018 opt_cluster_by,
1019 opt_table_options,
1020 opt_iceberg_table_partition_by,
1021 opt_table_properties,
1022 opt_as_query,
1023 )| {
1024 let create_option =
1025 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
1026 let table_type = match opt_type.map(|t| t.kind) {
1027 None => TableType::Normal,
1028 Some(TRANSIENT) => TableType::Transient,
1029 Some(TEMP) | Some(TEMPORARY) => TableType::Temporary,
1030 _ => unreachable!(),
1031 };
1032 Ok(Statement::CreateTable(CreateTableStmt {
1033 create_option,
1034 catalog,
1035 database,
1036 table,
1037 source,
1038 engine,
1039 uri_location,
1040 cluster_by: opt_cluster_by.map(|(_, _, typ, _, exprs, _)| ClusterOption {
1041 cluster_type: typ.unwrap_or(ClusterType::Linear),
1042 cluster_exprs: exprs,
1043 }),
1044 table_options: opt_table_options.unwrap_or_default(),
1045 iceberg_table_partition: opt_iceberg_table_partition_by
1046 .map(|(_, _, _, cols, _)| cols),
1047 table_properties: opt_table_properties.map(|(_, properties)| properties),
1048 as_query: opt_as_query.map(|(_, query)| Box::new(query)),
1049 table_type,
1050 }))
1051 },
1052 );
1053 let drop_table = map(
1054 rule! {
1055 DROP ~ TABLE ~ ( IF ~ ^EXISTS )? ~ #dot_separated_idents_1_to_3 ~ ALL?
1056 },
1057 |(_, _, opt_if_exists, (catalog, database, table), opt_all)| {
1058 Statement::DropTable(DropTableStmt {
1059 if_exists: opt_if_exists.is_some(),
1060 catalog,
1061 database,
1062 table,
1063 all: opt_all.is_some(),
1064 })
1065 },
1066 );
1067 let undrop_table = map(
1068 rule! {
1069 UNDROP ~ TABLE ~ #dot_separated_idents_1_to_3
1070 },
1071 |(_, _, (catalog, database, table))| {
1072 Statement::UndropTable(UndropTableStmt {
1073 catalog,
1074 database,
1075 table,
1076 })
1077 },
1078 );
1079 let alter_table = map(
1080 rule! {
1081 ALTER ~ TABLE ~ ( IF ~ ^EXISTS )? ~ #table_reference_only ~ #alter_table_action
1082 },
1083 |(_, _, opt_if_exists, table_reference, action)| {
1084 Statement::AlterTable(AlterTableStmt {
1085 if_exists: opt_if_exists.is_some(),
1086 table_reference,
1087 action,
1088 })
1089 },
1090 );
1091 let rename_table = map(
1092 rule! {
1093 RENAME ~ TABLE ~ ( IF ~ ^EXISTS )? ~ #dot_separated_idents_1_to_3 ~ TO ~ #dot_separated_idents_1_to_3
1094 },
1095 |(
1096 _,
1097 _,
1098 opt_if_exists,
1099 (catalog, database, table),
1100 _,
1101 (new_catalog, new_database, new_table),
1102 )| {
1103 Statement::RenameTable(RenameTableStmt {
1104 if_exists: opt_if_exists.is_some(),
1105 catalog,
1106 database,
1107 table,
1108 new_catalog,
1109 new_database,
1110 new_table,
1111 })
1112 },
1113 );
1114 let truncate_table = map(
1115 rule! {
1116 TRUNCATE ~ TABLE ~ #dot_separated_idents_1_to_3
1117 },
1118 |(_, _, (catalog, database, table))| {
1119 Statement::TruncateTable(TruncateTableStmt {
1120 catalog,
1121 database,
1122 table,
1123 })
1124 },
1125 );
1126 let optimize_table = map(
1127 rule! {
1128 OPTIMIZE ~ TABLE ~ #dot_separated_idents_1_to_3 ~ #optimize_table_action ~ ( LIMIT ~ #literal_u64 )?
1129 },
1130 |(_, _, (catalog, database, table), action, opt_limit)| {
1131 Statement::OptimizeTable(OptimizeTableStmt {
1132 catalog,
1133 database,
1134 table,
1135 action,
1136 limit: opt_limit.map(|(_, limit)| limit),
1137 })
1138 },
1139 );
1140 let vacuum_temp_files = map(
1141 rule! {
1142 VACUUM ~ TEMPORARY ~ FILES ~ (RETAIN ~ #literal_duration)? ~ (LIMIT ~ #literal_u64)?
1143 },
1144 |(_, _, _, retain, opt_limit)| {
1145 Statement::VacuumTemporaryFiles(VacuumTemporaryFiles {
1146 limit: opt_limit.map(|(_, limit)| limit),
1147 retain: retain.map(|(_, reatin)| reatin),
1148 })
1149 },
1150 );
1151 let vacuum_table = map(
1152 rule! {
1153 VACUUM ~ TABLE ~ #dot_separated_idents_1_to_3 ~ #vacuum_table_option
1154 },
1155 |(_, _, (catalog, database, table), option)| {
1156 Statement::VacuumTable(VacuumTableStmt {
1157 catalog,
1158 database,
1159 table,
1160 option,
1161 })
1162 },
1163 );
1164 let vacuum_drop_table = map(
1165 rule! {
1166 VACUUM ~ DROP ~ TABLE ~ (FROM ~ ^#dot_separated_idents_1_to_2)? ~ #vacuum_drop_table_option
1167 },
1168 |(_, _, _, database_option, option)| {
1169 let (catalog, database) = database_option.map_or_else(
1170 || (None, None),
1171 |(_, catalog_database)| (catalog_database.0, Some(catalog_database.1)),
1172 );
1173 Statement::VacuumDropTable(VacuumDropTableStmt {
1174 catalog,
1175 database,
1176 option,
1177 })
1178 },
1179 );
1180 let analyze_table = map(
1181 rule! {
1182 ANALYZE ~ TABLE ~ #dot_separated_idents_1_to_3 ~ NOSCAN?
1183 },
1184 |(_, _, (catalog, database, table), no_scan)| {
1185 Statement::AnalyzeTable(AnalyzeTableStmt {
1186 catalog,
1187 database,
1188 table,
1189 no_scan: no_scan.is_some(),
1190 })
1191 },
1192 );
1193 let exists_table = map(
1194 rule! {
1195 EXISTS ~ TABLE ~ #dot_separated_idents_1_to_3
1196 },
1197 |(_, _, (catalog, database, table))| {
1198 Statement::ExistsTable(ExistsTableStmt {
1199 catalog,
1200 database,
1201 table,
1202 })
1203 },
1204 );
1205
1206 let create_dictionary = map_res(
1208 rule! {
1209 CREATE ~ ( OR ~ ^REPLACE )? ~ DICTIONARY ~ ( IF ~ ^NOT ~ ^EXISTS )?
1210 ~ #dot_separated_idents_1_to_3
1211 ~ "(" ~ ^#comma_separated_list1(column_def) ~ ^")"
1212 ~ PRIMARY ~ ^KEY ~ ^#comma_separated_list1(ident)
1213 ~ ^SOURCE ~ ^"(" ~ ^#ident ~ ^"("
1214 ~ ( #table_option )?
1215 ~ ^")" ~ ^")"
1216 ~ ( COMMENT ~ ^#literal_string )?
1217 },
1218 |(
1219 _,
1220 opt_or_replace,
1221 _,
1222 opt_if_not_exists,
1223 (catalog, database, dictionary_name),
1224 _,
1225 columns,
1226 _,
1227 _,
1228 _,
1229 primary_keys,
1230 _,
1231 _,
1232 source_name,
1233 _,
1234 opt_source_options,
1235 _,
1236 _,
1237 opt_comment,
1238 )| {
1239 let create_option =
1240 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
1241 Ok(Statement::CreateDictionary(CreateDictionaryStmt {
1242 create_option,
1243 catalog,
1244 database,
1245 dictionary_name,
1246 columns,
1247 primary_keys,
1248 source_name,
1249 source_options: opt_source_options.unwrap_or_default(),
1250 comment: opt_comment.map(|(_, comment)| comment),
1251 }))
1252 },
1253 );
1254 let drop_dictionary = map(
1255 rule! {
1256 DROP ~ DICTIONARY ~ ( IF ~ ^EXISTS )? ~ #dot_separated_idents_1_to_3
1257 },
1258 |(_, _, opt_if_exists, (catalog, database, dictionary_name))| {
1259 Statement::DropDictionary(DropDictionaryStmt {
1260 if_exists: opt_if_exists.is_some(),
1261 catalog,
1262 database,
1263 dictionary_name,
1264 })
1265 },
1266 );
1267 let show_dictionaries = map(
1268 rule! {
1269 SHOW ~ DICTIONARIES ~ ((FROM|IN) ~ #ident)? ~ #show_limit?
1270 },
1271 |(_, _, db, limit)| {
1272 let database = match db {
1273 Some((_, d)) => Some(d),
1274 _ => None,
1275 };
1276 Statement::ShowDictionaries(ShowDictionariesStmt { database, limit })
1277 },
1278 );
1279 let show_create_dictionary = map(
1280 rule! {
1281 SHOW ~ CREATE ~ DICTIONARY ~ #dot_separated_idents_1_to_3
1282 },
1283 |(_, _, _, (catalog, database, dictionary_name))| {
1284 Statement::ShowCreateDictionary(ShowCreateDictionaryStmt {
1285 catalog,
1286 database,
1287 dictionary_name,
1288 })
1289 },
1290 );
1291 let rename_dictionary = map(
1292 rule! {
1293 RENAME ~ DICTIONARY ~ ( IF ~ ^EXISTS )? ~ #dot_separated_idents_1_to_3 ~ TO ~ #dot_separated_idents_1_to_3
1294 },
1295 |(
1296 _,
1297 _,
1298 opt_if_exists,
1299 (catalog, database, dictionary),
1300 _,
1301 (new_catalog, new_database, new_dictionary),
1302 )| {
1303 Statement::RenameDictionary(RenameDictionaryStmt {
1304 if_exists: opt_if_exists.is_some(),
1305 catalog,
1306 database,
1307 dictionary,
1308 new_catalog,
1309 new_database,
1310 new_dictionary,
1311 })
1312 },
1313 );
1314
1315 let create_view = map_res(
1316 rule! {
1317 CREATE ~ ( OR ~ ^REPLACE )? ~ VIEW ~ ( IF ~ ^NOT ~ ^EXISTS )?
1318 ~ #dot_separated_idents_1_to_3
1319 ~ ( "(" ~ #comma_separated_list1(ident) ~ ")" )?
1320 ~ AS ~ #query
1321 },
1322 |(
1323 _,
1324 opt_or_replace,
1325 _,
1326 opt_if_not_exists,
1327 (catalog, database, view),
1328 opt_columns,
1329 _,
1330 query,
1331 )| {
1332 let create_option =
1333 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
1334 Ok(Statement::CreateView(CreateViewStmt {
1335 create_option,
1336 catalog,
1337 database,
1338 view,
1339 columns: opt_columns
1340 .map(|(_, columns, _)| columns)
1341 .unwrap_or_default(),
1342 query: Box::new(query),
1343 }))
1344 },
1345 );
1346 let drop_view = map(
1347 rule! {
1348 DROP ~ VIEW ~ ( IF ~ ^EXISTS )? ~ #dot_separated_idents_1_to_3
1349 },
1350 |(_, _, opt_if_exists, (catalog, database, view))| {
1351 Statement::DropView(DropViewStmt {
1352 if_exists: opt_if_exists.is_some(),
1353 catalog,
1354 database,
1355 view,
1356 })
1357 },
1358 );
1359 let alter_view = map(
1360 rule! {
1361 ALTER ~ VIEW
1362 ~ #dot_separated_idents_1_to_3
1363 ~ ( "(" ~ #comma_separated_list1(ident) ~ ")" )?
1364 ~ AS ~ #query
1365 },
1366 |(_, _, (catalog, database, view), opt_columns, _, query)| {
1367 Statement::AlterView(AlterViewStmt {
1368 catalog,
1369 database,
1370 view,
1371 columns: opt_columns
1372 .map(|(_, columns, _)| columns)
1373 .unwrap_or_default(),
1374 query: Box::new(query),
1375 })
1376 },
1377 );
1378 let show_views = map(
1379 rule! {
1380 SHOW ~ FULL? ~ VIEWS ~ HISTORY? ~ ( ( FROM | IN ) ~ #dot_separated_idents_1_to_2 )? ~ #show_limit?
1381 },
1382 |(_, opt_full, _, opt_history, ctl_db, limit)| {
1383 let (catalog, database) = match ctl_db {
1384 Some((_, (Some(c), d))) => (Some(c), Some(d)),
1385 Some((_, (None, d))) => (None, Some(d)),
1386 _ => (None, None),
1387 };
1388 Statement::ShowViews(ShowViewsStmt {
1389 catalog,
1390 database,
1391 full: opt_full.is_some(),
1392 limit,
1393 with_history: opt_history.is_some(),
1394 })
1395 },
1396 );
1397 let describe_view = map(
1398 rule! {
1399 ( DESC | DESCRIBE ) ~ VIEW ~ #dot_separated_idents_1_to_3
1400 },
1401 |(_, _, (catalog, database, view))| {
1402 Statement::DescribeView(DescribeViewStmt {
1403 catalog,
1404 database,
1405 view,
1406 })
1407 },
1408 );
1409
1410 let create_index = map_res(
1411 rule! {
1412 CREATE
1413 ~ ( OR ~ ^REPLACE )?
1414 ~ ASYNC?
1415 ~ AGGREGATING ~ INDEX
1416 ~ ( IF ~ ^NOT ~ ^EXISTS )?
1417 ~ #ident
1418 ~ AS ~ #query
1419 },
1420 |(_, opt_or_replace, opt_async, _, _, opt_if_not_exists, index_name, _, query)| {
1421 let create_option =
1422 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
1423 Ok(Statement::CreateIndex(CreateIndexStmt {
1424 index_type: TableIndexType::Aggregating,
1425 create_option,
1426 index_name,
1427 query: Box::new(query),
1428 sync_creation: opt_async.is_none(),
1429 }))
1430 },
1431 );
1432
1433 let drop_index = map(
1434 rule! {
1435 DROP ~ AGGREGATING ~ INDEX ~ ( IF ~ ^EXISTS )? ~ #ident
1436 },
1437 |(_, _, _, opt_if_exists, index)| {
1438 Statement::DropIndex(DropIndexStmt {
1439 if_exists: opt_if_exists.is_some(),
1440 index,
1441 })
1442 },
1443 );
1444
1445 let refresh_index = map(
1446 rule! {
1447 REFRESH ~ AGGREGATING ~ INDEX ~ #ident ~ ( LIMIT ~ #literal_u64 )?
1448 },
1449 |(_, _, _, index, opt_limit)| {
1450 Statement::RefreshIndex(RefreshIndexStmt {
1451 index,
1452 limit: opt_limit.map(|(_, limit)| limit),
1453 })
1454 },
1455 );
1456
1457 let create_table_index = map_res(
1458 rule! {
1459 CREATE
1460 ~ ( OR ~ ^REPLACE )?
1461 ~ ASYNC?
1462 ~ #index_type ~ ^INDEX
1463 ~ ( IF ~ ^NOT ~ ^EXISTS )?
1464 ~ #ident
1465 ~ ON ~ #dot_separated_idents_1_to_3
1466 ~ ^"(" ~ ^#comma_separated_list1(ident) ~ ^")"
1467 ~ ( #table_option )?
1468 },
1469 |(
1470 _,
1471 opt_or_replace,
1472 opt_async,
1473 index_type,
1474 _,
1475 opt_if_not_exists,
1476 index_name,
1477 _,
1478 (catalog, database, table),
1479 _,
1480 columns,
1481 _,
1482 opt_index_options,
1483 )| {
1484 let create_option =
1485 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
1486 Ok(Statement::CreateTableIndex(CreateTableIndexStmt {
1487 create_option,
1488 index_name,
1489 index_type,
1490 catalog,
1491 database,
1492 table,
1493 columns,
1494 sync_creation: opt_async.is_none(),
1495 index_options: opt_index_options.unwrap_or_default(),
1496 }))
1497 },
1498 );
1499
1500 let drop_table_index = map(
1501 rule! {
1502 DROP ~ #index_type ~ ^INDEX ~ ( IF ~ ^EXISTS )? ~ #ident
1503 ~ ON ~ #dot_separated_idents_1_to_3
1504 },
1505 |(_, index_type, _, opt_if_exists, index_name, _, (catalog, database, table))| {
1506 Statement::DropTableIndex(DropTableIndexStmt {
1507 if_exists: opt_if_exists.is_some(),
1508 index_name,
1509 index_type,
1510 catalog,
1511 database,
1512 table,
1513 })
1514 },
1515 );
1516
1517 let refresh_table_index = map(
1518 rule! {
1519 REFRESH ~ #index_type ~ ^INDEX ~ #ident ~ ON ~ #dot_separated_idents_1_to_3 ~ ( LIMIT ~ #literal_u64 )?
1520 },
1521 |(_, index_type, _, index_name, _, (catalog, database, table), opt_limit)| {
1522 Statement::RefreshTableIndex(RefreshTableIndexStmt {
1523 index_name,
1524 index_type,
1525 catalog,
1526 database,
1527 table,
1528 limit: opt_limit.map(|(_, limit)| limit),
1529 })
1530 },
1531 );
1532
1533 let refresh_virtual_column = map(
1534 rule! {
1535 REFRESH ~ VIRTUAL ~ COLUMN ~ FOR ~ #dot_separated_idents_1_to_3
1536 },
1537 |(_, _, _, _, (catalog, database, table))| {
1538 Statement::RefreshVirtualColumn(RefreshVirtualColumnStmt {
1539 catalog,
1540 database,
1541 table,
1542 })
1543 },
1544 );
1545
1546 let show_virtual_columns = map(
1547 rule! {
1548 SHOW ~ VIRTUAL ~ COLUMNS ~ ( ( FROM | IN ) ~ #ident )? ~ ( ( FROM | IN ) ~ ^#dot_separated_idents_1_to_2 )? ~ #show_limit?
1549 },
1550 |(_, _, _, opt_table, opt_db, limit)| {
1551 let table = opt_table.map(|(_, table)| table);
1552 let (catalog, database) = match opt_db {
1553 Some((_, (Some(c), d))) => (Some(c), Some(d)),
1554 Some((_, (None, d))) => (None, Some(d)),
1555 _ => (None, None),
1556 };
1557 Statement::ShowVirtualColumns(ShowVirtualColumnsStmt {
1558 catalog,
1559 database,
1560 table,
1561 limit,
1562 })
1563 },
1564 );
1565
1566 let show_users = map(
1567 rule! {
1568 SHOW ~ USERS ~ #show_options?
1569 },
1570 |(_, _, show_options)| Statement::ShowUsers { show_options },
1571 );
1572
1573 let describe_user = map(
1574 rule! {
1575 ( DESC | DESCRIBE ) ~ USER ~ ^#user_identity
1576 },
1577 |(_, _, user)| Statement::DescribeUser { user },
1578 );
1579 let create_user = map_res(
1580 rule! {
1581 CREATE ~ ( OR ~ ^REPLACE )? ~ USER ~ ( IF ~ ^NOT ~ ^EXISTS )?
1582 ~ #user_identity
1583 ~ IDENTIFIED ~ ( WITH ~ ^#auth_type )? ~ ( BY ~ ^#literal_string )?
1584 ~ ( WITH ~ ^#comma_separated_list1(user_option))?
1585 },
1586 |(
1587 _,
1588 opt_or_replace,
1589 _,
1590 opt_if_not_exists,
1591 user,
1592 _,
1593 opt_auth_type,
1594 opt_password,
1595 opt_user_option,
1596 )| {
1597 let create_option =
1598 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
1599 Ok(Statement::CreateUser(CreateUserStmt {
1600 create_option,
1601 user,
1602 auth_option: AuthOption {
1603 auth_type: opt_auth_type.map(|(_, auth_type)| auth_type),
1604 password: opt_password.map(|(_, password)| password),
1605 },
1606 user_options: opt_user_option
1607 .map(|(_, user_options)| user_options)
1608 .unwrap_or_default(),
1609 }))
1610 },
1611 );
1612 let alter_user = map(
1613 rule! {
1614 ALTER ~ USER ~ ( #map(rule! { USER ~ "(" ~ ")" }, |_| None) | #map(user_identity, Some) )
1615 ~ ( IDENTIFIED ~ ( WITH ~ ^#auth_type )? ~ ( BY ~ ^#literal_string )? )?
1616 ~ ( WITH ~ ^#comma_separated_list1(user_option) )?
1617 },
1618 |(_, _, user, opt_auth_option, opt_user_option)| {
1619 Statement::AlterUser(AlterUserStmt {
1620 user,
1621 auth_option: opt_auth_option.map(|(_, opt_auth_type, opt_password)| AuthOption {
1622 auth_type: opt_auth_type.map(|(_, auth_type)| auth_type),
1623 password: opt_password.map(|(_, password)| password),
1624 }),
1625 user_options: opt_user_option
1626 .map(|(_, user_options)| user_options)
1627 .unwrap_or_default(),
1628 })
1629 },
1630 );
1631 let drop_user = map(
1632 rule! {
1633 DROP ~ USER ~ ( IF ~ ^EXISTS )? ~ #user_identity
1634 },
1635 |(_, _, opt_if_exists, user)| Statement::DropUser {
1636 if_exists: opt_if_exists.is_some(),
1637 user,
1638 },
1639 );
1640 let show_roles = map(
1641 rule! {
1642 SHOW ~ ROLES ~ #show_options?
1643 },
1644 |(_, _, show_options)| Statement::ShowRoles { show_options },
1645 );
1646 let create_role = map(
1647 rule! {
1648 CREATE ~ ROLE ~ ( IF ~ ^NOT ~ ^EXISTS )? ~ #role_name
1649 },
1650 |(_, _, opt_if_not_exists, role_name)| Statement::CreateRole {
1651 if_not_exists: opt_if_not_exists.is_some(),
1652 role_name,
1653 },
1654 );
1655 let drop_role = map(
1656 rule! {
1657 DROP ~ ROLE ~ ( IF ~ ^EXISTS )? ~ #role_name
1658 },
1659 |(_, _, opt_if_exists, role_name)| Statement::DropRole {
1660 if_exists: opt_if_exists.is_some(),
1661 role_name,
1662 },
1663 );
1664 let grant = map(
1665 rule! {
1666 GRANT ~ #grant_source ~ TO ~ #grant_option
1667 },
1668 |(_, source, _, grant_option)| {
1669 Statement::Grant(GrantStmt {
1670 source,
1671 principal: grant_option,
1672 })
1673 },
1674 );
1675 let grant_ownership = map(
1676 rule! {
1677 GRANT ~ OWNERSHIP ~ ON ~ #grant_ownership_level ~ TO ~ ROLE ~ #role_name
1678 },
1679 |(_, _, _, level, _, _, role_name)| {
1680 Statement::Grant(GrantStmt {
1681 source: AccountMgrSource::Privs {
1682 privileges: vec![UserPrivilegeType::Ownership],
1683 level,
1684 },
1685 principal: PrincipalIdentity::Role(role_name),
1686 })
1687 },
1688 );
1689 let show_grants = map(
1690 rule! {
1691 SHOW ~ GRANTS ~ #show_grant_option? ~ ^#show_options?
1692 },
1693 |(_, _, show_grant_option, opt_limit)| match show_grant_option {
1694 Some(ShowGrantOption::PrincipalIdentity(principal)) => Statement::ShowGrants {
1695 principal: Some(principal),
1696 show_options: opt_limit,
1697 },
1698 None => Statement::ShowGrants {
1699 principal: None,
1700 show_options: opt_limit,
1701 },
1702 Some(ShowGrantOption::GrantObjectName(object)) => {
1703 Statement::ShowObjectPrivileges(ShowObjectPrivilegesStmt {
1704 object,
1705 show_option: opt_limit,
1706 })
1707 }
1708 Some(ShowGrantOption::OfRole(name)) => {
1709 Statement::ShowGrantsOfRole(ShowGranteesOfRoleStmt {
1710 name,
1711 show_option: opt_limit,
1712 })
1713 }
1714 },
1715 );
1716 let revoke = map(
1717 rule! {
1718 REVOKE ~ #grant_source ~ FROM ~ #grant_option
1719 },
1720 |(_, source, _, grant_option)| {
1721 Statement::Revoke(RevokeStmt {
1722 source,
1723 principal: grant_option,
1724 })
1725 },
1726 );
1727 let create_udf = map_res(
1728 rule! {
1729 CREATE ~ ( OR ~ ^REPLACE )? ~ FUNCTION ~ ( IF ~ ^NOT ~ ^EXISTS )?
1730 ~ #ident ~ #udf_definition
1731 ~ ( DESC ~ ^"=" ~ ^#literal_string )?
1732 },
1733 |(_, opt_or_replace, _, opt_if_not_exists, udf_name, definition, opt_description)| {
1734 let create_option =
1735 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
1736 Ok(Statement::CreateUDF(CreateUDFStmt {
1737 create_option,
1738 udf_name,
1739 description: opt_description.map(|(_, _, description)| description),
1740 definition,
1741 }))
1742 },
1743 );
1744 let drop_udf = map(
1745 rule! {
1746 DROP ~ FUNCTION ~ ( IF ~ ^EXISTS )? ~ #ident
1747 },
1748 |(_, _, opt_if_exists, udf_name)| Statement::DropUDF {
1749 if_exists: opt_if_exists.is_some(),
1750 udf_name,
1751 },
1752 );
1753 let alter_udf = map(
1754 rule! {
1755 ALTER ~ FUNCTION
1756 ~ #ident ~ #udf_definition
1757 ~ ( DESC ~ ^"=" ~ ^#literal_string )?
1758 },
1759 |(_, _, udf_name, definition, opt_description)| {
1760 Statement::AlterUDF(AlterUDFStmt {
1761 udf_name,
1762 description: opt_description.map(|(_, _, description)| description),
1763 definition,
1764 })
1765 },
1766 );
1767
1768 let create_stage = map_res(
1770 rule! {
1771 CREATE ~ ( OR ~ ^REPLACE )? ~ STAGE ~ ( IF ~ ^NOT ~ ^EXISTS )?
1772 ~ ( #stage_name )
1773 ~ ( (URL ~ ^"=")? ~ #uri_location )?
1774 ~ ( #file_format_clause )?
1775 ~ ( (COMMENT | COMMENTS) ~ ^"=" ~ ^#literal_string )?
1776 },
1777 |(
1778 _,
1779 opt_or_replace,
1780 _,
1781 opt_if_not_exists,
1782 stage,
1783 url_opt,
1784 file_format_opt,
1785 comment_opt,
1786 )| {
1787 let create_option =
1788 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
1789 Ok(Statement::CreateStage(CreateStageStmt {
1790 create_option,
1791 stage_name: stage.to_string(),
1792 location: url_opt.map(|(_, location)| location),
1793 file_format_options: file_format_opt.unwrap_or_default(),
1794 comments: comment_opt.map(|v| v.2).unwrap_or_default(),
1795 }))
1796 },
1797 );
1798
1799 let list_stage = map(
1800 rule! {
1801 LIST ~ #at_string ~ (PATTERN ~ "=" ~ #literal_string)?
1802 },
1803 |(_, location, opt_pattern)| Statement::ListStage {
1804 location,
1805 pattern: opt_pattern.map(|v| v.2),
1806 },
1807 );
1808
1809 let remove_stage = map(
1810 rule! {
1811 REMOVE ~ #at_string ~ (PATTERN ~ "=" ~ #literal_string)?
1812 },
1813 |(_, location, opt_pattern)| Statement::RemoveStage {
1814 location,
1815 pattern: opt_pattern.map(|v| v.2).unwrap_or_default(),
1816 },
1817 );
1818
1819 let drop_stage = map(
1820 rule! {
1821 DROP ~ STAGE ~ ( IF ~ ^EXISTS )? ~ #stage_name
1822 },
1823 |(_, _, opt_if_exists, stage_name)| Statement::DropStage {
1824 if_exists: opt_if_exists.is_some(),
1825 stage_name: stage_name.to_string(),
1826 },
1827 );
1828
1829 let desc_stage = map(
1830 rule! {
1831 (DESC | DESCRIBE) ~ STAGE ~ #ident
1832 },
1833 |(_, _, stage_name)| Statement::DescribeStage {
1834 stage_name: stage_name.to_string(),
1835 },
1836 );
1837
1838 let connection_opt = connection_opt("=");
1840 let create_connection = map_res(
1841 rule! {
1842 CREATE ~ ( OR ~ ^REPLACE )? ~ CONNECTION ~ ( IF ~ ^NOT ~ ^EXISTS )?
1843 ~ #ident ~ STORAGE_TYPE ~ "=" ~ #literal_string ~ #connection_opt*
1844 },
1845 |(
1846 _,
1847 opt_or_replace,
1848 _,
1849 opt_if_not_exists,
1850 connection_name,
1851 _,
1852 _,
1853 storage_type,
1854 options,
1855 )| {
1856 let create_option =
1857 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
1858 let options =
1859 BTreeMap::from_iter(options.iter().map(|(k, v)| (k.to_lowercase(), v.clone())));
1860 Ok(Statement::CreateConnection(CreateConnectionStmt {
1861 create_option,
1862 name: connection_name,
1863 storage_type,
1864 storage_params: options,
1865 }))
1866 },
1867 );
1868
1869 let drop_connection = map(
1870 rule! {
1871 DROP ~ CONNECTION ~ ( IF ~ ^EXISTS )? ~ #ident
1872 },
1873 |(_, _, opt_if_exists, connection_name)| {
1874 Statement::DropConnection(DropConnectionStmt {
1875 if_exists: opt_if_exists.is_some(),
1876 name: connection_name,
1877 })
1878 },
1879 );
1880
1881 let desc_connection = map(
1882 rule! {
1883 (DESC | DESCRIBE) ~ CONNECTION ~ #ident
1884 },
1885 |(_, _, name)| Statement::DescribeConnection(DescribeConnectionStmt { name }),
1886 );
1887
1888 let show_connections = map(
1889 rule! {
1890 SHOW ~ CONNECTIONS
1891 },
1892 |(_, _)| Statement::ShowConnections(ShowConnectionsStmt {}),
1893 );
1894
1895 let call = map(
1896 rule! {
1897 CALL ~ #ident ~ "(" ~ #comma_separated_list0(parameter_to_string) ~ ")"
1898 },
1899 |(_, name, _, args, _)| {
1900 Statement::Call(CallStmt {
1901 name: name.to_string(),
1902 args,
1903 })
1904 },
1905 );
1906
1907 let vacuum_temporary_tables = map(
1908 rule! {
1909 VACUUM ~ TEMPORARY ~ TABLES ~ ( LIMIT ~ ^#literal_u64 )?
1910 },
1911 |(_, _, _, opt_limit)| {
1912 Statement::Call(CallStmt {
1913 name: "fuse_vacuum_temporary_table".to_string(),
1914 args: opt_limit.map(|v| v.1.to_string()).into_iter().collect(),
1915 })
1916 },
1917 );
1918
1919 let presign = map(
1920 rule! {
1921 PRESIGN ~ ( #presign_action )?
1922 ~ #presign_location
1923 ~ ( #presign_option )*
1924 },
1925 |(_, action, location, opts)| {
1926 let mut presign_stmt = PresignStmt {
1927 action: action.unwrap_or_default(),
1928 location,
1929 expire: Duration::from_secs(3600),
1930 content_type: None,
1931 };
1932 for opt in opts {
1933 presign_stmt.apply_option(opt);
1934 }
1935 Statement::Presign(presign_stmt)
1936 },
1937 );
1938
1939 let create_file_format = map_res(
1940 rule! {
1941 CREATE ~ ( OR ~ ^REPLACE )? ~ FILE ~ FORMAT ~ ( IF ~ ^NOT ~ ^EXISTS )?
1942 ~ #ident ~ #format_options
1943 },
1944 |(_, opt_or_replace, _, _, opt_if_not_exists, name, file_format_options)| {
1945 let create_option =
1946 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
1947 Ok(Statement::CreateFileFormat {
1948 create_option,
1949 name: name.to_string(),
1950 file_format_options,
1951 })
1952 },
1953 );
1954
1955 let drop_file_format = map(
1956 rule! {
1957 DROP ~ FILE ~ FORMAT ~ ( IF ~ EXISTS )? ~ #ident
1958 },
1959 |(_, _, _, opt_if_exists, name)| Statement::DropFileFormat {
1960 if_exists: opt_if_exists.is_some(),
1961 name: name.to_string(),
1962 },
1963 );
1964
1965 let show_file_formats = value(Statement::ShowFileFormats, rule! { SHOW ~ FILE ~ FORMATS });
1966
1967 let create_data_mask_policy = map_res(
1969 rule! {
1970 CREATE ~ ( OR ~ ^REPLACE )? ~ MASKING ~ POLICY ~ ( IF ~ ^NOT ~ ^EXISTS )? ~ #ident ~ #data_mask_policy
1971 },
1972 |(_, opt_or_replace, _, _, opt_if_not_exists, name, policy)| {
1973 let create_option =
1974 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
1975 let stmt = CreateDatamaskPolicyStmt {
1976 create_option,
1977 name: name.to_string(),
1978 policy,
1979 };
1980 Ok(Statement::CreateDatamaskPolicy(stmt))
1981 },
1982 );
1983 let drop_data_mask_policy = map(
1984 rule! {
1985 DROP ~ MASKING ~ POLICY ~ ( IF ~ ^EXISTS )? ~ #ident
1986 },
1987 |(_, _, _, opt_if_exists, name)| {
1988 let stmt = DropDatamaskPolicyStmt {
1989 if_exists: opt_if_exists.is_some(),
1990 name: name.to_string(),
1991 };
1992 Statement::DropDatamaskPolicy(stmt)
1993 },
1994 );
1995 let describe_data_mask_policy = map(
1996 rule! {
1997 ( DESC | DESCRIBE ) ~ MASKING ~ POLICY ~ #ident
1998 },
1999 |(_, _, _, name)| {
2000 Statement::DescDatamaskPolicy(DescDatamaskPolicyStmt {
2001 name: name.to_string(),
2002 })
2003 },
2004 );
2005
2006 let create_network_policy = map_res(
2007 rule! {
2008 CREATE ~ ( OR ~ ^REPLACE )? ~ NETWORK ~ ^POLICY ~ ( IF ~ ^NOT ~ ^EXISTS )? ~ ^#ident
2009 ~ ALLOWED_IP_LIST ~ ^Eq ~ ^"(" ~ ^#comma_separated_list0(literal_string) ~ ^")"
2010 ~ ( BLOCKED_IP_LIST ~ ^Eq ~ ^"(" ~ ^#comma_separated_list0(literal_string) ~ ^")" ) ?
2011 ~ ( COMMENT ~ ^Eq ~ ^#literal_string)?
2012 },
2013 |(
2014 _,
2015 opt_or_replace,
2016 _,
2017 _,
2018 opt_if_not_exists,
2019 name,
2020 _,
2021 _,
2022 _,
2023 allowed_ip_list,
2024 _,
2025 opt_blocked_ip_list,
2026 opt_comment,
2027 )| {
2028 let create_option =
2029 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
2030 let stmt = CreateNetworkPolicyStmt {
2031 create_option,
2032 name: name.to_string(),
2033 allowed_ip_list,
2034 blocked_ip_list: match opt_blocked_ip_list {
2035 Some(opt) => Some(opt.3),
2036 None => None,
2037 },
2038 comment: match opt_comment {
2039 Some(opt) => Some(opt.2),
2040 None => None,
2041 },
2042 };
2043 Ok(Statement::CreateNetworkPolicy(stmt))
2044 },
2045 );
2046 let alter_network_policy = map(
2047 rule! {
2048 ALTER ~ NETWORK ~ ^POLICY ~ ( IF ~ ^EXISTS )? ~ ^#ident ~ SET
2049 ~ ( ALLOWED_IP_LIST ~ ^Eq ~ ^"(" ~ ^#comma_separated_list0(literal_string) ~ ^")" ) ?
2050 ~ ( BLOCKED_IP_LIST ~ ^Eq ~ ^"(" ~ ^#comma_separated_list0(literal_string) ~ ^")" ) ?
2051 ~ ( COMMENT ~ ^Eq ~ ^#literal_string)?
2052 },
2053 |(
2054 _,
2055 _,
2056 _,
2057 opt_if_exists,
2058 name,
2059 _,
2060 opt_allowed_ip_list,
2061 opt_blocked_ip_list,
2062 opt_comment,
2063 )| {
2064 let stmt = AlterNetworkPolicyStmt {
2065 if_exists: opt_if_exists.is_some(),
2066 name: name.to_string(),
2067 allowed_ip_list: match opt_allowed_ip_list {
2068 Some(opt) => Some(opt.3),
2069 None => None,
2070 },
2071 blocked_ip_list: match opt_blocked_ip_list {
2072 Some(opt) => Some(opt.3),
2073 None => None,
2074 },
2075 comment: match opt_comment {
2076 Some(opt) => Some(opt.2),
2077 None => None,
2078 },
2079 };
2080 Statement::AlterNetworkPolicy(stmt)
2081 },
2082 );
2083 let drop_network_policy = map(
2084 rule! {
2085 DROP ~ NETWORK ~ ^POLICY ~ ( IF ~ ^EXISTS )? ~ ^#ident
2086 },
2087 |(_, _, _, opt_if_exists, name)| {
2088 let stmt = DropNetworkPolicyStmt {
2089 if_exists: opt_if_exists.is_some(),
2090 name: name.to_string(),
2091 };
2092 Statement::DropNetworkPolicy(stmt)
2093 },
2094 );
2095 let describe_network_policy = map(
2096 rule! {
2097 ( DESC | DESCRIBE ) ~ NETWORK ~ ^POLICY ~ ^#ident
2098 },
2099 |(_, _, _, name)| {
2100 Statement::DescNetworkPolicy(DescNetworkPolicyStmt {
2101 name: name.to_string(),
2102 })
2103 },
2104 );
2105 let show_network_policies = value(
2106 Statement::ShowNetworkPolicies,
2107 rule! { SHOW ~ NETWORK ~ ^POLICIES },
2108 );
2109
2110 let create_password_policy = map_res(
2111 rule! {
2112 CREATE ~ ( OR ~ ^REPLACE )? ~ PASSWORD ~ ^POLICY ~ ( IF ~ ^NOT ~ ^EXISTS )? ~ ^#ident
2113 ~ #password_set_options
2114 },
2115 |(_, opt_or_replace, _, _, opt_if_not_exists, name, set_options)| {
2116 let create_option =
2117 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
2118 let stmt = CreatePasswordPolicyStmt {
2119 create_option,
2120 name: name.to_string(),
2121 set_options,
2122 };
2123 Ok(Statement::CreatePasswordPolicy(stmt))
2124 },
2125 );
2126 let alter_password_policy = map(
2127 rule! {
2128 ALTER ~ PASSWORD ~ ^POLICY ~ ( IF ~ ^EXISTS )? ~ ^#ident
2129 ~ #alter_password_action
2130 },
2131 |(_, _, _, opt_if_exists, name, action)| {
2132 let stmt = AlterPasswordPolicyStmt {
2133 if_exists: opt_if_exists.is_some(),
2134 name: name.to_string(),
2135 action,
2136 };
2137 Statement::AlterPasswordPolicy(stmt)
2138 },
2139 );
2140 let drop_password_policy = map(
2141 rule! {
2142 DROP ~ PASSWORD ~ ^POLICY ~ ( IF ~ ^EXISTS )? ~ ^#ident
2143 },
2144 |(_, _, _, opt_if_exists, name)| {
2145 let stmt = DropPasswordPolicyStmt {
2146 if_exists: opt_if_exists.is_some(),
2147 name: name.to_string(),
2148 };
2149 Statement::DropPasswordPolicy(stmt)
2150 },
2151 );
2152 let describe_password_policy = map(
2153 rule! {
2154 ( DESC | DESCRIBE ) ~ PASSWORD ~ ^POLICY ~ ^#ident
2155 },
2156 |(_, _, _, name)| {
2157 Statement::DescPasswordPolicy(DescPasswordPolicyStmt {
2158 name: name.to_string(),
2159 })
2160 },
2161 );
2162 let show_password_policies = map(
2163 rule! {
2164 SHOW ~ PASSWORD ~ ^POLICIES ~ ^#show_options?
2165 },
2166 |(_, _, _, show_options)| Statement::ShowPasswordPolicies { show_options },
2167 );
2168
2169 let create_pipe = map(
2170 rule! {
2171 CREATE ~ PIPE ~ ( IF ~ ^NOT ~ ^EXISTS )?
2172 ~ #ident
2173 ~ ( AUTO_INGEST ~ "=" ~ #literal_bool )?
2174 ~ ( (COMMENT | COMMENTS) ~ ^"=" ~ ^#literal_string )?
2175 ~ AS ~ #copy_into_table
2176 },
2177 |(_, _, opt_if_not_exists, pipe, ingest, comment_opt, _, copy_stmt)| {
2178 let copy_stmt = match copy_stmt {
2179 Statement::CopyIntoTable(stmt) => stmt,
2180 _ => {
2181 unreachable!()
2182 }
2183 };
2184 Statement::CreatePipe(CreatePipeStmt {
2185 if_not_exists: opt_if_not_exists.is_some(),
2186 name: pipe.to_string(),
2187 auto_ingest: ingest.map(|v| v.2).unwrap_or_default(),
2188 comments: comment_opt.map(|v| v.2).unwrap_or_default(),
2189 copy_stmt,
2190 })
2191 },
2192 );
2193
2194 let alter_pipe = map(
2195 rule! {
2196 ALTER ~ PIPE ~ ( IF ~ ^EXISTS )?
2197 ~ #ident ~ #alter_pipe_option
2198 },
2199 |(_, _, opt_if_exists, task, options)| {
2200 Statement::AlterPipe(AlterPipeStmt {
2201 if_exists: opt_if_exists.is_some(),
2202 name: task.to_string(),
2203 options,
2204 })
2205 },
2206 );
2207
2208 let drop_pipe = map(
2209 rule! {
2210 DROP ~ PIPE ~ ( IF ~ ^EXISTS )?
2211 ~ #ident
2212 },
2213 |(_, _, opt_if_exists, task)| {
2214 Statement::DropPipe(DropPipeStmt {
2215 if_exists: opt_if_exists.is_some(),
2216 name: task.to_string(),
2217 })
2218 },
2219 );
2220
2221 let desc_pipe = map(
2222 rule! {
2223 ( DESC | DESCRIBE ) ~ PIPE ~ #ident
2224 },
2225 |(_, _, task)| {
2226 Statement::DescribePipe(DescribePipeStmt {
2227 name: task.to_string(),
2228 })
2229 },
2230 );
2231 let create_notification = map(
2232 rule! {
2233 CREATE ~ NOTIFICATION ~ INTEGRATION
2234 ~ ( IF ~ ^NOT ~ ^EXISTS )?
2235 ~ #ident
2236 ~ TYPE ~ "=" ~ #ident
2237 ~ ENABLED ~ "=" ~ #literal_bool
2238 ~ #notification_webhook_clause?
2239 ~ ( (COMMENT | COMMENTS) ~ ^"=" ~ ^#literal_string )?
2240 },
2241 |(
2242 _,
2243 _,
2244 _,
2245 if_not_exists,
2246 name,
2247 _,
2248 _,
2249 notification_type,
2250 _,
2251 _,
2252 enabled,
2253 webhook,
2254 comment,
2255 )| {
2256 Statement::CreateNotification(CreateNotificationStmt {
2257 if_not_exists: if_not_exists.is_some(),
2258 name: name.to_string(),
2259 notification_type: notification_type.to_string(),
2260 enabled,
2261 webhook_opts: webhook,
2262 comments: comment.map(|(_, _, comments)| comments),
2263 })
2264 },
2265 );
2266
2267 let drop_notification = map(
2268 rule! {
2269 DROP ~ NOTIFICATION ~ INTEGRATION ~ ( IF ~ ^EXISTS )?
2270 ~ #ident
2271 },
2272 |(_, _, _, if_exists, name)| {
2273 Statement::DropNotification(DropNotificationStmt {
2274 if_exists: if_exists.is_some(),
2275 name: name.to_string(),
2276 })
2277 },
2278 );
2279
2280 let alter_notification = map(
2281 rule! {
2282 ALTER ~ NOTIFICATION ~ INTEGRATION ~ ( IF ~ ^EXISTS )?
2283 ~ #ident
2284 ~ #alter_notification_options
2285 },
2286 |(_, _, _, if_exists, name, options)| {
2287 Statement::AlterNotification(AlterNotificationStmt {
2288 if_exists: if_exists.is_some(),
2289 name: name.to_string(),
2290 options,
2291 })
2292 },
2293 );
2294
2295 let desc_notification = map(
2296 rule! {
2297 ( DESC | DESCRIBE ) ~ NOTIFICATION ~ INTEGRATION ~ #ident
2298 },
2299 |(_, _, _, name)| {
2300 Statement::DescribeNotification(DescribeNotificationStmt {
2301 name: name.to_string(),
2302 })
2303 },
2304 );
2305
2306 let begin = value(Statement::Begin, rule! { BEGIN ~ TRANSACTION? });
2307 let commit = value(Statement::Commit, rule! { COMMIT });
2308 let abort = value(Statement::Abort, rule! { ABORT | ROLLBACK });
2309
2310 let execute_immediate = map(
2311 rule! {
2312 EXECUTE ~ IMMEDIATE ~ #code_string
2313 },
2314 |(_, _, script)| Statement::ExecuteImmediate(ExecuteImmediateStmt { script }),
2315 );
2316
2317 let system_action = map(
2318 rule! {
2319 SYSTEM ~ #action
2320 },
2321 |(_, action)| Statement::System(SystemStmt { action }),
2322 );
2323
2324 pub fn procedure_type(i: Input) -> IResult<ProcedureType> {
2325 map(rule! { #ident ~ #type_name }, |(name, data_type)| {
2326 ProcedureType {
2327 name: Some(name.to_string()),
2328 data_type,
2329 }
2330 })(i)
2331 }
2332
2333 fn procedure_return(i: Input) -> IResult<Vec<ProcedureType>> {
2334 let procedure_table_return = map(
2335 rule! {
2336 TABLE ~ "(" ~ #comma_separated_list1(procedure_type) ~ ")"
2337 },
2338 |(_, _, test, _)| test,
2339 );
2340 let procedure_single_return = map(rule! { #type_name }, |data_type| {
2341 vec![ProcedureType {
2342 name: None,
2343 data_type,
2344 }]
2345 });
2346 rule!(#procedure_single_return: "<type_name>"
2347 | #procedure_table_return: "TABLE(<var_name> <type_name>, ...)")(i)
2348 }
2349
2350 fn procedure_arg(i: Input) -> IResult<Option<Vec<ProcedureType>>> {
2351 let procedure_args = map(
2352 rule! {
2353 "(" ~ #comma_separated_list1(procedure_type) ~ ")"
2354 },
2355 |(_, args, _)| Some(args),
2356 );
2357 let procedure_empty_args = map(
2358 rule! {
2359 "(" ~ ")"
2360 },
2361 |(_, _)| None,
2362 );
2363 rule!(#procedure_empty_args: "()"
2364 | #procedure_args: "(<var_name> <type_name>, ...)")(i)
2365 }
2366
2367 let create_procedure = map_res(
2372 rule! {
2373 CREATE ~ ( OR ~ ^REPLACE )? ~ PROCEDURE ~ ( IF ~ ^NOT ~ ^EXISTS )? ~ #ident ~ #procedure_arg ~ RETURNS ~ #procedure_return ~ LANGUAGE ~ SQL ~ (COMMENT ~ "=" ~ #literal_string)? ~ AS ~ #code_string
2374 },
2375 |(
2376 _,
2377 opt_or_replace,
2378 _,
2379 opt_if_not_exists,
2380 name,
2381 args,
2382 _,
2383 return_type,
2384 _,
2385 _,
2386 opt_comment,
2387 _,
2388 script,
2389 )| {
2390 let create_option =
2391 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
2392
2393 let name = ProcedureIdentity {
2394 name: name.to_string(),
2395 args_type: if let Some(args) = &args {
2396 args.iter()
2397 .map(|arg| arg.data_type.to_string())
2398 .collect::<Vec<String>>()
2399 .join(",")
2400 } else {
2401 "".to_string()
2402 },
2403 };
2404 let stmt = CreateProcedureStmt {
2405 create_option,
2406 name,
2407 args,
2408 return_type,
2409 language: ProcedureLanguage::SQL,
2410 comment: match opt_comment {
2411 Some(opt) => Some(opt.2),
2412 None => None,
2413 },
2414 script,
2415 };
2416 Ok(Statement::CreateProcedure(stmt))
2417 },
2418 );
2419
2420 let show_procedures = map(
2421 rule! {
2422 SHOW ~ PROCEDURES ~ #show_options?
2423 },
2424 |(_, _, show_options)| Statement::ShowProcedures { show_options },
2425 );
2426
2427 fn procedure_type_name(i: Input) -> IResult<Vec<TypeName>> {
2428 let procedure_type_names = map(
2429 rule! {
2430 "(" ~ #comma_separated_list1(type_name) ~ ")"
2431 },
2432 |(_, args, _)| args,
2433 );
2434 let procedure_empty_types = map(
2435 rule! {
2436 "(" ~ ")"
2437 },
2438 |(_, _)| vec![],
2439 );
2440 rule!(#procedure_empty_types: "()"
2441 | #procedure_type_names: "(<type_name>, ...)")(i)
2442 }
2443
2444 let call_procedure = map(
2445 rule! {
2446 CALL ~ PROCEDURE ~ #ident ~ "(" ~ #comma_separated_list0(subexpr(0))? ~ ")"
2447 },
2448 |(_, _, name, _, opt_args, _)| {
2449 Statement::CallProcedure(CallProcedureStmt {
2450 name: name.to_string(),
2451 args: opt_args.unwrap_or_default(),
2452 })
2453 },
2454 );
2455
2456 let drop_procedure = map(
2457 rule! {
2458 DROP ~ PROCEDURE ~ ( IF ~ ^EXISTS )? ~ #ident ~ #procedure_type_name
2459 },
2460 |(_, _, opt_if_exists, name, args)| {
2461 Statement::DropProcedure(DropProcedureStmt {
2462 if_exists: opt_if_exists.is_some(),
2463 name: ProcedureIdentity {
2464 name: name.to_string(),
2465 args_type: if args.is_empty() {
2466 "".to_string()
2467 } else {
2468 args.iter()
2469 .map(|arg| arg.to_string())
2470 .collect::<Vec<String>>()
2471 .join(",")
2472 },
2473 },
2474 })
2475 },
2476 );
2477
2478 let describe_procedure = map(
2479 rule! {
2480 ( DESC | DESCRIBE ) ~ PROCEDURE ~ #ident ~ #procedure_type_name
2481 },
2482 |(_, _, name, args)| {
2483 Statement::DescProcedure(DescProcedureStmt {
2484 name: ProcedureIdentity {
2485 name: name.to_string(),
2486 args_type: if args.is_empty() {
2487 "".to_string()
2488 } else {
2489 args.iter()
2490 .map(|arg| arg.to_string())
2491 .collect::<Vec<String>>()
2492 .join(",")
2493 },
2494 },
2495 })
2496 },
2497 );
2498
2499 alt((
2500 rule!(
2502 #map(query, |query| Statement::Query(Box::new(query)))
2503 | #explain : "`EXPLAIN [PIPELINE | GRAPH] <statement>`"
2504 | #explain_analyze : "`EXPLAIN ANALYZE <statement>`"
2505 | #report: "`REPORT ISSUE <statement>`"
2506 | #show_settings : "`SHOW SETTINGS [<show_limit>]`"
2507 | #show_variables : "`SHOW VARIABLES [<show_limit>]`"
2508 | #show_stages : "`SHOW STAGES`"
2509 | #show_engines : "`SHOW ENGINES`"
2510 | #show_process_list : "`SHOW PROCESSLIST`"
2511 | #show_metrics : "`SHOW METRICS`"
2512 | #show_functions : "`SHOW FUNCTIONS [<show_limit>]`"
2513 | #show_indexes : "`SHOW INDEXES`"
2514 | #show_locks : "`SHOW LOCKS [IN ACCOUNT] [WHERE ...]`"
2515 | #kill_stmt : "`KILL (QUERY | CONNECTION) <object_id>`"
2516 | #vacuum_temp_files : "VACUUM TEMPORARY FILES [RETAIN number SECONDS|DAYS] [LIMIT number]"
2517 | #set_priority: "`SET PRIORITY (HIGH | MEDIUM | LOW) <object_id>`"
2518 | #system_action: "`SYSTEM (ENABLE | DISABLE) EXCEPTION_BACKTRACE`"
2519 ),
2520 rule!(
2522 #use_catalog: "`USE CATALOG <catalog>`"
2523 | #use_warehouse: "`USE WAREHOUSE <warehouse>`"
2524 | #use_database : "`USE <database>`"
2525 ),
2526 rule!(
2528 #show_warehouses: "`SHOW WAREHOUSES`"
2529 | #show_online_nodes: "`SHOW ONLINE NODES`"
2530 | #create_warehouse: "`CREATE WAREHOUSE <warehouse> [(ASSIGN <node_size> NODES [FROM <node_group>] [, ...])] WITH [warehouse_size = <warehouse_size>]`"
2531 | #drop_warehouse: "`DROP WAREHOUSE <warehouse>`"
2532 | #rename_warehouse: "`RENAME WAREHOUSE <warehouse> TO <new_warehouse>`"
2533 | #resume_warehouse: "`RESUME WAREHOUSE <warehouse>`"
2534 | #suspend_warehouse: "`SUSPEND WAREHOUSE <warehouse>`"
2535 | #inspect_warehouse: "`INSPECT WAREHOUSE <warehouse>`"
2536 | #add_warehouse_cluster: "`ALTER WAREHOUSE <warehouse> ADD CLUSTER <cluster> [(ASSIGN <node_size> NODES [FROM <node_group>] [, ...])] WITH [cluster_size = <cluster_size>]`"
2537 | #drop_warehouse_cluster: "`ALTER WAREHOUSE <warehouse> DROP CLUSTER <cluster>`"
2538 | #rename_warehouse_cluster: "`ALTER WAREHOUSE <warehouse> RENAME CLUSTER <cluster> TO <new_cluster>`"
2539 | #assign_warehouse_nodes: "`ALTER WAREHOUSE <warehouse> ASSIGN NODES ( ASSIGN <node_size> NODES [FROM <node_group>] FOR <cluster> [, ...] )`"
2540 | #unassign_warehouse_nodes: "`ALTER WAREHOUSE <warehouse> UNASSIGN NODES ( UNASSIGN <node_size> NODES [FROM <node_group>] FOR <cluster> [, ...] )`"
2541 ),
2542 rule!(
2544 #show_workload_groups: "`SHOW WORKLOAD GROUPS`"
2545 | #create_workload_group: "`CREATE WORKLOAD GROUP [IF NOT EXISTS] <name> WITH [<workload_group_quotas>]`"
2546 | #drop_workload_group: "`DROP WORKLOAD GROUP [IF EXISTS] <name>`"
2547 | #rename_workload_group: "`RENAME WORKLOAD GROUP <old_name> TO <new_name>`"
2548 | #set_workload_group_quotas: "`ALTER WORKLOAD GROUP <name> SET [<workload_group_quotas>]`"
2549 | #unset_workload_group_quotas: "`ALTER WORKLOAD GROUP <name> UNSET {<name> | (<name>, ...)}`"
2550 ),
2551 rule!(
2553 #show_databases : "`SHOW [FULL] DATABASES [(FROM | IN) <catalog>] [<show_limit>]`"
2554 | #undrop_database : "`UNDROP DATABASE <database>`"
2555 | #show_create_database : "`SHOW CREATE DATABASE <database>`"
2556 | #show_drop_databases : "`SHOW DROP DATABASES [FROM <database>] [<show_limit>]`"
2557 | #create_database : "`CREATE [OR REPLACE] DATABASE [IF NOT EXISTS] <database> [ENGINE = <engine>]`"
2558 | #drop_database : "`DROP DATABASE [IF EXISTS] <database>`"
2559 | #alter_database : "`ALTER DATABASE [IF EXISTS] <action>`"
2560 ),
2561 rule!(
2563 #create_network_policy: "`CREATE NETWORK POLICY [IF NOT EXISTS] name ALLOWED_IP_LIST = ('ip1' [, 'ip2']) [BLOCKED_IP_LIST = ('ip1' [, 'ip2'])] [COMMENT = '<string_literal>']`"
2564 | #alter_network_policy: "`ALTER NETWORK POLICY [IF EXISTS] name SET [ALLOWED_IP_LIST = ('ip1' [, 'ip2'])] [BLOCKED_IP_LIST = ('ip1' [, 'ip2'])] [COMMENT = '<string_literal>']`"
2565 | #drop_network_policy: "`DROP NETWORK POLICY [IF EXISTS] name`"
2566 | #describe_network_policy: "`DESC NETWORK POLICY name`"
2567 | #show_network_policies: "`SHOW NETWORK POLICIES`"
2568 | #create_password_policy: "`CREATE PASSWORD POLICY [IF NOT EXISTS] name [PASSWORD_MIN_LENGTH = <u64_literal>] ... [COMMENT = '<string_literal>']`"
2569 | #alter_password_policy: "`ALTER PASSWORD POLICY [IF EXISTS] name SET [PASSWORD_MIN_LENGTH = <u64_literal>] ... [COMMENT = '<string_literal>']`"
2570 | #drop_password_policy: "`DROP PASSWORD POLICY [IF EXISTS] name`"
2571 | #describe_password_policy: "`DESC PASSWORD POLICY name`"
2572 | #show_password_policies: "`SHOW PASSWORD POLICIES [<show_options>]`"
2573 ),
2574 rule!(
2575 #conditional_multi_table_insert() : "`INSERT [OVERWRITE] {FIRST|ALL} { WHEN <condition> THEN intoClause [ ... ] } [ ... ] [ ELSE intoClause ] <subquery>`"
2576 | #unconditional_multi_table_insert() : "`INSERT [OVERWRITE] ALL intoClause [ ... ] <subquery>`"
2577 | #insert_stmt(false, false) : "`INSERT INTO [TABLE] <table> [(<column>, ...)] (VALUES <values> | <query>)`"
2578 | #replace_stmt(false) : "`REPLACE INTO [TABLE] <table> [(<column>, ...)] (FORMAT <format> | VALUES <values> | <query>)`"
2579 | #merge : "`MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]`"
2580 | #delete : "`DELETE FROM <table> [WHERE ...]`"
2581 | #update : "`UPDATE <table> SET <column> = <expr> [, <column> = <expr> , ... ] [WHERE ...]`"
2582 | #begin
2583 | #commit
2584 | #abort
2585 ),
2586 rule!(
2587 #show_users : "`SHOW USERS`"
2588 | #describe_user: "`DESCRIBE USER <user_name>`"
2589 | #create_user : "`CREATE [OR REPLACE] USER [IF NOT EXISTS] '<username>' IDENTIFIED [WITH <auth_type>] [BY <password>] [WITH <user_option>, ...]`"
2590 | #alter_user : "`ALTER USER ('<username>' | USER()) [IDENTIFIED [WITH <auth_type>] [BY <password>]] [WITH <user_option>, ...]`"
2591 | #drop_user : "`DROP USER [IF EXISTS] '<username>'`"
2592 | #show_roles : "`SHOW ROLES`"
2593 | #create_role : "`CREATE ROLE [IF NOT EXISTS] <role_name>`"
2594 | #drop_role : "`DROP ROLE [IF EXISTS] <role_name>`"
2595 | #create_udf : "`CREATE [OR REPLACE] FUNCTION [IF NOT EXISTS] <udf_name> <udf_definition> [DESC = <description>]`"
2596 | #drop_udf : "`DROP FUNCTION [IF EXISTS] <udf_name>`"
2597 | #alter_udf : "`ALTER FUNCTION <udf_name> <udf_definition> [DESC = <description>]`"
2598 | #set_role: "`SET [DEFAULT] ROLE <role>`"
2599 | #set_secondary_roles: "`SET SECONDARY ROLES (ALL | NONE)`"
2600 | #set_secondary_specify_roles: "`SET SECONDARY ROLES [role_name,...]`"
2601 | #show_user_functions : "`SHOW USER FUNCTIONS [<show_limit>]`"
2602 ),
2603 rule!(
2604 #show_tables : "`SHOW [FULL] TABLES [FROM <database>] [<show_limit>]`"
2605 | #show_columns : "`SHOW [FULL] COLUMNS FROM <table> [FROM|IN <catalog>.<database>] [<show_limit>]`"
2606 | #show_create_table : "`SHOW CREATE TABLE [<database>.]<table>`"
2607 | #describe_view : "`DESCRIBE VIEW [<database>.]<view>`"
2608 | #describe_table : "`DESCRIBE [<database>.]<table>`"
2609 | #show_fields : "`SHOW FIELDS FROM [<database>.]<table>`"
2610 | #show_tables_status : "`SHOW TABLES STATUS [FROM <database>] [<show_limit>]`"
2611 | #show_drop_tables_status : "`SHOW DROP TABLES [FROM <database>]`"
2612 | #attach_table : "`ATTACH TABLE [<database>.]<table> <uri>`"
2613 | #create_table : "`CREATE [OR REPLACE] TABLE [IF NOT EXISTS] [<database>.]<table> [<source>] [<table_options>]`"
2614 | #drop_table : "`DROP TABLE [IF EXISTS] [<database>.]<table>`"
2615 | #undrop_table : "`UNDROP TABLE [<database>.]<table>`"
2616 | #alter_table : "`ALTER TABLE [<database>.]<table> <action>`"
2617 | #rename_table : "`RENAME TABLE [<database>.]<table> TO <new_table>`"
2618 | #truncate_table : "`TRUNCATE TABLE [<database>.]<table>`"
2619 | #optimize_table : "`OPTIMIZE TABLE [<database>.]<table> (ALL | PURGE | COMPACT [SEGMENT])`"
2620 | #vacuum_table : "`VACUUM TABLE [<database>.]<table> [RETAIN number HOURS] [DRY RUN | DRY RUN SUMMARY]`"
2621 | #vacuum_drop_table : "`VACUUM DROP TABLE [FROM [<catalog>.]<database>] [RETAIN number HOURS] [DRY RUN | DRY RUN SUMMARY]`"
2622 | #analyze_table : "`ANALYZE TABLE [<database>.]<table>`"
2623 | #exists_table : "`EXISTS TABLE [<database>.]<table>`"
2624 | #show_table_functions : "`SHOW TABLE_FUNCTIONS [<show_limit>]`"
2625 ),
2626 rule!(
2628 #create_dictionary : "`CREATE [OR REPLACE] DICTIONARY [IF NOT EXISTS] <dictionary_name> [(<column>, ...)] PRIMARY KEY [<primary_key>, ...] SOURCE (<source_name> ([<source_options>])) [COMMENT <comment>] `"
2629 | #drop_dictionary : "`DROP DICTIONARY [IF EXISTS] <dictionary_name>`"
2630 | #show_create_dictionary : "`SHOW CREATE DICTIONARY <dictionary_name> `"
2631 | #show_dictionaries : "`SHOW DICTIONARIES [<show_option>, ...]`"
2632 | #rename_dictionary: "`RENAME DICTIONARY [<database>.]<old_dict_name> TO <new_dict_name>`"
2633 ),
2634 rule!(
2636 #create_view : "`CREATE [OR REPLACE] VIEW [IF NOT EXISTS] [<database>.]<view> [(<column>, ...)] AS SELECT ...`"
2637 | #drop_view : "`DROP VIEW [IF EXISTS] [<database>.]<view>`"
2638 | #alter_view : "`ALTER VIEW [<database>.]<view> [(<column>, ...)] AS SELECT ...`"
2639 | #show_views : "`SHOW [FULL] VIEWS [FROM <database>] [<show_limit>]`"
2640 | #create_index: "`CREATE [OR REPLACE] AGGREGATING INDEX [IF NOT EXISTS] <index> AS SELECT ...`"
2641 | #drop_index: "`DROP <index_type> INDEX [IF EXISTS] <index>`"
2642 | #refresh_index: "`REFRESH <index_type> INDEX <index> [LIMIT <limit>]`"
2643 | #create_table_index: "`CREATE [OR REPLACE] <index_type> INDEX [IF NOT EXISTS] <index> ON [<database>.]<table>(<column>, ...)`"
2644 | #drop_table_index: "`DROP <index_type> INDEX [IF EXISTS] <index> ON [<database>.]<table>`"
2645 | #refresh_table_index: "`REFRESH <index_type> INDEX <index> ON [<database>.]<table> [LIMIT <limit>]`"
2646 | #refresh_virtual_column: "`REFRESH VIRTUAL COLUMN FOR [<database>.]<table>`"
2647 | #show_virtual_columns : "`SHOW VIRTUAL COLUMNS FROM <table> [FROM|IN <catalog>.<database>] [<show_limit>]`"
2648 | #sequence
2649 ),
2650 rule!(
2651 #create_stage: "`CREATE [OR REPLACE] STAGE [ IF NOT EXISTS ] <stage_name>
2652 [ FILE_FORMAT = ( { TYPE = { CSV | PARQUET } [ formatTypeOptions ] ) } ]
2653 [ COPY_OPTIONS = ( copyOptions ) ]
2654 [ COMMENT = '<string_literal>' ]`"
2655 | #desc_stage: "`DESC STAGE <stage_name>`"
2656 | #list_stage: "`LIST @<stage_name> [pattern = '<pattern>']`"
2657 | #remove_stage: "`REMOVE @<stage_name> [pattern = '<pattern>']`"
2658 | #drop_stage: "`DROP STAGE <stage_name>`"
2659 | #create_file_format: "`CREATE FILE FORMAT [ IF NOT EXISTS ] <format_name> formatTypeOptions`"
2660 | #show_file_formats: "`SHOW FILE FORMATS`"
2661 | #drop_file_format: "`DROP FILE FORMAT [ IF EXISTS ] <format_name>`"
2662 | #copy_into
2663 | #call: "`CALL <procedure_name>(<parameter>, ...)`"
2664 | #grant : "`GRANT { ROLE <role_name> | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON <privileges_level> } TO { [ROLE <role_name>] | [USER] <user> }`"
2665 | #show_grants : "`SHOW GRANTS {FOR { ROLE <role_name> | USER <user> }] | ON {DATABASE <db_name> | TABLE <db_name>.<table_name>} }`"
2666 | #revoke : "`REVOKE { ROLE <role_name> | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON <privileges_level> } FROM { [ROLE <role_name>] | [USER] <user> }`"
2667 | #grant_ownership : "GRANT OWNERSHIP ON <privileges_level> TO ROLE <role_name>"
2668 | #presign: "`PRESIGN [{DOWNLOAD | UPLOAD}] <location> [EXPIRE = 3600]`"
2669 ),
2670 rule!(
2672 #create_data_mask_policy: "`CREATE MASKING POLICY [IF NOT EXISTS] mask_name as (val1 val_type1 [, val type]) return type -> case`"
2673 | #drop_data_mask_policy: "`DROP MASKING POLICY [IF EXISTS] mask_name`"
2674 | #describe_data_mask_policy: "`DESC MASKING POLICY mask_name`"
2675 ),
2676 rule!(
2677 #set_stmt : "`SET [variable] {<name> = <value> | (<name>, ...) = (<value>, ...)}`"
2678 | #unset_stmt : "`UNSET [variable] {<name> | (<name>, ...)}`"
2679 | #query_setting : "SETTINGS ( {<name> = <value> | (<name>, ...) = (<value>, ...)} ) Statement"
2680 ),
2681 rule!(
2683 #show_catalogs : "`SHOW CATALOGS [<show_limit>]`"
2684 | #show_create_catalog : "`SHOW CREATE CATALOG <catalog>`"
2685 | #create_catalog: "`CREATE CATALOG [IF NOT EXISTS] <catalog> TYPE=<catalog_type> CONNECTION=<catalog_options>`"
2686 | #drop_catalog: "`DROP CATALOG [IF EXISTS] <catalog>`"
2687 ),
2688 rule!(
2689 #create_task : "`CREATE TASK [ IF NOT EXISTS ] <name>
2690 [ { WAREHOUSE = <string> } ]
2691 [ SCHEDULE = { <num> MINUTE | USING CRON <expr> <time_zone> } ]
2692 [ AFTER <string>, <string>...]
2693 [ WHEN boolean_expr ]
2694 [ SUSPEND_TASK_AFTER_NUM_FAILURES = <num> ]
2695 [ ERROR_INTEGRATION = <string_literal> ]
2696 [ COMMENT = '<string_literal>' ]
2697AS
2698 <sql>`"
2699 | #drop_task : "`DROP TASK [ IF EXISTS ] <name>`"
2700 | #alter_task : "`ALTER TASK [ IF EXISTS ] <name> SUSPEND | RESUME | SET <option> = <value>` | UNSET <option> | MODIFY AS <sql> | MODIFY WHEN <boolean_expr> | ADD/REMOVE AFTER <string>, <string>...`"
2701 | #show_tasks : "`SHOW TASKS [<show_limit>]`"
2702 | #desc_task : "`DESC | DESCRIBE TASK <name>`"
2703 | #execute_task: "`EXECUTE TASK <name>`"
2704 ),
2705 rule!(
2707 #stream_table
2708 | #dynamic_table
2709 ),
2710 rule!(
2711 #create_pipe : "`CREATE PIPE [ IF NOT EXISTS ] <name>
2712 [ AUTO_INGEST = [ TRUE | FALSE ] ]
2713 [ COMMENT = '<string_literal>' ]
2714AS
2715 <copy_sql>`"
2716 | #drop_pipe : "`DROP PIPE [ IF EXISTS ] <name>`"
2717 | #alter_pipe : "`ALTER PIPE [ IF EXISTS ] <name> SET <option> = <value>` | REFRESH <option> = <value>`"
2718 | #desc_pipe : "`DESC | DESCRIBE PIPE <name>`"
2719 | #create_notification : "`CREATE NOTIFICATION INTEGRATION [ IF NOT EXISTS ] <name>
2720 TYPE = <type>
2721 ENABLED = <bool>
2722 [ WEBHOOK = ( url = <string_literal>, method = <string_literal>, authorization_header = <string_literal> ) ]
2723 [ COMMENT = '<string_literal>' ]`"
2724 | #alter_notification : "`ALTER NOTIFICATION INTEGRATION [ IF EXISTS ] <name> SET <option> = <value>`"
2725 | #desc_notification : "`DESC | DESCRIBE NOTIFICATION INTEGRATION <name>`"
2726 | #drop_notification : "`DROP NOTIFICATION INTEGRATION [ IF EXISTS ] <name>`"
2727 ),
2728 rule!(
2729 #create_connection: "`CREATE [OR REPLACE] CONNECTION [IF NOT EXISTS] <connection_name> STORAGE_TYPE = <type> <storage_configs>`"
2730 | #drop_connection: "`DROP CONNECTION [IF EXISTS] <connection_name>`"
2731 | #desc_connection: "`DESC | DESCRIBE CONNECTION <connection_name>`"
2732 | #show_connections: "`SHOW CONNECTIONS`"
2733 | #execute_immediate : "`EXECUTE IMMEDIATE $$ <script> $$`"
2734 | #create_procedure : "`CREATE [ OR REPLACE ] PROCEDURE <procedure_name>() RETURNS { <result_data_type> [ NOT NULL ] | TABLE(<var_name> <data_type>, ...)} LANGUAGE SQL [ COMMENT = '<string_literal>' ] AS <procedure_definition>`"
2735 | #drop_procedure : "`DROP PROCEDURE <procedure_name>()`"
2736 | #show_procedures : "`SHOW PROCEDURES [<show_options>]()`"
2737 | #describe_procedure : "`DESC PROCEDURE <procedure_name>()`"
2738 | #call_procedure : "`CALL PROCEDURE <procedure_name>()`"
2739 ),
2740 rule!(#comment),
2741 rule!(#vacuum_temporary_tables),
2742 ))(i)
2743}
2744
2745pub fn statement(i: Input) -> IResult<StatementWithFormat> {
2746 map(
2747 rule! {
2748 #statement_body ~ ( FORMAT ~ ^#ident )? ~ ";"? ~ &EOI
2749 },
2750 |(stmt, opt_format, _, _)| StatementWithFormat {
2751 stmt,
2752 format: opt_format.map(|(_, format)| format.name),
2753 },
2754 )(i)
2755}
2756
2757pub fn parse_create_option(
2758 opt_or_replace: bool,
2759 opt_if_not_exists: bool,
2760) -> Result<CreateOption, nom::Err<ErrorKind>> {
2761 match (opt_or_replace, opt_if_not_exists) {
2762 (false, false) => Ok(CreateOption::Create),
2763 (true, false) => Ok(CreateOption::CreateOrReplace),
2764 (false, true) => Ok(CreateOption::CreateIfNotExists),
2765 (true, true) => Err(nom::Err::Failure(ErrorKind::Other(
2766 "option IF NOT EXISTS and OR REPLACE are incompatible.",
2767 ))),
2768 }
2769}
2770
2771pub fn insert_stmt(
2772 allow_raw: bool,
2773 in_streaming_load: bool,
2774) -> impl FnMut(Input) -> IResult<Statement> {
2775 move |i| {
2776 let insert_source_parser = if in_streaming_load {
2777 insert_source_file
2778 } else if allow_raw {
2779 insert_source_fast_values
2780 } else {
2781 insert_source
2782 };
2783 map_res(
2784 rule! {
2785 #with? ~ INSERT ~ #hint? ~ OVERWRITE? ~ INTO? ~ TABLE?
2786 ~ #dot_separated_idents_1_to_3
2787 ~ ( "(" ~ #comma_separated_list1(ident) ~ ")" )?
2788 ~ #insert_source_parser
2789 },
2790 |(
2791 with,
2792 _,
2793 opt_hints,
2794 overwrite,
2795 into,
2796 _,
2797 (catalog, database, table),
2798 opt_columns,
2799 source,
2800 )| {
2801 if overwrite.is_none() && into.is_none() {
2802 return Err(nom::Err::Failure(ErrorKind::Other(
2803 "INSERT statement must be followed by 'overwrite' or 'into'",
2804 )));
2805 }
2806 Ok(Statement::Insert(InsertStmt {
2807 hints: opt_hints,
2808 with,
2809 catalog,
2810 database,
2811 table,
2812 columns: opt_columns
2813 .map(|(_, columns, _)| columns)
2814 .unwrap_or_default(),
2815 source,
2816 overwrite: overwrite.is_some(),
2817 }))
2818 },
2819 )(i)
2820 }
2821}
2822
2823pub fn conditional_multi_table_insert() -> impl FnMut(Input) -> IResult<Statement> {
2824 move |i| {
2825 map(
2826 rule! {
2827 INSERT ~ OVERWRITE? ~ (FIRST | ALL) ~ (#when_clause)+ ~ (#else_clause)? ~ #query
2828 },
2829 |(_, overwrite, kind, when_clauses, opt_else, source)| {
2830 Statement::InsertMultiTable(InsertMultiTableStmt {
2831 overwrite: overwrite.is_some(),
2832 is_first: matches!(kind.kind, FIRST),
2833 when_clauses,
2834 else_clause: opt_else,
2835 into_clauses: vec![],
2836 source,
2837 })
2838 },
2839 )(i)
2840 }
2841}
2842
2843pub fn unconditional_multi_table_insert() -> impl FnMut(Input) -> IResult<Statement> {
2844 move |i| {
2845 map(
2846 rule! {
2847 INSERT ~ OVERWRITE? ~ ALL ~ (#into_clause)+ ~ #query
2848 },
2849 |(_, overwrite, _, into_clauses, source)| {
2850 Statement::InsertMultiTable(InsertMultiTableStmt {
2851 overwrite: overwrite.is_some(),
2852 is_first: false,
2853 when_clauses: vec![],
2854 else_clause: None,
2855 into_clauses,
2856 source,
2857 })
2858 },
2859 )(i)
2860 }
2861}
2862
2863fn when_clause(i: Input) -> IResult<WhenClause> {
2864 map(
2865 rule! {
2866 WHEN ~ ^#expr ~ THEN ~ (#into_clause)+
2867 },
2868 |(_, expr, _, into_clauses)| WhenClause {
2869 condition: expr,
2870 into_clauses,
2871 },
2872 )(i)
2873}
2874
2875fn into_clause(i: Input) -> IResult<IntoClause> {
2876 let source_expr = alt((
2877 map(rule! {DEFAULT}, |_| SourceExpr::Default),
2878 map(rule! { #expr }, SourceExpr::Expr),
2879 ));
2880 map(
2881 rule! {
2882 INTO
2883 ~ #dot_separated_idents_1_to_3
2884 ~ ( "(" ~ #comma_separated_list1(ident) ~ ")" )?
2885 ~ (VALUES ~ "(" ~ #comma_separated_list1(source_expr) ~ ")" )?
2886 },
2887 |(_, (catalog, database, table), opt_target_columns, opt_source_columns)| IntoClause {
2888 catalog,
2889 database,
2890 table,
2891 target_columns: opt_target_columns
2892 .map(|(_, columns, _)| columns)
2893 .unwrap_or_default(),
2894 source_columns: opt_source_columns
2895 .map(|(_, _, columns, _)| columns)
2896 .unwrap_or_default(),
2897 },
2898 )(i)
2899}
2900
2901fn else_clause(i: Input) -> IResult<ElseClause> {
2902 map(
2903 rule! {
2904 ELSE ~ (#into_clause)+
2905 },
2906 |(_, into_clauses)| ElseClause { into_clauses },
2907 )(i)
2908}
2909
2910pub fn replace_stmt(allow_raw: bool) -> impl FnMut(Input) -> IResult<Statement> {
2911 move |i| {
2912 let insert_source_parser = if allow_raw {
2913 insert_source_fast_values
2914 } else {
2915 insert_source
2916 };
2917 map(
2918 rule! {
2919 REPLACE ~ #hint? ~ INTO?
2920 ~ #dot_separated_idents_1_to_3
2921 ~ ( "(" ~ #comma_separated_list1(ident) ~ ")" )?
2922 ~ ON ~ CONFLICT? ~ "(" ~ #comma_separated_list1(ident) ~ ")"
2923 ~ ( DELETE ~ WHEN ~ ^#expr )?
2924 ~ #insert_source_parser
2925 },
2926 |(
2927 _,
2928 opt_hints,
2929 _,
2930 (catalog, database, table),
2931 opt_columns,
2932 _,
2933 opt_conflict,
2934 _,
2935 on_conflict_columns,
2936 _,
2937 opt_delete_when,
2938 source,
2939 )| {
2940 Statement::Replace(ReplaceStmt {
2941 hints: opt_hints,
2942 catalog,
2943 database,
2944 table,
2945 is_conflict: opt_conflict.is_some(),
2946 on_conflict_columns,
2947 columns: opt_columns
2948 .map(|(_, columns, _)| columns)
2949 .unwrap_or_default(),
2950 source,
2951 delete_when: opt_delete_when.map(|(_, _, expr)| expr),
2952 })
2953 },
2954 )(i)
2955 }
2956}
2957
2958pub fn insert_source(i: Input) -> IResult<InsertSource> {
2960 let row = map(
2961 rule! {
2962 "(" ~ #comma_separated_list1(expr) ~ ")"
2963 },
2964 |(_, values, _)| values,
2965 );
2966 let values = map(
2967 rule! {
2968 VALUES ~ #comma_separated_list0(row)
2969 },
2970 |(_, rows)| InsertSource::Values { rows },
2971 );
2972
2973 let query = map(query, |query| InsertSource::Select {
2974 query: Box::new(query),
2975 });
2976
2977 rule!(
2978 #values
2979 | #query
2980 )(i)
2981}
2982
2983pub fn insert_source_file(i: Input) -> IResult<InsertSource> {
2984 let value = map(
2985 rule! {
2986 "(" ~ #comma_separated_list1(expr) ~ ")"
2987 },
2988 |(_, values, _)| values,
2989 );
2990 map(
2991 rule! {
2992 (VALUES ~ #value?)? ~ FROM ~ #at_string ~ #file_format_clause ~ ";"? ~ &EOI
2993 },
2994 |(values, _, location, format_options, _, _)| InsertSource::LoadFile {
2995 value: values.map(|(_, value)| value).unwrap_or_default(),
2996 location,
2997 format_options,
2998 },
2999 )(i)
3000}
3001
3002pub fn insert_source_fast_values(i: Input) -> IResult<InsertSource> {
3007 let values = map(
3008 rule! {
3009 VALUES ~ #rest_str
3010 },
3011 |(_, (rest_str, start))| InsertSource::RawValues { rest_str, start },
3012 );
3013 let query = map(
3014 rule! {
3015 #query ~ ";"? ~ &EOI
3016 },
3017 |(query, _, _)| InsertSource::Select {
3018 query: Box::new(query),
3019 },
3020 );
3021
3022 rule!(
3023 #insert_source_file |
3024 #values
3025 | #query
3026 )(i)
3027}
3028
3029pub fn mutation_source(i: Input) -> IResult<MutationSource> {
3030 let query = map(rule! {#query ~ #table_alias}, |(query, source_alias)| {
3031 MutationSource::Select {
3032 query: Box::new(query),
3033 source_alias,
3034 }
3035 });
3036
3037 let source_table = map(
3038 rule!(#dot_separated_idents_1_to_3 ~ #with_options? ~ #table_alias?),
3039 |((catalog, database, table), with_options, alias)| MutationSource::Table {
3040 catalog,
3041 database,
3042 table,
3043 with_options,
3044 alias,
3045 },
3046 );
3047
3048 rule!(
3049 #query
3050 | #source_table
3051 )(i)
3052}
3053
3054pub fn unset_source(i: Input) -> IResult<Vec<Identifier>> {
3055 let var = map(
3057 rule! {
3058 #ident
3059 },
3060 |variable| vec![variable],
3061 );
3062 let vars = map(
3063 rule! {
3064 "(" ~ ^#comma_separated_list1(ident) ~ ")"
3065 },
3066 |(_, variables, _)| variables,
3067 );
3068
3069 rule!(
3070 #var
3071 | #vars
3072 )(i)
3073}
3074
3075pub fn set_stmt_args(i: Input) -> IResult<(Identifier, Box<Expr>)> {
3076 map(
3077 rule! {
3078 #ident ~ "=" ~ #subexpr(0)
3079 },
3080 |(id, _, expr)| (id, Box::new(expr)),
3081 )(i)
3082}
3083
3084pub fn set_var_hints(i: Input) -> IResult<HintItem> {
3085 map(
3086 rule! {
3087 SET_VAR ~ ^"(" ~ ^#ident ~ ^"=" ~ #subexpr(0) ~ ^")"
3088 },
3089 |(_, _, name, _, expr, _)| HintItem { name, expr },
3090 )(i)
3091}
3092
3093pub fn hint(i: Input) -> IResult<Hint> {
3094 let hint = map(
3095 rule! {
3096 "/*+" ~ #set_var_hints+ ~ "*/"
3097 },
3098 |(_, hints_list, _)| Hint { hints_list },
3099 );
3100 let invalid_hint = map(
3101 rule! {
3102 "/*+" ~ (!"*/" ~ #any_token)* ~ "*/"
3103 },
3104 |_| Hint { hints_list: vec![] },
3105 );
3106 rule!(#hint|#invalid_hint)(i)
3107}
3108
3109pub fn query_setting(i: Input) -> IResult<(Identifier, Expr)> {
3110 map(
3111 rule! {
3112 #ident ~ "=" ~ #subexpr(0)
3113 },
3114 |(id, _, value)| (id, value),
3115 )(i)
3116}
3117
3118pub fn query_statement_setting(i: Input) -> IResult<Settings> {
3119 let query_set = map(
3120 rule! {
3121 "(" ~ #comma_separated_list0(query_setting) ~ ")"
3122 },
3123 |(_, query_setting, _)| {
3124 let mut ids = Vec::with_capacity(query_setting.len());
3125 let mut values = Vec::with_capacity(query_setting.len());
3126 for (id, value) in query_setting {
3127 ids.push(id);
3128 values.push(value);
3129 }
3130 Settings {
3131 set_type: SetType::SettingsQuery,
3132 identifiers: ids,
3133 values: SetValues::Expr(values.into_iter().map(|x| x.into()).collect()),
3134 }
3135 },
3136 );
3137 rule!(#query_set: "(SETTING_NAME = VALUE, ...)")(i)
3138}
3139pub fn top_n(i: Input) -> IResult<u64> {
3140 map(
3141 rule! {
3142 TOP
3143 ~ ^#error_hint(
3144 not(literal_u64),
3145 "expecting a literal number after keyword `TOP`, if you were referring to a column with name `top`, \
3146 please quote it like `\"top\"`"
3147 )
3148 ~ ^#literal_u64
3149 : "TOP <limit>"
3150 },
3151 |(_, _, n)| n,
3152 )(i)
3153}
3154
3155pub fn rest_str(i: Input) -> IResult<(String, usize)> {
3156 let first_token = i.tokens.first().unwrap();
3158 let last_token = i.tokens.last().unwrap();
3159 Ok((
3160 i.slice((i.len() - 1)..),
3161 (
3162 first_token.source[first_token.span.start()..last_token.span.end()].to_string(),
3163 first_token.span.start(),
3164 ),
3165 ))
3166}
3167
3168pub fn column_def(i: Input) -> IResult<ColumnDefinition> {
3169 #[derive(Clone)]
3170 enum ColumnConstraint {
3171 Nullable(bool),
3172 DefaultExpr(Box<Expr>),
3173 VirtualExpr(Box<Expr>),
3174 StoredExpr(Box<Expr>),
3175 }
3176
3177 let nullable = alt((
3178 value(ColumnConstraint::Nullable(true), rule! { NULL }),
3179 value(ColumnConstraint::Nullable(false), rule! { NOT ~ ^NULL }),
3180 ));
3181 let expr = alt((
3182 map(
3183 rule! {
3184 DEFAULT ~ ^#subexpr(NOT_PREC)
3185 },
3186 |(_, default_expr)| ColumnConstraint::DefaultExpr(Box::new(default_expr)),
3187 ),
3188 map(
3189 rule! {
3190 (GENERATED ~ ^ALWAYS)? ~ AS ~ ^"(" ~ ^#subexpr(NOT_PREC) ~ ^")" ~ VIRTUAL
3191 },
3192 |(_, _, _, virtual_expr, _, _)| ColumnConstraint::VirtualExpr(Box::new(virtual_expr)),
3193 ),
3194 map(
3195 rule! {
3196 (GENERATED ~ ^ALWAYS)? ~ AS ~ ^"(" ~ ^#subexpr(NOT_PREC) ~ ^")" ~ STORED
3197 },
3198 |(_, _, _, stored_expr, _, _)| ColumnConstraint::StoredExpr(Box::new(stored_expr)),
3199 ),
3200 ));
3201
3202 let comment = map(
3203 rule! {
3204 COMMENT ~ #literal_string
3205 },
3206 |(_, comment)| comment,
3207 );
3208
3209 let (i, (mut def, constraints)) = map(
3210 rule! {
3211 #ident
3212 ~ #type_name
3213 ~ ( #nullable | #expr )*
3214 ~ ( #comment )?
3215 : "`<column name> <type> [DEFAULT <expr>] [AS (<expr>) VIRTUAL] [AS (<expr>) STORED] [COMMENT '<comment>']`"
3216 },
3217 |(name, data_type, constraints, comment)| {
3218 let def = ColumnDefinition {
3219 name,
3220 data_type,
3221 expr: None,
3222 comment,
3223 };
3224 (def, constraints)
3225 },
3226 )(i)?;
3227
3228 for constraint in constraints {
3229 match constraint {
3230 ColumnConstraint::Nullable(nullable) => {
3231 if (nullable && matches!(def.data_type, TypeName::NotNull(_)))
3232 || (!nullable && matches!(def.data_type, TypeName::Nullable(_)))
3233 {
3234 return Err(nom::Err::Error(Error::from_error_kind(
3235 i,
3236 ErrorKind::Other("ambiguous NOT NULL constraint"),
3237 )));
3238 }
3239 if nullable {
3240 def.data_type = def.data_type.wrap_nullable();
3241 } else {
3242 def.data_type = def.data_type.wrap_not_null();
3243 }
3244 }
3245 ColumnConstraint::DefaultExpr(default_expr) => {
3246 def.expr = Some(ColumnExpr::Default(default_expr))
3247 }
3248 ColumnConstraint::VirtualExpr(virtual_expr) => {
3249 def.expr = Some(ColumnExpr::Virtual(virtual_expr))
3250 }
3251 ColumnConstraint::StoredExpr(stored_expr) => {
3252 def.expr = Some(ColumnExpr::Stored(stored_expr))
3253 }
3254 }
3255 }
3256
3257 Ok((i, def))
3258}
3259
3260pub fn table_index_def(i: Input) -> IResult<TableIndexDefinition> {
3261 map_res(
3262 rule! {
3263 ASYNC?
3264 ~ #index_type ~ ^INDEX
3265 ~ #ident
3266 ~ ^"(" ~ ^#comma_separated_list1(ident) ~ ^")"
3267 ~ ( #table_option )?
3268 },
3269 |(opt_async, index_type, _, index_name, _, columns, _, opt_index_options)| {
3270 Ok(TableIndexDefinition {
3271 index_name,
3272 index_type,
3273 columns,
3274 sync_creation: opt_async.is_none(),
3275 index_options: opt_index_options.unwrap_or_default(),
3276 })
3277 },
3278 )(i)
3279}
3280
3281pub fn create_def(i: Input) -> IResult<CreateDefinition> {
3282 alt((
3283 map(rule! { #column_def }, CreateDefinition::Column),
3284 map(rule! { #table_index_def }, CreateDefinition::TableIndex),
3285 ))(i)
3286}
3287
3288pub fn role_name(i: Input) -> IResult<String> {
3289 let role_ident = map_res(
3290 rule! {
3291 #ident
3292 },
3293 |role_name| {
3294 let name = role_name.name;
3295 let mut chars = name.chars();
3296 while let Some(c) = chars.next() {
3297 match c {
3298 '\\' => match chars.next() {
3299 Some('f') | Some('b') => {
3300 return Err(nom::Err::Failure(ErrorKind::Other(
3301 "' or \" or \\f or \\b are not allowed in role name",
3302 )));
3303 }
3304 _ => {}
3305 },
3306 '\'' | '"' => {
3307 return Err(nom::Err::Failure(ErrorKind::Other(
3308 "' or \" or \\f or \\b are not allowed in role name",
3309 )));
3310 }
3311 _ => {}
3312 }
3313 }
3314 Ok(name)
3315 },
3316 );
3317 let role_lit = map(
3318 rule! {
3319 #literal_string
3320 },
3321 |role_name| role_name,
3322 );
3323
3324 rule!(
3325 #role_ident : "<role_name>"
3326 | #role_lit : "'<role_name>'"
3327 )(i)
3328}
3329
3330pub fn grant_source(i: Input) -> IResult<AccountMgrSource> {
3331 let role = map(
3332 rule! {
3333 ROLE ~ #role_name
3334 },
3335 |(_, role_name)| AccountMgrSource::Role { role: role_name },
3336 );
3337 let privs = map(
3338 rule! {
3339 #comma_separated_list1(priv_type) ~ ON ~ #grant_level
3340 },
3341 |(privs, _, level)| AccountMgrSource::Privs {
3342 privileges: privs,
3343 level,
3344 },
3345 );
3346 let all = map(
3347 rule! { ALL ~ PRIVILEGES? ~ ON ~ #grant_all_level },
3348 |(_, _, _, level)| AccountMgrSource::ALL { level },
3349 );
3350
3351 let udf_privs = map(
3352 rule! {
3353 USAGE ~ ON ~ UDF ~ #ident
3354 },
3355 |(_, _, _, udf)| AccountMgrSource::Privs {
3356 privileges: vec![UserPrivilegeType::Usage],
3357 level: AccountMgrLevel::UDF(udf.to_string()),
3358 },
3359 );
3360
3361 let udf_all_privs = map(
3362 rule! {
3363 ALL ~ PRIVILEGES? ~ ON ~ UDF ~ #ident
3364 },
3365 |(_, _, _, _, udf)| AccountMgrSource::Privs {
3366 privileges: vec![UserPrivilegeType::Usage],
3367 level: AccountMgrLevel::UDF(udf.to_string()),
3368 },
3369 );
3370
3371 let stage_privs = map(
3372 rule! {
3373 #comma_separated_list1(stage_priv_type) ~ ON ~ STAGE ~ #ident
3374 },
3375 |(privileges, _, _, stage_name)| AccountMgrSource::Privs {
3376 privileges,
3377 level: AccountMgrLevel::Stage(stage_name.to_string()),
3378 },
3379 );
3380
3381 let warehouse_privs = map(
3382 rule! {
3383 USAGE ~ ON ~ WAREHOUSE ~ #ident
3384 },
3385 |(_, _, _, w)| AccountMgrSource::Privs {
3386 privileges: vec![UserPrivilegeType::Usage],
3387 level: AccountMgrLevel::Warehouse(w.to_string()),
3388 },
3389 );
3390
3391 let warehouse_all_privs = map(
3392 rule! {
3393 ALL ~ PRIVILEGES? ~ ON ~ WAREHOUSE ~ #ident
3394 },
3395 |(_, _, _, _, w)| AccountMgrSource::Privs {
3396 privileges: vec![UserPrivilegeType::Usage],
3397 level: AccountMgrLevel::Warehouse(w.to_string()),
3398 },
3399 );
3400
3401 let connection_privs = map(
3402 rule! {
3403 ACCESS ~ CONNECTION ~ ON ~ CONNECTION ~ #ident
3404 },
3405 |(_, _, _, _, c)| AccountMgrSource::Privs {
3406 privileges: vec![UserPrivilegeType::AccessConnection],
3407 level: AccountMgrLevel::Connection(c.to_string()),
3408 },
3409 );
3410
3411 let connection_all_privs = map(
3412 rule! {
3413 ALL ~ PRIVILEGES? ~ ON ~ CONNECTION ~ #ident
3414 },
3415 |(_, _, _, _, w)| AccountMgrSource::Privs {
3416 privileges: vec![UserPrivilegeType::AccessConnection],
3417 level: AccountMgrLevel::Connection(w.to_string()),
3418 },
3419 );
3420
3421 let seq_privs = map(
3422 rule! {
3423 ACCESS ~ SEQUENCE ~ ON ~ SEQUENCE ~ #ident
3424 },
3425 |(_, _, _, _, c)| AccountMgrSource::Privs {
3426 privileges: vec![UserPrivilegeType::AccessSequence],
3427 level: AccountMgrLevel::Sequence(c.to_string()),
3428 },
3429 );
3430
3431 let seq_all_privs = map(
3432 rule! {
3433 ALL ~ PRIVILEGES? ~ ON ~ SEQUENCE ~ #ident
3434 },
3435 |(_, _, _, _, w)| AccountMgrSource::Privs {
3436 privileges: vec![UserPrivilegeType::AccessSequence],
3437 level: AccountMgrLevel::Sequence(w.to_string()),
3438 },
3439 );
3440
3441 rule!(
3442 #role : "ROLE <role_name>"
3443 | #warehouse_all_privs: "ALL [ PRIVILEGES ] ON WAREHOUSE <warehouse_name>"
3444 | #connection_all_privs: "ALL [ PRIVILEGES ] ON CONNECTION <connection_name>"
3445 | #seq_all_privs: "ALL [ PRIVILEGES ] ON SEQUENCE <seq_name>"
3446 | #udf_privs: "USAGE ON UDF <udf_name>"
3447 | #warehouse_privs: "USAGE ON WAREHOUSE <warehouse_name>"
3448 | #connection_privs: "ACCESS CONNECTION ON CONNECTION <connection_name>"
3449 | #seq_privs: "ACCESS SEQUENCE ON CONNECTION <seq_name>"
3450 | #privs : "<privileges> ON <privileges_level>"
3451 | #stage_privs : "<stage_privileges> ON STAGE <stage_name>"
3452 | #udf_all_privs: "ALL [ PRIVILEGES ] ON UDF <udf_name>"
3453 | #all : "ALL [ PRIVILEGES ] ON <privileges_level>"
3454 )(i)
3455}
3456
3457pub fn priv_type(i: Input) -> IResult<UserPrivilegeType> {
3458 let usage = value(UserPrivilegeType::Usage, rule! { USAGE });
3459 let select = value(UserPrivilegeType::Select, rule! { SELECT });
3460 let insert = value(UserPrivilegeType::Insert, rule! { INSERT });
3461 let update = value(UserPrivilegeType::Update, rule! { UPDATE });
3462 let delete = value(UserPrivilegeType::Delete, rule! { DELETE });
3463 let alter = value(UserPrivilegeType::Alter, rule! { ALTER });
3464 let super_priv = value(UserPrivilegeType::Super, rule! { SUPER });
3465 let create_user = value(UserPrivilegeType::CreateUser, rule! { CREATE ~ USER });
3466 let create_database = value(
3467 UserPrivilegeType::CreateDatabase,
3468 rule! { CREATE ~ DATABASE },
3469 );
3470 let create_warehouse = value(
3471 UserPrivilegeType::CreateWarehouse,
3472 rule! { CREATE ~ WAREHOUSE },
3473 );
3474 let create_connection = value(
3475 UserPrivilegeType::CreateConnection,
3476 rule! { CREATE ~ CONNECTION },
3477 );
3478 let access_sequence = value(
3479 UserPrivilegeType::AccessConnection,
3480 rule! { ACCESS ~ CONNECTION },
3481 );
3482 let create_sequence = value(
3483 UserPrivilegeType::CreateSequence,
3484 rule! { CREATE ~ SEQUENCE },
3485 );
3486 let access_connection = value(
3487 UserPrivilegeType::AccessSequence,
3488 rule! { ACCESS ~ SEQUENCE },
3489 );
3490 let drop_user = value(UserPrivilegeType::DropUser, rule! { DROP ~ USER });
3491 let create_role = value(UserPrivilegeType::CreateRole, rule! { CREATE ~ ROLE });
3492 let drop_role = value(UserPrivilegeType::DropRole, rule! { DROP ~ ROLE });
3493 let grant = value(UserPrivilegeType::Grant, rule! { GRANT });
3494 let create_stage = value(UserPrivilegeType::CreateStage, rule! { CREATE ~ STAGE });
3495 let set = value(UserPrivilegeType::Set, rule! { SET });
3496 let drop = value(UserPrivilegeType::Drop, rule! { DROP });
3497 let create = value(UserPrivilegeType::Create, rule! { CREATE });
3498
3499 alt((
3500 rule!(
3501 #usage
3502 | #select
3503 | #insert
3504 | #update
3505 | #delete
3506 | #alter
3507 | #super_priv
3508 | #create_user
3509 | #create_database
3510 | #create_warehouse
3511 ),
3512 rule!(
3513 #create_connection
3514 | #access_connection
3515 | #access_sequence
3516 | #create_sequence
3517 | #drop_user
3518 | #create_role
3519 | #drop_role
3520 | #grant
3521 | #create_stage
3522 | #set
3523 | #drop
3524 | #create
3525 ),
3526 ))(i)
3527}
3528
3529pub fn stage_priv_type(i: Input) -> IResult<UserPrivilegeType> {
3530 alt((
3531 value(UserPrivilegeType::Read, rule! { READ }),
3532 value(UserPrivilegeType::Write, rule! { WRITE }),
3533 ))(i)
3534}
3535
3536pub fn priv_share_type(i: Input) -> IResult<ShareGrantObjectPrivilege> {
3537 alt((
3538 value(ShareGrantObjectPrivilege::Usage, rule! { USAGE }),
3539 value(ShareGrantObjectPrivilege::Select, rule! { SELECT }),
3540 value(
3541 ShareGrantObjectPrivilege::ReferenceUsage,
3542 rule! { REFERENCE_USAGE },
3543 ),
3544 ))(i)
3545}
3546
3547pub fn alter_add_share_accounts(i: Input) -> IResult<bool> {
3548 alt((value(true, rule! { ADD }), value(false, rule! { REMOVE })))(i)
3549}
3550
3551pub fn on_object_name(i: Input) -> IResult<GrantObjectName> {
3552 let database = map(
3553 rule! {
3554 DATABASE ~ #ident
3555 },
3556 |(_, database)| GrantObjectName::Database(database.to_string()),
3557 );
3558
3559 let table = map(
3561 rule! {
3562 TABLE ~ #dot_separated_idents_1_to_2
3563 },
3564 |(_, (database, table))| {
3565 GrantObjectName::Table(database.map(|db| db.to_string()), table.to_string())
3566 },
3567 );
3568
3569 let stage = map(rule! { STAGE ~ #ident}, |(_, stage_name)| {
3570 GrantObjectName::Stage(stage_name.to_string())
3571 });
3572
3573 let udf = map(rule! { UDF ~ #ident}, |(_, udf_name)| {
3574 GrantObjectName::UDF(udf_name.to_string())
3575 });
3576
3577 let warehouse = map(rule! { WAREHOUSE ~ #ident}, |(_, w)| {
3578 GrantObjectName::Warehouse(w.to_string())
3579 });
3580
3581 let connection = map(rule! { CONNECTION ~ #ident}, |(_, w)| {
3582 GrantObjectName::Connection(w.to_string())
3583 });
3584
3585 let seq = map(rule! { SEQUENCE ~ #ident}, |(_, w)| {
3586 GrantObjectName::Sequence(w.to_string())
3587 });
3588
3589 rule!(
3590 #database : "DATABASE <database>"
3591 | #table : "TABLE <database>.<table>"
3592 | #stage : "STAGE <stage_name>"
3593 | #udf : "UDF <udf_name>"
3594 | #warehouse : "WAREHOUSE <warehouse_name>"
3595 | #connection : "CONNECTION <connection_name>"
3596 | #seq : "SEQUENCE <seq_name>"
3597 )(i)
3598}
3599
3600pub fn grant_level(i: Input) -> IResult<AccountMgrLevel> {
3601 let global = map(rule! { "*" ~ "." ~ "*" }, |_| AccountMgrLevel::Global);
3603 let db = map(
3606 rule! {
3607 ( #ident ~ "." )? ~ "*"
3608 },
3609 |(database, _)| AccountMgrLevel::Database(database.map(|(database, _)| database.name)),
3610 );
3611
3612 let table = map(
3614 rule! {
3615 ( #ident ~ "." )? ~ #parameter_to_string
3616 },
3617 |(database, table)| {
3618 AccountMgrLevel::Table(database.map(|(database, _)| database.name), table)
3619 },
3620 );
3621
3622 rule!(
3623 #global : "*.*"
3624 | #db : "<database>.*"
3625 | #table : "<database>.<table>"
3626 )(i)
3627}
3628
3629pub fn grant_all_level(i: Input) -> IResult<AccountMgrLevel> {
3630 let global = map(rule! { "*" ~ "." ~ "*" }, |_| AccountMgrLevel::Global);
3632 let db = map(
3635 rule! {
3636 ( #ident ~ "." )? ~ "*"
3637 },
3638 |(database, _)| AccountMgrLevel::Database(database.map(|(database, _)| database.name)),
3639 );
3640
3641 let table = map(
3643 rule! {
3644 ( #ident ~ "." )? ~ #parameter_to_string
3645 },
3646 |(database, table)| {
3647 AccountMgrLevel::Table(database.map(|(database, _)| database.name), table)
3648 },
3649 );
3650
3651 let stage = map(rule! { STAGE ~ #ident}, |(_, stage_name)| {
3652 AccountMgrLevel::Stage(stage_name.to_string())
3653 });
3654
3655 let warehouse = map(rule! { WAREHOUSE ~ #ident}, |(_, w)| {
3656 AccountMgrLevel::Warehouse(w.to_string())
3657 });
3658 rule!(
3659 #global : "*.*"
3660 | #db : "<database>.*"
3661 | #table : "<database>.<table>"
3662 | #stage : "STAGE <stage_name>"
3663 | #warehouse : "WAREHOUSE <warehouse_name>"
3664 )(i)
3665}
3666
3667pub fn grant_ownership_level(i: Input) -> IResult<AccountMgrLevel> {
3668 let db = map(
3671 rule! {
3672 ( #grant_ident ~ "." )? ~ "*"
3673 },
3674 |(database, _)| AccountMgrLevel::Database(database.map(|(database, _)| database.name)),
3675 );
3676
3677 let table = map(
3679 rule! {
3680 ( #grant_ident ~ "." )? ~ #parameter_to_grant_string
3681 },
3682 |(database, table)| {
3683 AccountMgrLevel::Table(database.map(|(database, _)| database.name), table)
3684 },
3685 );
3686
3687 #[derive(Clone)]
3688 enum Object {
3689 Stage,
3690 Udf,
3691 Warehouse,
3692 Connection,
3693 Sequence,
3694 }
3695 let object = alt((
3696 value(Object::Udf, rule! { UDF }),
3697 value(Object::Stage, rule! { STAGE }),
3698 value(Object::Warehouse, rule! { WAREHOUSE }),
3699 value(Object::Connection, rule! { CONNECTION }),
3700 value(Object::Sequence, rule! { SEQUENCE }),
3701 ));
3702
3703 let object = map(
3705 rule! { #object ~ #grant_ident },
3706 |(object, object_name)| match object {
3707 Object::Stage => AccountMgrLevel::Stage(object_name.to_string()),
3708 Object::Udf => AccountMgrLevel::UDF(object_name.to_string()),
3709 Object::Warehouse => AccountMgrLevel::Warehouse(object_name.to_string()),
3710 Object::Connection => AccountMgrLevel::Connection(object_name.to_string()),
3711 Object::Sequence => AccountMgrLevel::Sequence(object_name.to_string()),
3712 },
3713 );
3714
3715 rule!(
3716 #db : "<database>.*"
3717 | #table : "<database>.<table>"
3718 | #object : "STAGE | UDF | WAREHOUSE | CONNECTION | SEQUENCE <object_name>"
3719 )(i)
3720}
3721
3722pub fn show_grant_option(i: Input) -> IResult<ShowGrantOption> {
3723 let grant_role = map(
3724 rule! {
3725 FOR ~ #grant_option
3726 },
3727 |(_, opt_principal)| ShowGrantOption::PrincipalIdentity(opt_principal),
3728 );
3729
3730 let share_object_name = map(
3731 rule! {
3732 ON ~ #on_object_name
3733 },
3734 |(_, object_name)| ShowGrantOption::GrantObjectName(object_name),
3735 );
3736
3737 let role_granted = map(
3738 rule! {
3739 OF ~ ROLE ~ #role_name
3740 },
3741 |(_, _, role_name)| ShowGrantOption::OfRole(role_name),
3742 );
3743
3744 rule!(
3745 #grant_role: "FOR { ROLE <role_name> | [USER] <user> }"
3746 | #share_object_name: "ON {DATABASE <db_name> | TABLE <db_name>.<table_name> | UDF <udf_name> | STAGE <stage_name> | CONNECTION <connection_name> | SEQUENCE <seq_name> }"
3747 | #role_granted: "OF ROLE <role_name>"
3748 )(i)
3749}
3750
3751pub fn grant_option(i: Input) -> IResult<PrincipalIdentity> {
3752 let role = map(
3753 rule! {
3754 ROLE ~ #role_name
3755 },
3756 |(_, role_name)| PrincipalIdentity::Role(role_name),
3757 );
3758
3759 let user = map(
3760 rule! {
3761 USER? ~ #user_identity
3762 },
3763 |(_, user)| PrincipalIdentity::User(user),
3764 );
3765
3766 rule!(
3767 #role
3768 | #user
3769 )(i)
3770}
3771
3772pub fn create_table_source(i: Input) -> IResult<CreateTableSource> {
3773 let columns = map(
3774 rule! {
3775 "(" ~ ^#comma_separated_list1(create_def) ~ ^")"
3776 },
3777 |(_, create_defs, _)| {
3778 let mut columns = Vec::with_capacity(create_defs.len());
3779 let mut table_indexes = Vec::new();
3780 for create_def in create_defs {
3781 match create_def {
3782 CreateDefinition::Column(column) => {
3783 columns.push(column);
3784 }
3785 CreateDefinition::TableIndex(table_index) => {
3786 table_indexes.push(table_index);
3787 }
3788 }
3789 }
3790 let opt_table_indexes = if !table_indexes.is_empty() {
3791 Some(table_indexes)
3792 } else {
3793 None
3794 };
3795 CreateTableSource::Columns(columns, opt_table_indexes)
3796 },
3797 );
3798 let like = map(
3799 rule! {
3800 LIKE ~ #dot_separated_idents_1_to_3
3801 },
3802 |(_, (catalog, database, table))| CreateTableSource::Like {
3803 catalog,
3804 database,
3805 table,
3806 },
3807 );
3808
3809 rule!(
3810 #columns
3811 | #like
3812 )(i)
3813}
3814
3815pub fn alter_database_action(i: Input) -> IResult<AlterDatabaseAction> {
3816 let rename_database = map(
3817 rule! {
3818 RENAME ~ TO ~ #ident
3819 },
3820 |(_, _, new_db)| AlterDatabaseAction::RenameDatabase { new_db },
3821 );
3822
3823 let refresh_cache = map(
3824 rule! {
3825 REFRESH ~ CACHE
3826 },
3827 |(_, _)| AlterDatabaseAction::RefreshDatabaseCache,
3828 );
3829
3830 rule!(
3831 #rename_database
3832 | #refresh_cache
3833 )(i)
3834}
3835
3836pub fn modify_column_type(i: Input) -> IResult<ColumnDefinition> {
3837 #[derive(Educe)]
3838 #[educe(Clone(bound = false, attrs = "#[recursive::recursive]"))]
3839 enum ColumnConstraint {
3840 Nullable(bool),
3841 DefaultExpr(Box<Expr>),
3842 }
3843
3844 let nullable = alt((
3845 value(ColumnConstraint::Nullable(true), rule! { NULL }),
3846 value(ColumnConstraint::Nullable(false), rule! { NOT ~ ^NULL }),
3847 ));
3848 let expr = alt((map(
3849 rule! {
3850 DEFAULT ~ ^#subexpr(NOT_PREC)
3851 },
3852 |(_, default_expr)| ColumnConstraint::DefaultExpr(Box::new(default_expr)),
3853 ),));
3854
3855 let comment = map(
3856 rule! {
3857 COMMENT ~ #literal_string
3858 },
3859 |(_, comment)| comment,
3860 );
3861
3862 map_res(
3863 rule! {
3864 #ident
3865 ~ #type_name
3866 ~ ( #nullable | #expr )*
3867 ~ ( #comment )?
3868 : "`<column name> <type> [DEFAULT <expr>] [COMMENT '<comment>']`"
3869 },
3870 |(name, data_type, constraints, comment)| {
3871 let mut def = ColumnDefinition {
3872 name,
3873 data_type,
3874 expr: None,
3875 comment,
3876 };
3877 for constraint in constraints {
3878 match constraint {
3879 ColumnConstraint::Nullable(nullable) => {
3880 if (nullable && matches!(def.data_type, TypeName::NotNull(_)))
3881 || (!nullable && matches!(def.data_type, TypeName::Nullable(_)))
3882 {
3883 return Err(nom::Err::Failure(ErrorKind::Other(
3884 "ambiguous NOT NULL constraint",
3885 )));
3886 }
3887 if nullable {
3888 def.data_type = def.data_type.wrap_nullable();
3889 } else {
3890 def.data_type = def.data_type.wrap_not_null();
3891 }
3892 }
3893 ColumnConstraint::DefaultExpr(default_expr) => {
3894 def.expr = Some(ColumnExpr::Default(default_expr))
3895 }
3896 }
3897 }
3898 Ok(def)
3899 },
3900 )(i)
3901}
3902
3903pub fn modify_column_comment(i: Input) -> IResult<ColumnComment> {
3904 let comment = map(
3905 rule! {
3906 COMMENT ~ #literal_string
3907 },
3908 |(_, comment)| comment,
3909 );
3910 map_res(
3911 rule! {
3912 #ident
3913 ~ #comment
3914 : "`<column name> COMMENT '<comment>'`"
3915 },
3916 |(name, comment)| Ok(ColumnComment { name, comment }),
3917 )(i)
3918}
3919
3920pub fn modify_column_action(i: Input) -> IResult<ModifyColumnAction> {
3921 let set_mask_policy = map(
3922 rule! {
3923 #ident ~ SET ~ MASKING ~ POLICY ~ #ident
3924 },
3925 |(column, _, _, _, mask_name)| {
3926 ModifyColumnAction::SetMaskingPolicy(column, mask_name.to_string())
3927 },
3928 );
3929
3930 let unset_mask_policy = map(
3931 rule! {
3932 #ident ~ UNSET ~ MASKING ~ POLICY
3933 },
3934 |(column, _, _, _)| ModifyColumnAction::UnsetMaskingPolicy(column),
3935 );
3936
3937 let convert_stored_computed_column = map(
3938 rule! {
3939 #ident ~ DROP ~ STORED
3940 },
3941 |(column, _, _)| ModifyColumnAction::ConvertStoredComputedColumn(column),
3942 );
3943
3944 let modify_column_type = map(
3945 rule! {
3946 #modify_column_type ~ ("," ~ COLUMN? ~ #modify_column_type)*
3947 },
3948 |(column_def, column_def_vec)| {
3949 let mut column_defs = vec![column_def];
3950 column_def_vec
3951 .iter()
3952 .for_each(|(_, _, column_def)| column_defs.push(column_def.clone()));
3953 ModifyColumnAction::SetDataType(column_defs)
3954 },
3955 );
3956
3957 let modify_column_comment = map(
3958 rule! {
3959 #modify_column_comment ~ ("," ~ COLUMN? ~ #modify_column_comment)*
3960 },
3961 |(column_def, column_def_vec)| {
3962 let mut column_defs = vec![column_def];
3963 column_def_vec
3964 .iter()
3965 .for_each(|(_, _, column_def)| column_defs.push(column_def.clone()));
3966 ModifyColumnAction::Comment(column_defs)
3967 },
3968 );
3969
3970 rule!(
3971 #set_mask_policy
3972 | #unset_mask_policy
3973 | #convert_stored_computed_column
3974 | #modify_column_type
3975 | #modify_column_comment
3976 )(i)
3977}
3978
3979pub fn alter_table_action(i: Input) -> IResult<AlterTableAction> {
3980 let rename_table = map(
3981 rule! {
3982 RENAME ~ TO ~ #ident
3983 },
3984 |(_, _, new_table)| AlterTableAction::RenameTable { new_table },
3985 );
3986 let rename_column = map(
3987 rule! {
3988 RENAME ~ COLUMN? ~ #ident ~ TO ~ #ident
3989 },
3990 |(_, _, old_column, _, new_column)| AlterTableAction::RenameColumn {
3991 old_column,
3992 new_column,
3993 },
3994 );
3995 let modify_table_comment = map(
3996 rule! {
3997 COMMENT ~ ^"=" ~ ^#literal_string
3998 },
3999 |(_, _, new_comment)| AlterTableAction::ModifyTableComment { new_comment },
4000 );
4001 let add_column = map(
4002 rule! {
4003 ADD ~ COLUMN? ~ #column_def ~ ( #add_column_option )?
4004 },
4005 |(_, _, column, option)| AlterTableAction::AddColumn {
4006 column,
4007 option: option.unwrap_or(AddColumnOption::End),
4008 },
4009 );
4010
4011 let modify_column = map(
4012 rule! {
4013 MODIFY ~ COLUMN? ~ #modify_column_action
4014 },
4015 |(_, _, action)| AlterTableAction::ModifyColumn { action },
4016 );
4017
4018 let drop_column = map(
4019 rule! {
4020 DROP ~ COLUMN? ~ #ident
4021 },
4022 |(_, _, column)| AlterTableAction::DropColumn { column },
4023 );
4024 let alter_table_cluster_key = map(
4025 rule! {
4026 CLUSTER ~ ^BY ~ ( #cluster_type )? ~ ^"(" ~ ^#comma_separated_list1(expr) ~ ^")"
4027 },
4028 |(_, _, typ, _, cluster_exprs, _)| AlterTableAction::AlterTableClusterKey {
4029 cluster_by: ClusterOption {
4030 cluster_type: typ.unwrap_or(ClusterType::Linear),
4031 cluster_exprs,
4032 },
4033 },
4034 );
4035
4036 let drop_table_cluster_key = map(
4037 rule! {
4038 DROP ~ CLUSTER ~ KEY
4039 },
4040 |(_, _, _)| AlterTableAction::DropTableClusterKey,
4041 );
4042
4043 let recluster_table = map(
4044 rule! {
4045 RECLUSTER ~ FINAL? ~ ( WHERE ~ ^#expr )? ~ ( LIMIT ~ #literal_u64 )?
4046 },
4047 |(_, opt_is_final, opt_selection, opt_limit)| AlterTableAction::ReclusterTable {
4048 is_final: opt_is_final.is_some(),
4049 selection: opt_selection.map(|(_, selection)| selection),
4050 limit: opt_limit.map(|(_, limit)| limit),
4051 },
4052 );
4053
4054 let revert_table = map(
4055 rule! {
4056 FLASHBACK ~ TO ~ #travel_point
4057 },
4058 |(_, _, point)| AlterTableAction::FlashbackTo { point },
4059 );
4060
4061 let set_table_options = map(
4062 rule! {
4063 SET ~ OPTIONS ~ "(" ~ #set_table_option ~ ")"
4064 },
4065 |(_, _, _, set_options, _)| AlterTableAction::SetOptions { set_options },
4066 );
4067
4068 let unset_table_options = map(
4069 rule! {
4070 UNSET ~ OPTIONS ~ #unset_source
4071 },
4072 |(_, _, targets)| AlterTableAction::UnsetOptions { targets },
4073 );
4074
4075 let refresh_cache = map(
4076 rule! {
4077 REFRESH ~ CACHE
4078 },
4079 |(_, _)| AlterTableAction::RefreshTableCache,
4080 );
4081
4082 let modify_table_connection = map(
4083 rule! {
4084 CONNECTION ~ ^"=" ~ #connection_options
4085 },
4086 |(_, _, connection_options)| AlterTableAction::ModifyConnection {
4087 new_connection: connection_options,
4088 },
4089 );
4090
4091 rule!(
4092 #alter_table_cluster_key
4093 | #drop_table_cluster_key
4094 | #rename_table
4095 | #rename_column
4096 | #modify_table_comment
4097 | #add_column
4098 | #drop_column
4099 | #modify_column
4100 | #recluster_table
4101 | #revert_table
4102 | #set_table_options
4103 | #unset_table_options
4104 | #refresh_cache
4105 | #modify_table_connection
4106 )(i)
4107}
4108
4109pub fn match_clause(i: Input) -> IResult<MergeOption> {
4110 map(
4111 rule! {
4112 WHEN ~ MATCHED ~ (AND ~ ^#expr)? ~ THEN ~ #match_operation
4113 },
4114 |(_, _, expr_op, _, match_operation)| match expr_op {
4115 Some(expr) => MergeOption::Match(MatchedClause {
4116 selection: Some(expr.1),
4117 operation: match_operation,
4118 }),
4119 None => MergeOption::Match(MatchedClause {
4120 selection: None,
4121 operation: match_operation,
4122 }),
4123 },
4124 )(i)
4125}
4126
4127fn match_operation(i: Input) -> IResult<MatchOperation> {
4128 alt((
4129 value(MatchOperation::Delete, rule! { DELETE }),
4130 map(
4131 rule! {
4132 UPDATE ~ SET ~ ^#comma_separated_list1(mutation_update_expr)
4133 },
4134 |(_, _, update_list)| MatchOperation::Update {
4135 update_list,
4136 is_star: false,
4137 },
4138 ),
4139 map(
4140 rule! {
4141 UPDATE ~ "*"
4142 },
4143 |(_, _)| MatchOperation::Update {
4144 update_list: Vec::new(),
4145 is_star: true,
4146 },
4147 ),
4148 ))(i)
4149}
4150
4151pub fn unmatch_clause(i: Input) -> IResult<MergeOption> {
4152 alt((
4153 map(
4154 rule! {
4155 WHEN ~ NOT ~ MATCHED ~ (AND ~ ^#expr)? ~ THEN ~ INSERT ~ ( "(" ~ ^#comma_separated_list1(ident) ~ ^")" )?
4156 ~ VALUES ~ ^#row_values
4157 },
4158 |(_, _, _, expr_op, _, _, columns_op, _, values)| {
4159 let selection = match expr_op {
4160 Some(e) => Some(e.1),
4161 None => None,
4162 };
4163 match columns_op {
4164 Some(columns) => MergeOption::Unmatch(UnmatchedClause {
4165 insert_operation: InsertOperation {
4166 columns: Some(columns.1),
4167 values,
4168 is_star: false,
4169 },
4170 selection,
4171 }),
4172 None => MergeOption::Unmatch(UnmatchedClause {
4173 insert_operation: InsertOperation {
4174 columns: None,
4175 values,
4176 is_star: false,
4177 },
4178 selection,
4179 }),
4180 }
4181 },
4182 ),
4183 map(
4184 rule! {
4185 WHEN ~ NOT ~ MATCHED ~ (AND ~ ^#expr)? ~ THEN ~ INSERT ~ "*"
4186 },
4187 |(_, _, _, expr_op, _, _, _)| {
4188 let selection = match expr_op {
4189 Some(e) => Some(e.1),
4190 None => None,
4191 };
4192 MergeOption::Unmatch(UnmatchedClause {
4193 insert_operation: InsertOperation {
4194 columns: None,
4195 values: Vec::new(),
4196 is_star: true,
4197 },
4198 selection,
4199 })
4200 },
4201 ),
4202 ))(i)
4203}
4204
4205pub fn add_column_option(i: Input) -> IResult<AddColumnOption> {
4206 alt((
4207 value(AddColumnOption::First, rule! { FIRST }),
4208 map(rule! { AFTER ~ #ident }, |(_, ident)| {
4209 AddColumnOption::After(ident)
4210 }),
4211 ))(i)
4212}
4213
4214pub fn optimize_table_action(i: Input) -> IResult<OptimizeTableAction> {
4215 alt((
4216 value(OptimizeTableAction::All, rule! { ALL }),
4217 map(
4218 rule! { PURGE ~ (BEFORE ~ ^#travel_point)? },
4219 |(_, opt_travel_point)| OptimizeTableAction::Purge {
4220 before: opt_travel_point.map(|(_, p)| p),
4221 },
4222 ),
4223 map(rule! { COMPACT ~ SEGMENT? }, |(_, opt_segment)| {
4224 OptimizeTableAction::Compact {
4225 target: opt_segment.map_or(CompactTarget::Block, |_| CompactTarget::Segment),
4226 }
4227 }),
4228 ))(i)
4229}
4230
4231pub fn literal_duration(i: Input) -> IResult<Duration> {
4232 let seconds = map(
4233 rule! {
4234 #literal_u64 ~ SECONDS
4235 },
4236 |(v, _)| Duration::from_secs(v),
4237 );
4238
4239 let days = map(
4240 rule! {
4241 #literal_u64 ~ DAYS
4242 },
4243 |(v, _)| Duration::from_secs(v * 60 * 60 * 24),
4244 );
4245
4246 rule!(
4247 #days
4248 | #seconds
4249 )(i)
4250}
4251
4252pub fn vacuum_drop_table_option(i: Input) -> IResult<VacuumDropTableOption> {
4253 alt((map(
4254 rule! {
4255 (DRY ~ ^RUN ~ SUMMARY?)? ~ (LIMIT ~ #literal_u64)?
4256 },
4257 |(opt_dry_run, opt_limit)| VacuumDropTableOption {
4258 dry_run: opt_dry_run.map(|dry_run| dry_run.2.is_some()),
4259 limit: opt_limit.map(|(_, limit)| limit as usize),
4260 },
4261 ),))(i)
4262}
4263
4264pub fn vacuum_table_option(i: Input) -> IResult<VacuumTableOption> {
4265 alt((map(
4266 rule! {
4267 (DRY ~ ^RUN ~ SUMMARY?)?
4268 },
4269 |opt_dry_run| VacuumTableOption {
4270 dry_run: opt_dry_run.map(|dry_run| dry_run.2.is_some()),
4271 },
4272 ),))(i)
4273}
4274
4275pub fn task_sql_block(i: Input) -> IResult<TaskSql> {
4276 let single_statement = map(
4277 rule! {
4278 #statement
4279 },
4280 |stmt| {
4281 let sql = format!("{}", stmt.stmt);
4282 TaskSql::SingleStatement(sql)
4283 },
4284 );
4285 let task_block = map(
4286 rule! {
4287 BEGIN
4288 ~ #semicolon_terminated_list1(statement_body)
4289 ~ END
4290 },
4291 |(_, stmts, _)| {
4292 let sql = stmts
4293 .iter()
4294 .map(|stmt| format!("{}", stmt))
4295 .collect::<Vec<String>>();
4296 TaskSql::ScriptBlock(sql)
4297 },
4298 );
4299 alt((single_statement, task_block))(i)
4300}
4301
4302pub fn alter_task_option(i: Input) -> IResult<AlterTaskOptions> {
4303 let suspend = map(
4304 rule! {
4305 SUSPEND
4306 },
4307 |_| AlterTaskOptions::Suspend,
4308 );
4309 let resume = map(
4310 rule! {
4311 RESUME
4312 },
4313 |_| AlterTaskOptions::Resume,
4314 );
4315 let modify_as = map(
4316 rule! {
4317 MODIFY ~ AS ~ #task_sql_block
4318 },
4319 |(_, _, sql)| AlterTaskOptions::ModifyAs(sql),
4320 );
4321 let modify_when = map(
4322 rule! {
4323 MODIFY ~ WHEN ~ #expr
4324 },
4325 |(_, _, expr)| AlterTaskOptions::ModifyWhen(expr),
4326 );
4327 let add_after = map(
4328 rule! {
4329 ADD ~ AFTER ~ #comma_separated_list0(literal_string)
4330 },
4331 |(_, _, after)| AlterTaskOptions::AddAfter(after),
4332 );
4333 let remove_after = map(
4334 rule! {
4335 REMOVE ~ AFTER ~ #comma_separated_list0(literal_string)
4336 },
4337 |(_, _, after)| AlterTaskOptions::RemoveAfter(after),
4338 );
4339
4340 let set = map(
4341 rule! {
4342 SET
4343 ~ #alter_task_set_option*
4344 ~ #set_table_option?
4345 },
4346 |(_, task_set_options, session_opts)| {
4347 let mut set = AlterTaskOptions::Set {
4348 session_parameters: session_opts,
4349 warehouse: None,
4350 schedule: None,
4351 suspend_task_after_num_failures: None,
4352 comments: None,
4353 error_integration: None,
4354 };
4355 for opt in task_set_options {
4356 set.apply_opt(opt);
4357 }
4358 set
4359 },
4360 );
4361 let unset = map(
4362 rule! {
4363 UNSET ~ WAREHOUSE
4364 },
4365 |_| AlterTaskOptions::Unset { warehouse: true },
4366 );
4367 rule!(
4368 #suspend
4369 | #resume
4370 | #modify_as
4371 | #set
4372 | #unset
4373 | #modify_when
4374 | #add_after
4375 | #remove_after
4376 )(i)
4377}
4378
4379pub fn alter_pipe_option(i: Input) -> IResult<AlterPipeOptions> {
4380 let set = map(
4381 rule! {
4382 SET
4383 ~ ( PIPE_EXECUTION_PAUSED ~ "=" ~ #literal_bool )?
4384 ~ ( COMMENT ~ "=" ~ #literal_string )?
4385 },
4386 |(_, execution_parsed, comment)| AlterPipeOptions::Set {
4387 execution_paused: execution_parsed.map(|(_, _, paused)| paused),
4388 comments: comment.map(|(_, _, comment)| comment),
4389 },
4390 );
4391 let refresh = map(
4392 rule! {
4393 REFRESH
4394 ~ ( PREFIX ~ "=" ~ #literal_string )?
4395 ~ ( MODIFIED_AFTER ~ "=" ~ #literal_string )?
4396 },
4397 |(_, prefix, modified_after)| AlterPipeOptions::Refresh {
4398 prefix: prefix.map(|(_, _, prefix)| prefix),
4399 modified_after: modified_after.map(|(_, _, modified_after)| modified_after),
4400 },
4401 );
4402 rule!(
4403 #set
4404 | #refresh
4405 )(i)
4406}
4407
4408pub fn task_warehouse_option(i: Input) -> IResult<WarehouseOptions> {
4409 alt((map(
4410 rule! {
4411 (WAREHOUSE ~ "=" ~ #literal_string)?
4412 },
4413 |warehouse_opt| {
4414 let warehouse = match warehouse_opt {
4415 Some(warehouse) => Some(warehouse.2),
4416 None => None,
4417 };
4418 WarehouseOptions { warehouse }
4419 },
4420 ),))(i)
4421}
4422
4423pub fn assign_nodes_list(i: Input) -> IResult<Vec<(Option<String>, u64)>> {
4424 let nodes_list = map(
4425 rule! {
4426 ASSIGN ~ #literal_u64 ~ NODES ~ (FROM ~ #option_to_string)?
4427 },
4428 |(_, node_size, _, node_group)| (node_group.map(|(_, x)| x), node_size),
4429 );
4430
4431 map(comma_separated_list1(nodes_list), |opts| {
4432 opts.into_iter().collect()
4433 })(i)
4434}
4435
4436pub fn assign_warehouse_nodes_list(i: Input) -> IResult<Vec<(Identifier, Option<String>, u64)>> {
4437 let nodes_list = map(
4438 rule! {
4439 ASSIGN ~ #literal_u64 ~ NODES ~ (FROM ~ #option_to_string)? ~ FOR ~ #ident
4440 },
4441 |(_, node_size, _, node_group, _, cluster)| {
4442 (cluster, node_group.map(|(_, x)| x), node_size)
4443 },
4444 );
4445
4446 map(comma_separated_list1(nodes_list), |opts| {
4447 opts.into_iter().collect()
4448 })(i)
4449}
4450
4451pub fn unassign_warehouse_nodes_list(i: Input) -> IResult<Vec<(Identifier, Option<String>, u64)>> {
4452 let nodes_list = map(
4453 rule! {
4454 UNASSIGN ~ #literal_u64 ~ NODES ~ (FROM ~ #option_to_string)? ~ FOR ~ #ident
4455 },
4456 |(_, node_size, _, node_group, _, cluster)| {
4457 (cluster, node_group.map(|(_, x)| x), node_size)
4458 },
4459 );
4460
4461 map(comma_separated_list1(nodes_list), |opts| {
4462 opts.into_iter().collect()
4463 })(i)
4464}
4465
4466pub fn warehouse_cluster_option(i: Input) -> IResult<BTreeMap<String, String>> {
4467 let option = map(
4468 rule! {
4469 #ident ~ "=" ~ #option_to_string
4470 },
4471 |(k, _, v)| (k, v),
4472 );
4473 map(comma_separated_list1(option), |opts| {
4474 opts.into_iter()
4475 .map(|(k, v)| (k.name.to_lowercase(), v.clone()))
4476 .collect()
4477 })(i)
4478}
4479
4480pub fn workload_quotas(i: Input) -> IResult<BTreeMap<String, QuotaValueStmt>> {
4481 let option = map(
4482 rule! {
4483 #ident ~ "=" ~ #option_to_string
4484 },
4485 |(k, _, v)| (k, v),
4486 );
4487
4488 map_res(comma_separated_list1(option), |opts| {
4489 let mut quotas = BTreeMap::new();
4490 for (name, value) in opts {
4491 let name = name.name.to_lowercase();
4492 match QuotaValueStmt::new(&name, value) {
4493 Ok(value) => {
4494 quotas.insert(name, value);
4495 }
4496 Err(error_desc) => {
4497 return Err(nom::Err::Failure(ErrorKind::Other(error_desc)));
4498 }
4499 }
4500 }
4501
4502 Ok(quotas)
4503 })(i)
4504}
4505
4506pub fn task_schedule_option(i: Input) -> IResult<ScheduleOptions> {
4507 let interval = map(
4508 rule! {
4509 #literal_u64 ~ MINUTE
4510 },
4511 |(mins, _)| ScheduleOptions::IntervalSecs(mins * 60, 0),
4512 );
4513 let cron_expr = map(
4514 rule! {
4515 USING ~ CRON ~ #literal_string ~ #literal_string?
4516 },
4517 |(_, _, expr, timezone)| ScheduleOptions::CronExpression(expr, timezone),
4518 );
4519 let interval_sec = map(
4520 rule! {
4521 #literal_u64 ~ SECOND
4522 },
4523 |(secs, _)| ScheduleOptions::IntervalSecs(secs, 0),
4524 );
4525 let interval_millis = map(
4526 rule! {
4527 #literal_u64 ~ MILLISECOND
4528 },
4529 |(millis, _)| ScheduleOptions::IntervalSecs(0, millis),
4530 );
4531 rule!(
4532 #interval
4533 | #cron_expr
4534 | #interval_sec
4535 | #interval_millis
4536 )(i)
4537}
4538
4539pub fn kill_target(i: Input) -> IResult<KillTarget> {
4540 alt((
4541 value(KillTarget::Query, rule! { QUERY }),
4542 value(KillTarget::Connection, rule! { CONNECTION }),
4543 ))(i)
4544}
4545
4546pub fn priority(i: Input) -> IResult<Priority> {
4547 alt((
4548 value(Priority::LOW, rule! { LOW }),
4549 value(Priority::MEDIUM, rule! { MEDIUM }),
4550 value(Priority::HIGH, rule! { HIGH }),
4551 ))(i)
4552}
4553
4554pub fn action(i: Input) -> IResult<SystemAction> {
4555 let mut backtrace = map(
4556 rule! {
4557 #switch ~ EXCEPTION_BACKTRACE
4558 },
4559 |(switch, _)| SystemAction::Backtrace(switch),
4560 );
4561 rule!(
4563 #backtrace
4564 )(i)
4565}
4566
4567pub fn switch(i: Input) -> IResult<bool> {
4568 alt((
4569 value(true, rule! { ENABLE }),
4570 value(false, rule! { DISABLE }),
4571 ))(i)
4572}
4573
4574pub fn cluster_type(i: Input) -> IResult<ClusterType> {
4575 alt((
4576 value(ClusterType::Linear, rule! { LINEAR }),
4577 value(ClusterType::Hilbert, rule! { HILBERT }),
4578 ))(i)
4579}
4580
4581pub fn limit_where(i: Input) -> IResult<ShowLimit> {
4582 map(
4583 rule! {
4584 WHERE ~ #expr
4585 },
4586 |(_, selection)| ShowLimit::Where {
4587 selection: Box::new(selection),
4588 },
4589 )(i)
4590}
4591
4592pub fn limit_like(i: Input) -> IResult<ShowLimit> {
4593 map(
4594 rule! {
4595 LIKE ~ #literal_string
4596 },
4597 |(_, pattern)| ShowLimit::Like { pattern },
4598 )(i)
4599}
4600
4601pub fn show_limit(i: Input) -> IResult<ShowLimit> {
4602 rule!(
4603 #limit_like
4604 | #limit_where
4605 )(i)
4606}
4607
4608pub fn show_options(i: Input) -> IResult<ShowOptions> {
4609 map(
4610 rule! {
4611 #show_limit? ~ ( LIMIT ~ ^#literal_u64 )?
4612 },
4613 |(show_limit, opt_limit)| ShowOptions {
4614 show_limit,
4615 limit: opt_limit.map(|(_, limit)| limit),
4616 },
4617 )(i)
4618}
4619
4620pub fn table_option(i: Input) -> IResult<BTreeMap<String, String>> {
4621 map(
4622 rule! {
4623 ( #ident ~ "=" ~ #option_to_string )*
4624 },
4625 |opts| {
4626 BTreeMap::from_iter(
4627 opts.iter()
4628 .map(|(k, _, v)| (k.name.to_lowercase(), v.clone())),
4629 )
4630 },
4631 )(i)
4632}
4633
4634pub fn set_table_option(i: Input) -> IResult<BTreeMap<String, String>> {
4635 let option = map(
4636 rule! {
4637 #ident ~ "=" ~ #option_to_string
4638 },
4639 |(k, _, v)| (k, v),
4640 );
4641
4642 map(comma_separated_list1(option), |opts| {
4643 opts.into_iter()
4644 .map(|(k, v)| (k.name.to_lowercase(), v.clone()))
4645 .collect()
4646 })(i)
4647}
4648
4649pub fn option_to_string(i: Input) -> IResult<String> {
4650 let bool_to_string = |i| map(literal_bool, |v| v.to_string())(i);
4651
4652 rule!(
4653 #bool_to_string
4654 | #parameter_to_string
4655 )(i)
4656}
4657
4658pub fn engine(i: Input) -> IResult<Engine> {
4659 let engine = alt((
4660 value(Engine::Null, rule! { NULL }),
4661 value(Engine::Memory, rule! { MEMORY }),
4662 value(Engine::Fuse, rule! { FUSE }),
4663 value(Engine::View, rule! { VIEW }),
4664 value(Engine::Random, rule! { RANDOM }),
4665 value(Engine::Iceberg, rule! { ICEBERG }),
4666 value(Engine::Delta, rule! { DELTA }),
4667 ));
4668
4669 map(
4670 rule! {
4671 ENGINE ~ ^"=" ~ ^#engine
4672 },
4673 |(_, _, engine)| engine,
4674 )(i)
4675}
4676
4677pub fn database_engine(i: Input) -> IResult<DatabaseEngine> {
4678 value(DatabaseEngine::Default, rule! { DEFAULT })(i)
4679}
4680
4681pub fn create_database_option(i: Input) -> IResult<CreateDatabaseOption> {
4682 let mut create_db_engine = map(
4683 rule! {
4684 ENGINE ~ ^"=" ~ ^#database_engine
4685 },
4686 |(_, _, option)| CreateDatabaseOption::DatabaseEngine(option),
4687 );
4688
4689 rule!(
4690 #create_db_engine
4691 )(i)
4692}
4693
4694pub fn catalog_type(i: Input) -> IResult<CatalogType> {
4695 alt((
4696 value(CatalogType::Default, rule! { DEFAULT }),
4697 value(CatalogType::Hive, rule! { HIVE }),
4698 value(CatalogType::Iceberg, rule! { ICEBERG }),
4699 ))(i)
4700}
4701
4702pub fn user_option(i: Input) -> IResult<UserOptionItem> {
4703 let tenant_setting = value(UserOptionItem::TenantSetting(true), rule! { TENANTSETTING });
4704 let no_tenant_setting = value(
4705 UserOptionItem::TenantSetting(false),
4706 rule! { NOTENANTSETTING },
4707 );
4708 let default_role_option = map(
4709 rule! {
4710 DEFAULT_ROLE ~ ^"=" ~ ^#role_name
4711 },
4712 |(_, _, role)| UserOptionItem::DefaultRole(role),
4713 );
4714 let set_network_policy = map(
4715 rule! {
4716 SET ~ NETWORK ~ ^POLICY ~ ^"=" ~ ^#literal_string
4717 },
4718 |(_, _, _, _, policy)| UserOptionItem::SetNetworkPolicy(policy),
4719 );
4720 let unset_network_policy = map(
4721 rule! {
4722 UNSET ~ NETWORK ~ ^POLICY
4723 },
4724 |(_, _, _)| UserOptionItem::UnsetNetworkPolicy,
4725 );
4726 let set_disabled_option = map(
4727 rule! {
4728 DISABLED ~ ^"=" ~ #literal_bool
4729 },
4730 |(_, _, disabled)| UserOptionItem::Disabled(disabled),
4731 );
4732 let set_password_policy = map(
4733 rule! {
4734 SET ~ PASSWORD ~ ^POLICY ~ ^"=" ~ ^#literal_string
4735 },
4736 |(_, _, _, _, policy)| UserOptionItem::SetPasswordPolicy(policy),
4737 );
4738 let unset_password_policy = map(
4739 rule! {
4740 UNSET ~ PASSWORD ~ ^POLICY
4741 },
4742 |(_, _, _)| UserOptionItem::UnsetPasswordPolicy,
4743 );
4744 let must_change_password = map(
4745 rule! {
4746 MUST_CHANGE_PASSWORD ~ ^"=" ~ ^#literal_bool
4747 },
4748 |(_, _, val)| UserOptionItem::MustChangePassword(val),
4749 );
4750 let set_workload_group = map(
4751 rule! {
4752 SET ~ WORKLOAD ~ ^GROUP ~ ^"=" ~ ^#literal_string
4753 },
4754 |(_, _, _, _, wg)| UserOptionItem::SetWorkloadGroup(wg),
4755 );
4756 let unset_workload_group = map(
4757 rule! {
4758 UNSET ~ WORKLOAD ~ ^GROUP
4759 },
4760 |(_, _, _)| UserOptionItem::UnsetWorkloadGroup,
4761 );
4762
4763 rule!(
4764 #tenant_setting
4765 | #no_tenant_setting
4766 | #default_role_option
4767 | #set_network_policy
4768 | #unset_network_policy
4769 | #set_password_policy
4770 | #unset_password_policy
4771 | #set_disabled_option
4772 | #must_change_password
4773 | #set_workload_group
4774 | #unset_workload_group
4775 )(i)
4776}
4777
4778pub fn user_identity(i: Input) -> IResult<UserIdentity> {
4779 map(
4780 rule! {
4781 #parameter_to_string ~ ( "@" ~ "'%'" )?
4782 },
4783 |(username, _)| {
4784 let hostname = "%".to_string();
4785 UserIdentity { username, hostname }
4786 },
4787 )(i)
4788}
4789
4790pub fn auth_type(i: Input) -> IResult<AuthType> {
4791 alt((
4792 value(AuthType::NoPassword, rule! { NO_PASSWORD }),
4793 value(AuthType::Sha256Password, rule! { SHA256_PASSWORD }),
4794 value(AuthType::DoubleSha1Password, rule! { DOUBLE_SHA1_PASSWORD }),
4795 value(AuthType::JWT, rule! { JWT }),
4796 ))(i)
4797}
4798
4799pub fn presign_action(i: Input) -> IResult<PresignAction> {
4800 alt((
4801 value(PresignAction::Download, rule! { DOWNLOAD }),
4802 value(PresignAction::Upload, rule! { UPLOAD }),
4803 ))(i)
4804}
4805
4806pub fn presign_location(i: Input) -> IResult<PresignLocation> {
4807 map_res(
4808 rule! {
4809 #stage_location
4810 },
4811 |v| Ok(PresignLocation::StageLocation(v)),
4812 )(i)
4813}
4814
4815pub fn presign_option(i: Input) -> IResult<PresignOption> {
4816 alt((
4817 map(rule! { EXPIRE ~ ^"=" ~ ^#literal_u64 }, |(_, _, v)| {
4818 PresignOption::Expire(v)
4819 }),
4820 map(
4821 rule! { CONTENT_TYPE ~ ^"=" ~ ^#literal_string },
4822 |(_, _, v)| PresignOption::ContentType(v),
4823 ),
4824 ))(i)
4825}
4826
4827pub fn table_reference_with_alias(i: Input) -> IResult<TableReference> {
4828 map(
4829 consumed(rule! {
4830 #dot_separated_idents_1_to_3 ~ #alias_name?
4831 }),
4832 |(span, ((catalog, database, table), alias))| TableReference::Table {
4833 span: transform_span(span.tokens),
4834 catalog,
4835 database,
4836 table,
4837 alias: alias.map(|v| TableAlias {
4838 name: v,
4839 columns: vec![],
4840 }),
4841 temporal: None,
4842 with_options: None,
4843 pivot: None,
4844 unpivot: None,
4845 sample: None,
4846 },
4847 )(i)
4848}
4849
4850pub fn update_expr(i: Input) -> IResult<UpdateExpr> {
4851 map(rule! { ( #ident ~ "=" ~ ^#expr ) }, |(name, _, expr)| {
4852 UpdateExpr { name, expr }
4853 })(i)
4854}
4855
4856pub fn udaf_state_field(i: Input) -> IResult<UDAFStateField> {
4857 map(
4858 rule! {
4859 #ident
4860 ~ #type_name
4861 : "`<state name> <type>`"
4862 },
4863 |(name, type_name)| UDAFStateField { name, type_name },
4864 )(i)
4865}
4866
4867pub fn udf_header(i: Input) -> IResult<(String, String)> {
4868 map(
4869 rule! {
4870 #literal_string ~ #match_text("=") ~ ^#literal_string
4871 },
4872 |(k, _, v)| (k, v),
4873 )(i)
4874}
4875
4876pub fn udf_script_or_address(i: Input) -> IResult<(String, bool)> {
4877 let script = map(
4878 rule! {
4879 AS ~ ^(#code_string | #literal_string)
4880 },
4881 |(_, code)| (code, true),
4882 );
4883
4884 let address = map(
4885 rule! {
4886 ADDRESS ~ ^"=" ~ ^#literal_string
4887 },
4888 |(_, _, address)| (address, false),
4889 );
4890
4891 rule!(
4892 #script: "AS <language_codes>"
4893 | #address: "ADDRESS=<udf_server_address>"
4894 )(i)
4895}
4896
4897pub fn udf_definition(i: Input) -> IResult<UDFDefinition> {
4898 let lambda_udf = map(
4899 rule! {
4900 AS ~ "(" ~ #comma_separated_list0(ident) ~ ")"
4901 ~ "->" ~ #expr
4902 },
4903 |(_, _, parameters, _, _, definition)| UDFDefinition::LambdaUDF {
4904 parameters,
4905 definition: Box::new(definition),
4906 },
4907 );
4908
4909 let udf = map(
4910 rule! {
4911 "(" ~ #comma_separated_list0(type_name) ~ ")"
4912 ~ RETURNS ~ #type_name
4913 ~ LANGUAGE ~ #ident
4914 ~ (#udf_immutable)?
4915 ~ ( IMPORTS ~ ^"=" ~ "(" ~ #comma_separated_list0(literal_string) ~ ")" )?
4916 ~ ( PACKAGES ~ ^"=" ~ "(" ~ #comma_separated_list0(literal_string) ~ ")" )?
4917 ~ HANDLER ~ ^"=" ~ ^#literal_string
4918 ~ ( HEADERS ~ ^"=" ~ "(" ~ #comma_separated_list0(udf_header) ~ ")" )?
4919 ~ #udf_script_or_address
4920 },
4921 |(
4922 _,
4923 arg_types,
4924 _,
4925 _,
4926 return_type,
4927 _,
4928 language,
4929 immutable,
4930 imports,
4931 packages,
4932 _,
4933 _,
4934 handler,
4935 headers,
4936 address_or_code,
4937 )| {
4938 if address_or_code.1 {
4939 UDFDefinition::UDFScript {
4940 arg_types,
4941 return_type,
4942 code: address_or_code.0,
4943 imports: imports
4944 .map(|(_, _, _, imports, _)| imports)
4945 .unwrap_or_default(),
4946 packages: packages
4947 .map(|(_, _, _, packages, _)| packages)
4948 .unwrap_or_default(),
4949 handler,
4950 language: language.to_string(),
4951 runtime_version: "".to_string(),
4954 immutable,
4955 }
4956 } else {
4957 UDFDefinition::UDFServer {
4958 arg_types,
4959 return_type,
4960 address: address_or_code.0,
4961 handler,
4962 language: language.to_string(),
4963 headers: headers
4964 .map(|(_, _, _, headers, _)| BTreeMap::from_iter(headers))
4965 .unwrap_or_default(),
4966 immutable,
4967 }
4968 }
4969 },
4970 );
4971
4972 let udaf = map(
4973 rule! {
4974 "(" ~ #comma_separated_list0(type_name) ~ ")"
4975 ~ STATE ~ "{" ~ #comma_separated_list0(udaf_state_field) ~ "}"
4976 ~ RETURNS ~ #type_name
4977 ~ LANGUAGE ~ #ident
4978 ~ ( IMPORTS ~ ^"=" ~ "(" ~ #comma_separated_list0(literal_string) ~ ")" )?
4979 ~ ( PACKAGES ~ ^"=" ~ "(" ~ #comma_separated_list0(literal_string) ~ ")" )?
4980 ~ ( HEADERS ~ ^"=" ~ "(" ~ #comma_separated_list0(udf_header) ~ ")" )?
4981 ~ #udf_script_or_address
4982 },
4983 |(
4984 _,
4985 arg_types,
4986 _,
4987 _,
4988 _,
4989 state_types,
4990 _,
4991 _,
4992 return_type,
4993 _,
4994 language,
4995 imports,
4996 packages,
4997 headers,
4998 address_or_code,
4999 )| {
5000 if address_or_code.1 {
5001 UDFDefinition::UDAFScript {
5002 arg_types,
5003 state_fields: state_types,
5004 return_type,
5005 code: address_or_code.0,
5006 language: language.to_string(),
5007 imports: imports
5008 .map(|(_, _, _, imports, _)| imports)
5009 .unwrap_or_default(),
5010 packages: packages
5011 .map(|(_, _, _, packages, _)| packages)
5012 .unwrap_or_default(),
5013 runtime_version: "".to_string(),
5016 }
5017 } else {
5018 UDFDefinition::UDAFServer {
5019 arg_types,
5020 state_fields: state_types,
5021 return_type,
5022 address: address_or_code.0,
5023 headers: headers
5024 .map(|(_, _, _, headers, _)| BTreeMap::from_iter(headers))
5025 .unwrap_or_default(),
5026 language: language.to_string(),
5027 }
5028 }
5029 },
5030 );
5031
5032 rule!(
5033 #lambda_udf: "AS (<parameter>, ...) -> <definition expr>"
5034 | #udaf: "(<arg_type>, ...) STATE {<state_field>, ...} RETURNS <return_type> LANGUAGE <language> { ADDRESS=<udf_server_address> | AS <language_codes> } "
5035 | #udf: "(<arg_type>, ...) RETURNS <return_type> LANGUAGE <language> HANDLER=<handler> { ADDRESS=<udf_server_address> | AS <language_codes> } "
5036
5037 )(i)
5038}
5039
5040fn udf_immutable(i: Input) -> IResult<bool> {
5041 alt((
5042 value(false, rule! { VOLATILE }),
5043 value(true, rule! { IMMUTABLE }),
5044 ))(i)
5045}
5046
5047pub fn mutation_update_expr(i: Input) -> IResult<MutationUpdateExpr> {
5048 map(
5049 rule! { #dot_separated_idents_1_to_2 ~ "=" ~ ^#expr },
5050 |((table, name), _, expr)| MutationUpdateExpr { table, name, expr },
5051 )(i)
5052}
5053
5054pub fn password_set_options(i: Input) -> IResult<PasswordSetOptions> {
5055 map(
5056 rule! {
5057 ( PASSWORD_MIN_LENGTH ~ Eq ~ ^#literal_u64 )?
5058 ~ ( PASSWORD_MAX_LENGTH ~ Eq ~ ^#literal_u64 )?
5059 ~ ( PASSWORD_MIN_UPPER_CASE_CHARS ~ Eq ~ ^#literal_u64 )?
5060 ~ ( PASSWORD_MIN_LOWER_CASE_CHARS ~ Eq ~ ^#literal_u64 )?
5061 ~ ( PASSWORD_MIN_NUMERIC_CHARS ~ Eq ~ ^#literal_u64 )?
5062 ~ ( PASSWORD_MIN_SPECIAL_CHARS ~ Eq ~ ^#literal_u64 )?
5063 ~ ( PASSWORD_MIN_AGE_DAYS ~ Eq ~ ^#literal_u64 )?
5064 ~ ( PASSWORD_MAX_AGE_DAYS ~ Eq ~ ^#literal_u64 )?
5065 ~ ( PASSWORD_MAX_RETRIES ~ Eq ~ ^#literal_u64 )?
5066 ~ ( PASSWORD_LOCKOUT_TIME_MINS ~ Eq ~ ^#literal_u64 )?
5067 ~ ( PASSWORD_HISTORY ~ Eq ~ ^#literal_u64 )?
5068 ~ ( COMMENT ~ Eq ~ ^#literal_string)?
5069 },
5070 |(
5071 opt_min_length,
5072 opt_max_length,
5073 opt_min_upper_case_chars,
5074 opt_min_lower_case_chars,
5075 opt_min_numeric_chars,
5076 opt_min_special_chars,
5077 opt_min_age_days,
5078 opt_max_age_days,
5079 opt_max_retries,
5080 opt_lockout_time_mins,
5081 opt_history,
5082 opt_comment,
5083 )| {
5084 PasswordSetOptions {
5085 min_length: opt_min_length.map(|opt| opt.2),
5086 max_length: opt_max_length.map(|opt| opt.2),
5087 min_upper_case_chars: opt_min_upper_case_chars.map(|opt| opt.2),
5088 min_lower_case_chars: opt_min_lower_case_chars.map(|opt| opt.2),
5089 min_numeric_chars: opt_min_numeric_chars.map(|opt| opt.2),
5090 min_special_chars: opt_min_special_chars.map(|opt| opt.2),
5091 min_age_days: opt_min_age_days.map(|opt| opt.2),
5092 max_age_days: opt_max_age_days.map(|opt| opt.2),
5093 max_retries: opt_max_retries.map(|opt| opt.2),
5094 lockout_time_mins: opt_lockout_time_mins.map(|opt| opt.2),
5095 history: opt_history.map(|opt| opt.2),
5096 comment: opt_comment.map(|opt| opt.2),
5097 }
5098 },
5099 )(i)
5100}
5101
5102pub fn password_unset_options(i: Input) -> IResult<PasswordUnSetOptions> {
5103 map(
5104 rule! {
5105 PASSWORD_MIN_LENGTH?
5106 ~ PASSWORD_MAX_LENGTH?
5107 ~ PASSWORD_MIN_UPPER_CASE_CHARS?
5108 ~ PASSWORD_MIN_LOWER_CASE_CHARS?
5109 ~ PASSWORD_MIN_NUMERIC_CHARS?
5110 ~ PASSWORD_MIN_SPECIAL_CHARS?
5111 ~ PASSWORD_MIN_AGE_DAYS?
5112 ~ PASSWORD_MAX_AGE_DAYS?
5113 ~ PASSWORD_MAX_RETRIES?
5114 ~ PASSWORD_LOCKOUT_TIME_MINS?
5115 ~ PASSWORD_HISTORY?
5116 ~ COMMENT?
5117 },
5118 |(
5119 opt_min_length,
5120 opt_max_length,
5121 opt_min_upper_case_chars,
5122 opt_min_lower_case_chars,
5123 opt_min_numeric_chars,
5124 opt_min_special_chars,
5125 opt_min_age_days,
5126 opt_max_age_days,
5127 opt_max_retries,
5128 opt_lockout_time_mins,
5129 opt_history,
5130 opt_comment,
5131 )| {
5132 PasswordUnSetOptions {
5133 min_length: opt_min_length.is_some(),
5134 max_length: opt_max_length.is_some(),
5135 min_upper_case_chars: opt_min_upper_case_chars.is_some(),
5136 min_lower_case_chars: opt_min_lower_case_chars.is_some(),
5137 min_numeric_chars: opt_min_numeric_chars.is_some(),
5138 min_special_chars: opt_min_special_chars.is_some(),
5139 min_age_days: opt_min_age_days.is_some(),
5140 max_age_days: opt_max_age_days.is_some(),
5141 max_retries: opt_max_retries.is_some(),
5142 lockout_time_mins: opt_lockout_time_mins.is_some(),
5143 history: opt_history.is_some(),
5144 comment: opt_comment.is_some(),
5145 }
5146 },
5147 )(i)
5148}
5149
5150pub fn alter_password_action(i: Input) -> IResult<AlterPasswordAction> {
5151 let set_options = map(
5152 rule! {
5153 SET ~ #password_set_options
5154 },
5155 |(_, set_options)| AlterPasswordAction::SetOptions(set_options),
5156 );
5157 let unset_options = map(
5158 rule! {
5159 UNSET ~ #password_unset_options
5160 },
5161 |(_, unset_options)| AlterPasswordAction::UnSetOptions(unset_options),
5162 );
5163
5164 rule!(
5165 #set_options
5166 | #unset_options
5167 )(i)
5168}
5169
5170pub fn explain_option(i: Input) -> IResult<ExplainOption> {
5171 map(
5172 rule! {
5173 VERBOSE | LOGICAL | OPTIMIZED | DECORRELATED
5174 },
5175 |opt| match &opt.kind {
5176 VERBOSE => ExplainOption::Verbose,
5177 LOGICAL => ExplainOption::Logical,
5178 OPTIMIZED => ExplainOption::Optimized,
5179 DECORRELATED => ExplainOption::Decorrelated,
5180 _ => unreachable!(),
5181 },
5182 )(i)
5183}
5184
5185pub fn create_task_option(i: Input) -> IResult<CreateTaskOption> {
5186 let warehouse_opt = map(
5187 rule! {
5188 (WAREHOUSE ~ "=" ~ #literal_string)
5189 },
5190 |(_, _, warehouse)| CreateTaskOption::Warehouse(warehouse),
5191 );
5192 let schedule_opt = map(
5193 rule! {
5194 SCHEDULE ~ "=" ~ #task_schedule_option
5195 },
5196 |(_, _, schedule)| CreateTaskOption::Schedule(schedule),
5197 );
5198 let after_opt = map(
5199 rule! {
5200 AFTER ~ #comma_separated_list0(literal_string)
5201 },
5202 |(_, after)| CreateTaskOption::After(after),
5203 );
5204 let when_opt = map(
5205 rule! {
5206 WHEN ~ #expr
5207 },
5208 |(_, expr)| CreateTaskOption::When(expr),
5209 );
5210 let suspend_task_after_num_failures_opt = map(
5211 rule! {
5212 SUSPEND_TASK_AFTER_NUM_FAILURES ~ "=" ~ #literal_u64
5213 },
5214 |(_, _, num)| CreateTaskOption::SuspendTaskAfterNumFailures(num),
5215 );
5216 let error_integration_opt = map(
5217 rule! {
5218 ERROR_INTEGRATION ~ "=" ~ #literal_string
5219 },
5220 |(_, _, integration)| CreateTaskOption::ErrorIntegration(integration),
5221 );
5222 let comment_opt = map(
5223 rule! {
5224 (COMMENT | COMMENTS) ~ "=" ~ #literal_string
5225 },
5226 |(_, _, comment)| CreateTaskOption::Comment(comment),
5227 );
5228
5229 map(
5230 rule! {
5231 #warehouse_opt
5232 | #schedule_opt
5233 | #after_opt
5234 | #when_opt
5235 | #suspend_task_after_num_failures_opt
5236 | #error_integration_opt
5237 | #comment_opt
5238 },
5239 |opt| opt,
5240 )(i)
5241}
5242
5243fn alter_task_set_option(i: Input) -> IResult<AlterTaskSetOption> {
5244 let warehouse_opt = map(
5245 rule! {
5246 (WAREHOUSE ~ "=" ~ #literal_string)
5247 },
5248 |(_, _, warehouse)| AlterTaskSetOption::Warehouse(warehouse),
5249 );
5250 let schedule_opt = map(
5251 rule! {
5252 SCHEDULE ~ "=" ~ #task_schedule_option
5253 },
5254 |(_, _, schedule)| AlterTaskSetOption::Schedule(schedule),
5255 );
5256 let suspend_task_after_num_failures_opt = map(
5257 rule! {
5258 SUSPEND_TASK_AFTER_NUM_FAILURES ~ "=" ~ #literal_u64
5259 },
5260 |(_, _, num)| AlterTaskSetOption::SuspendTaskAfterNumFailures(num),
5261 );
5262 let error_integration_opt = map(
5263 rule! {
5264 ERROR_INTEGRATION ~ "=" ~ #literal_string
5265 },
5266 |(_, _, integration)| AlterTaskSetOption::ErrorIntegration(integration),
5267 );
5268 let comment_opt = map(
5269 rule! {
5270 (COMMENT | COMMENTS) ~ "=" ~ #literal_string
5271 },
5272 |(_, _, comment)| AlterTaskSetOption::Comment(comment),
5273 );
5274
5275 map(
5276 rule! {
5277 #warehouse_opt
5278 | #schedule_opt
5279 | #suspend_task_after_num_failures_opt
5280 | #error_integration_opt
5281 | #comment_opt
5282 },
5283 |opt| opt,
5284 )(i)
5285}
5286
5287pub fn notification_webhook_options(i: Input) -> IResult<NotificationWebhookOptions> {
5288 let url_option = map(
5289 rule! {
5290 URL ~ "=" ~ #literal_string
5291 },
5292 |(_, _, v)| ("url".to_string(), v.to_string()),
5293 );
5294 let method_option = map(
5295 rule! {
5296 METHOD ~ "=" ~ #literal_string
5297 },
5298 |(_, _, v)| ("method".to_string(), v.to_string()),
5299 );
5300 let auth_option = map(
5301 rule! {
5302 AUTHORIZATION_HEADER ~ "=" ~ #literal_string
5303 },
5304 |(_, _, v)| ("authorization_header".to_string(), v.to_string()),
5305 );
5306
5307 map(
5308 rule! { ((
5309 #url_option
5310 | #method_option
5311 | #auth_option) ~ ","?)* },
5312 |opts| {
5313 NotificationWebhookOptions::from_iter(
5314 opts.iter().map(|((k, v), _)| (k.to_uppercase(), v.clone())),
5315 )
5316 },
5317 )(i)
5318}
5319
5320pub fn notification_webhook_clause(i: Input) -> IResult<NotificationWebhookOptions> {
5321 map(
5322 rule! { WEBHOOK ~ ^"=" ~ ^"(" ~ ^#notification_webhook_options ~ ^")" },
5323 |(_, _, _, opts, _)| opts,
5324 )(i)
5325}
5326
5327pub fn alter_notification_options(i: Input) -> IResult<AlterNotificationOptions> {
5328 let enabled = map(
5329 rule! {
5330 SET ~ ENABLED ~ ^"=" ~ #literal_bool
5331 },
5332 |(_, _, _, enabled)| {
5333 AlterNotificationOptions::Set(AlterNotificationSetOptions::enabled(enabled))
5334 },
5335 );
5336 let webhook = map(
5337 rule! {
5338 SET ~ #notification_webhook_clause
5339 },
5340 |(_, webhook)| {
5341 AlterNotificationOptions::Set(AlterNotificationSetOptions::webhook_opts(webhook))
5342 },
5343 );
5344 let comment = map(
5345 rule! {
5346 SET ~ (COMMENT | COMMENTS) ~ ^"=" ~ #literal_string
5347 },
5348 |(_, _, _, comment)| {
5349 AlterNotificationOptions::Set(AlterNotificationSetOptions::comments(comment))
5350 },
5351 );
5352 map(
5353 rule! {
5354 #enabled
5355 | #webhook
5356 | #comment
5357 },
5358 |opts| opts,
5359 )(i)
5360}
5361
5362fn index_type(i: Input) -> IResult<TableIndexType> {
5363 alt((
5364 value(TableIndexType::Inverted, rule! { INVERTED }),
5365 value(TableIndexType::Ngram, rule! { NGRAM }),
5366 value(TableIndexType::Vector, rule! { VECTOR }),
5367 ))(i)
5368}