1use std::collections::BTreeMap;
16use std::fmt::Display;
17use std::fmt::Formatter;
18
19use derive_visitor::Drive;
20use derive_visitor::DriveMut;
21
22use super::CreateOption;
23use crate::ast::Expr;
24use crate::ast::Identifier;
25use crate::ast::ShowLimit;
26use crate::ast::quote::QuotedString;
27use crate::ast::write_comma_separated_string_list;
28use crate::ast::write_comma_separated_string_map;
29
30#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
31pub enum TaskSql {
32 SingleStatement(String),
33 ScriptBlock(Vec<String>),
34}
35
36impl Display for TaskSql {
37 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
38 match self {
39 TaskSql::SingleStatement(stmt) => write!(f, "{}", stmt),
40 TaskSql::ScriptBlock(stmts) => {
41 writeln!(f, "BEGIN")?;
42 for stmt in stmts {
43 writeln!(f, "{};", stmt)?;
44 }
45 write!(f, "END;")?;
46 Ok(())
47 }
48 }
49 }
50}
51
52#[derive(Debug, Clone, PartialEq)]
53#[allow(clippy::large_enum_variant)]
54pub enum CreateTaskOption {
55 Warehouse(String),
56 Schedule(ScheduleOptions),
57 After(Vec<String>),
58 When(Expr),
59 SuspendTaskAfterNumFailures(u64),
60 ErrorIntegration(String),
61 Comment(String),
62}
63
64#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
65pub struct CreateTaskStmt {
66 pub create_option: CreateOption,
67 pub name: String,
68 pub warehouse: Option<String>,
69 pub schedule_opts: Option<ScheduleOptions>,
70 pub session_parameters: BTreeMap<String, String>,
71 pub suspend_task_after_num_failures: Option<u64>,
72 pub error_integration: Option<String>,
74 pub comments: Option<String>,
75 pub after: Vec<String>,
76 pub when_condition: Option<Expr>,
77 pub sql: TaskSql,
78}
79
80impl CreateTaskStmt {
81 pub fn apply_opt(&mut self, opt: CreateTaskOption) {
82 match opt {
83 CreateTaskOption::Warehouse(wh) => {
84 self.warehouse = Some(wh);
85 }
86 CreateTaskOption::Schedule(schedule) => {
87 self.schedule_opts = Some(schedule);
88 }
89 CreateTaskOption::After(after) => {
90 self.after = after;
91 }
92 CreateTaskOption::When(when) => {
93 self.when_condition = Some(when);
94 }
95 CreateTaskOption::SuspendTaskAfterNumFailures(num) => {
96 self.suspend_task_after_num_failures = Some(num);
97 }
98 CreateTaskOption::ErrorIntegration(integration) => {
99 self.error_integration = Some(integration);
100 }
101 CreateTaskOption::Comment(comment) => {
102 self.comments = Some(comment);
103 }
104 }
105 }
106}
107
108impl Display for CreateTaskStmt {
109 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
110 write!(f, "CREATE")?;
111 if let CreateOption::CreateOrReplace = self.create_option {
112 write!(f, " OR REPLACE")?;
113 }
114 write!(f, " TASK")?;
115 if let CreateOption::CreateIfNotExists = self.create_option {
116 write!(f, " IF NOT EXISTS")?;
117 }
118 write!(f, " {}", self.name)?;
119
120 if let Some(warehouse) = self.warehouse.as_ref() {
121 write!(f, " WAREHOUSE = '{}'", warehouse)?;
122 }
123
124 if let Some(schedule_opt) = self.schedule_opts.as_ref() {
125 write!(f, " SCHEDULE = {}", schedule_opt)?;
126 }
127
128 if let Some(num) = self.suspend_task_after_num_failures {
129 write!(f, " SUSPEND_TASK_AFTER_NUM_FAILURES = {}", num)?;
130 }
131
132 if !self.after.is_empty() {
133 write!(f, " AFTER ")?;
134 write_comma_separated_string_list(f, &self.after)?;
135 }
136
137 if let Some(when_condition) = &self.when_condition {
138 write!(f, " WHEN {}", when_condition)?;
139 }
140 if let Some(error_integration) = &self.error_integration {
141 write!(f, " ERROR_INTEGRATION = '{}'", error_integration)?;
142 }
143
144 if let Some(comments) = &self.comments {
145 write!(f, " COMMENTS = '{}'", comments)?;
146 }
147
148 if !self.session_parameters.is_empty() {
149 write!(f, " ")?;
150 write_comma_separated_string_map(f, &self.session_parameters)?;
151 }
152
153 write!(f, " AS {}", self.sql)?;
154
155 Ok(())
156 }
157}
158
159#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
160pub struct WarehouseOptions {
161 pub warehouse: Option<String>,
162}
163
164impl Display for WarehouseOptions {
165 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
166 if let Some(wh) = &self.warehouse {
167 write!(f, "WAREHOUSE = '{}'", wh)?;
168 }
169 Ok(())
170 }
171}
172
173#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
174pub enum ScheduleOptions {
175 IntervalSecs(u64, u64),
176 CronExpression(String, Option<String>),
177}
178
179impl Display for ScheduleOptions {
180 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
181 match self {
182 ScheduleOptions::IntervalSecs(secs, ms) => {
183 if *ms > 0 {
184 write!(f, "{} MILLISECOND", ms)?;
185 Ok(())
186 } else {
187 write!(f, "{} SECOND", secs)?;
188 Ok(())
189 }
190 }
191 ScheduleOptions::CronExpression(expr, tz) => {
192 write!(f, "USING CRON '{}'", expr)?;
193 if let Some(tz) = tz {
194 write!(f, " '{}'", tz)?;
195 }
196 Ok(())
197 }
198 }
199 }
200}
201
202#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
203pub struct AlterTaskStmt {
204 pub if_exists: bool,
205 pub name: String,
206 pub options: AlterTaskOptions,
207}
208
209impl Display for AlterTaskStmt {
210 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
211 write!(f, "ALTER TASK")?;
212 if self.if_exists {
213 write!(f, " IF EXISTS")?;
214 }
215 write!(f, " {}", self.name)?;
216 write!(f, " {}", self.options)?;
217 Ok(())
218 }
219}
220
221#[derive(Debug, Clone, PartialEq)]
222pub enum AlterTaskSetOption {
223 Warehouse(String),
224 Schedule(ScheduleOptions),
225 SuspendTaskAfterNumFailures(u64),
226 ErrorIntegration(String),
227 Comment(String),
228}
229
230#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
231pub enum AlterTaskOptions {
232 Resume,
233 Suspend,
234 Set {
235 warehouse: Option<String>,
236 schedule: Option<ScheduleOptions>,
237 suspend_task_after_num_failures: Option<u64>,
238 comments: Option<String>,
239 session_parameters: Option<BTreeMap<String, String>>,
240 error_integration: Option<String>,
241 },
242 Unset {
243 warehouse: bool,
244 },
245 ModifyAs(TaskSql),
247 ModifyWhen(Expr),
248 AddAfter(Vec<String>),
249 RemoveAfter(Vec<String>),
250}
251
252impl AlterTaskOptions {
253 pub fn apply_opt(&mut self, opt: AlterTaskSetOption) {
254 if let AlterTaskOptions::Set {
255 warehouse,
256 schedule,
257 suspend_task_after_num_failures,
258 session_parameters: _,
259 error_integration,
260 comments,
261 } = self
262 {
263 match opt {
264 AlterTaskSetOption::Warehouse(wh) => {
265 *warehouse = Some(wh);
266 }
267 AlterTaskSetOption::Schedule(s) => {
268 *schedule = Some(s);
269 }
270 AlterTaskSetOption::ErrorIntegration(integration) => {
271 *error_integration = Some(integration);
272 }
273 AlterTaskSetOption::SuspendTaskAfterNumFailures(num) => {
274 *suspend_task_after_num_failures = Some(num);
275 }
276 AlterTaskSetOption::Comment(comment) => {
277 *comments = Some(comment);
278 }
279 }
280 }
281 }
282}
283
284impl Display for AlterTaskOptions {
285 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
286 match self {
287 AlterTaskOptions::Resume => write!(f, "RESUME"),
288 AlterTaskOptions::Suspend => write!(f, "SUSPEND"),
289 AlterTaskOptions::Set {
290 warehouse,
291 schedule,
292 suspend_task_after_num_failures,
293 session_parameters,
294 error_integration,
295 comments,
296 } => {
297 write!(f, "SET")?;
298 if let Some(wh) = warehouse {
299 write!(f, " WAREHOUSE = '{wh}'")?;
300 }
301 if let Some(schedule) = schedule {
302 write!(f, " SCHEDULE = {schedule}")?;
303 }
304 if let Some(num) = suspend_task_after_num_failures {
305 write!(f, " SUSPEND_TASK_AFTER_NUM_FAILURES = {num}")?;
306 }
307 if let Some(comments) = comments {
308 write!(f, " COMMENT = {}", QuotedString(comments, '\''))?;
309 }
310 if let Some(error_integration) = error_integration {
311 write!(f, " ERROR_INTEGRATION = '{error_integration}'")?;
312 }
313 if let Some(session) = session_parameters {
314 write!(f, " ")?;
315 write_comma_separated_string_map(f, session)?;
316 }
317 Ok(())
318 }
319 AlterTaskOptions::Unset { warehouse } => {
320 if *warehouse {
321 write!(f, "UNSET WAREHOUSE")?;
322 }
323 Ok(())
324 }
325 AlterTaskOptions::ModifyAs(sql) => write!(f, "MODIFY AS {sql}"),
326 AlterTaskOptions::ModifyWhen(expr) => write!(f, "MODIFY WHEN {expr}"),
327 AlterTaskOptions::AddAfter(after) => {
328 write!(f, "ADD AFTER ")?;
329 write_comma_separated_string_list(f, after)
330 }
331 AlterTaskOptions::RemoveAfter(after) => {
332 write!(f, "REMOVE AFTER ")?;
333 write_comma_separated_string_list(f, after)
334 }
335 }
336 }
337}
338
339#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
340pub struct DropTaskStmt {
341 pub if_exists: bool,
342 pub name: String,
343}
344
345impl Display for DropTaskStmt {
346 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
347 write!(f, "DROP TASK")?;
348 if self.if_exists {
349 write!(f, " IF EXISTS")?;
350 }
351 write!(f, " {}", self.name)
352 }
353}
354
355#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
356pub struct ShowTasksStmt {
357 pub limit: Option<ShowLimit>,
358}
359
360impl Display for ShowTasksStmt {
361 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
362 write!(f, "SHOW ")?;
363 write!(f, "TASKS")?;
364 if let Some(limit) = &self.limit {
365 write!(f, " {limit}")?;
366 }
367
368 Ok(())
369 }
370}
371
372#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
373pub struct ExecuteTaskStmt {
374 pub name: Identifier,
375}
376
377impl Display for ExecuteTaskStmt {
378 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
379 write!(f, "EXECUTE TASK {}", self.name)
380 }
381}
382
383#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
384pub struct DescribeTaskStmt {
385 pub name: Identifier,
386}
387
388impl Display for DescribeTaskStmt {
389 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
390 write!(f, "DESCRIBE TASK {}", self.name)
391 }
392}