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