databend_common_ast/parser/
dynamic_table.rs1use nom::branch::alt;
16use nom::branch::permutation;
17use nom::combinator::map;
18use nom::combinator::value;
19use nom_rule::rule;
20
21use crate::ast::ClusterOption;
22use crate::ast::ClusterType;
23use crate::ast::CreateDynamicTableStmt;
24use crate::ast::InitializeMode;
25use crate::ast::RefreshMode;
26use crate::ast::Statement;
27use crate::ast::TargetLag;
28use crate::ast::WarehouseOptions;
29use crate::parser::common::comma_separated_list1;
30use crate::parser::common::dot_separated_idents_1_to_3;
31use crate::parser::common::map_res;
32use crate::parser::common::IResult;
33use crate::parser::common::*;
34use crate::parser::expr::expr;
35use crate::parser::expr::literal_u64;
36use crate::parser::query::query;
37use crate::parser::statement::cluster_type;
38use crate::parser::statement::create_table_source;
39use crate::parser::statement::parse_create_option;
40use crate::parser::statement::table_option;
41use crate::parser::statement::task_warehouse_option;
42use crate::parser::token::TokenKind::*;
43use crate::parser::Input;
44
45pub fn dynamic_table(i: Input) -> IResult<Statement> {
46 rule!(
47 #create_dynamic_table : "`CREATE [OR REPLACE] [TRANSIENT] DYNAMIC TABLE [ IF NOT EXISTS ] [<database>.]<table> [<source>]
48 [ CLUSTER BY <expr> ]
49 TARGET_LAG = { <num> { SECOND | MINUTE | HOUR | DAY } | DOWNSTREAM}
50 [ { WAREHOUSE = <string> } ]
51 [ REFRESH_MODE = { AUTO | FULL | INCREMENTAL } ]
52 [ INITIALIZE = { ON_CREATE | ON_SCHEDULE } ]
53 [ COMMENT = '<string_literal>' ]
54AS
55 <sql>`"
56 )(i)
57}
58
59fn create_dynamic_table(i: Input) -> IResult<Statement> {
60 map_res(
61 rule! {
62 CREATE ~ ( OR ~ ^REPLACE )? ~ TRANSIENT? ~ DYNAMIC ~ TABLE ~ ( IF ~ ^NOT ~ ^EXISTS )?
63 ~ #dot_separated_idents_1_to_3
64 ~ #create_table_source?
65 ~ ( CLUSTER ~ ^BY ~ ( #cluster_type )? ~ ^"(" ~ ^#comma_separated_list1(expr) ~ ^")" )?
66 ~ #dynamic_table_options
67 ~ (#table_option)?
68 ~ (AS ~ ^#query)
69 },
70 |(
71 _,
72 opt_or_replace,
73 opt_transient,
74 _,
75 _,
76 opt_if_not_exists,
77 (catalog, database, table),
78 source,
79 opt_cluster_by,
80 (target_lag, warehouse_opts, refresh_mode_opt, initialize_opt),
81 opt_table_options,
82 (_, query),
83 )| {
84 let create_option =
85 parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?;
86 Ok(Statement::CreateDynamicTable(CreateDynamicTableStmt {
87 create_option,
88 transient: opt_transient.is_some(),
89 catalog,
90 database,
91 table,
92 source,
93 cluster_by: opt_cluster_by.map(|(_, _, typ, _, cluster_exprs, _)| ClusterOption {
94 cluster_type: typ.unwrap_or(ClusterType::Linear),
95 cluster_exprs,
96 }),
97 target_lag,
98 warehouse_opts,
99 refresh_mode: refresh_mode_opt.unwrap_or(RefreshMode::Auto),
100 initialize: initialize_opt.unwrap_or(InitializeMode::OnCreate),
101 table_options: opt_table_options.unwrap_or_default(),
102 as_query: Box::new(query),
103 }))
104 },
105 )(i)
106}
107
108fn dynamic_table_options(
109 i: Input,
110) -> IResult<(
111 TargetLag,
112 WarehouseOptions,
113 Option<RefreshMode>,
114 Option<InitializeMode>,
115)> {
116 let target_lag = map(
117 rule! {
118 TARGET_LAG ~ "=" ~ #target_lag
119 },
120 |(_, _, target_lag)| target_lag,
121 );
122
123 let refresh_mode = alt((
124 value(RefreshMode::Auto, rule! { AUTO }),
125 value(RefreshMode::Full, rule! { FULL }),
126 value(RefreshMode::Incremental, rule! { INCREMENTAL }),
127 ));
128 let refresh_mode_opt = map(
129 rule! {
130 (REFRESH_MODE ~ "=" ~ #refresh_mode)?
131 },
132 |v| v.map(|v| v.2),
133 );
134
135 let initialize_mode = alt((
136 value(InitializeMode::OnCreate, rule! { ON_CREATE }),
137 value(InitializeMode::OnSchedule, rule! { ON_SCHEDULE }),
138 ));
139 let initialize_opt = map(
140 rule! {
141 (INITIALIZE ~ "=" ~ #initialize_mode)?
142 },
143 |v| v.map(|v| v.2),
144 );
145
146 permutation((
147 target_lag,
148 task_warehouse_option,
149 refresh_mode_opt,
150 initialize_opt,
151 ))(i)
152}
153
154fn target_lag(i: Input) -> IResult<TargetLag> {
155 let interval_sec = map(
156 rule! {
157 #literal_u64 ~ SECOND
158 },
159 |(secs, _)| TargetLag::IntervalSecs(secs),
160 );
161 let interval_min = map(
162 rule! {
163 #literal_u64 ~ MINUTE
164 },
165 |(mins, _)| TargetLag::IntervalSecs(mins * 60),
166 );
167 let interval_hour = map(
168 rule! {
169 #literal_u64 ~ HOUR
170 },
171 |(hours, _)| TargetLag::IntervalSecs(hours * 60 * 60),
172 );
173 let interval_day = map(
174 rule! {
175 #literal_u64 ~ DAY
176 },
177 |(days, _)| TargetLag::IntervalSecs(days * 60 * 60 * 24),
178 );
179 let downstream = map(
180 rule! {
181 DOWNSTREAM
182 },
183 |_| TargetLag::Downstream,
184 );
185 rule!(
186 #interval_sec
187 | #interval_min
188 | #interval_hour
189 | #interval_day
190 | #downstream
191 )(i)
192}