Skip to main content

databend_common_ast/parser/
statement.rs

1// Copyright 2021 Datafuse Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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
50// (tenant, share name, endpoint name)
51pub 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    // kill query 199;
399    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    // catalogs
526    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    // TODO: support `COMMENT` in create catalog
539    // TODO: use a more specific option struct instead of BTreeMap
540    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    // parse `show fields from` statement
1047    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    // DICTIONARY
1331    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    // row policy
1934    // CREATE ROW ACCESS POLICY [ IF NOT EXISTS ] <name> AS
1935    // ( <arg_name> <arg_type> [ , ... ] ) RETURNS BOOLEAN -> <body>
1936    // [ COMMENT = '<string_literal>' ]
1937    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    // stages
2041    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    // connections
2123    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    // data mark policy
2259    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    // CREATE [ OR REPLACE ] PROCEDURE <name> ()
2660    // RETURNS { <result_data_type> }[ NOT NULL ]
2661    // LANGUAGE SQL
2662    // [ COMMENT = '<string_literal>' ] AS <procedure_definition>
2663    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    // fn procedure_type_name(i: Input) -> IResult<Vec<TypeName>> {
2717    // let procedure_type_names = map(
2718    // rule! {
2719    // "(" ~ #comma_separated_list1(type_name) ~ ")"
2720    // },
2721    // |(_, args, _)| args,
2722    // );
2723    // let procedure_empty_types = map(
2724    // rule! {
2725    // "(" ~ ")"
2726    // },
2727    // |(_, _)| vec![],
2728    // );
2729    // rule!(#procedure_empty_types: "()"
2730    // | #procedure_type_names: "(<type_name>, ...)").parse(i)
2731    // }
2732
2733    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
3283// `VALUES (expr, expr), (expr, expr)`
3284pub 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
3329// `INSERT INTO ... VALUES` statement will
3330// stop the parser immediately and return the rest tokens in `InsertSource`.
3331//
3332// This is a hack to parse large insert statements.
3333pub 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    //#ident ~ ( "(" ~ ^#comma_separated_list1(ident) ~ ")")?
3385    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    // It's safe to unwrap because input must contain EOI.
3490    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    // `db01`.'tb1' or `db01`.`tb1` or `db01`.tb1
4090    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    // *.*
4155    let global = map(rule! { "*" ~ "." ~ "*" }, |_| AccountMgrLevel::Global);
4156    // db.*
4157    // "*": as current db or "table" with current db
4158    let db = map(
4159        rule! {
4160            ( #ident ~ "." )? ~ "*"
4161        },
4162        |(database, _)| AccountMgrLevel::Database(database.map(|(database, _)| database.name)),
4163    );
4164
4165    // `db01`.'tb1' or `db01`.`tb1` or `db01`.tb1
4166    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    // *.*
4196    let global = map(rule! { "*" ~ "." ~ "*" }, |_| AccountMgrLevel::Global);
4197    // db.*
4198    // "*": as current db or "table" with current db
4199    let db = map(
4200        rule! {
4201            ( #ident ~ "." )? ~ "*"
4202        },
4203        |(database, _)| AccountMgrLevel::Database(database.map(|(database, _)| database.name)),
4204    );
4205
4206    // `db01`.'tb1' or `db01`.`tb1` or `db01`.tb1
4207    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    // db.*
4235    // "*": as current db or "table" with current db
4236    let db = map(
4237        rule! {
4238            ( #grant_ident ~ "." )? ~ "*"
4239        },
4240        |(database, _)| AccountMgrLevel::Database(database.map(|(database, _)| database.name)),
4241    );
4242
4243    // `db01`.'tb1' or `db01`.`tb1` or `db01`.tb1
4244    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    // Object object_name
4274    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    // Parse: <column> SET MASKING POLICY <policy_name> [USING (masked_col_name, cond_col_1, ...)]
4708    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    // NOTE: `AT (BRANCH|TAG => ...)` travel-point syntax is only supported when
4928    // creating a branch/tag via `ALTER TABLE ... CREATE`. It is intentionally not
4929    // available for SELECT or other query statements, so keep the parsing rule scoped
4930    // here to avoid implying broader support.
4931    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    // The action list is split to avoid the trait bound limit in `alt(...)`.
4967    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    // add other system action type here
5474    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                    // TODO inject runtime_version by user
5986                    // Now we use fixed runtime version
5987                    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                    // TODO inject runtime_version by user
6092                    // Now we use fixed runtime version
6093                    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}