1#[cfg(not(feature = "std"))]
19use alloc::{boxed::Box, format, string::String, vec, vec::Vec};
20
21#[cfg(feature = "serde")]
22use serde::{Deserialize, Serialize};
23
24#[cfg(feature = "visitor")]
25use sqltk_parser_derive::{Visit, VisitMut};
26
27use super::super::dml::CreateTable;
28use crate::ast::{
29 ClusteredBy, ColumnDef, CommentDef, Expr, FileFormat, HiveDistributionStyle, HiveFormat, Ident,
30 ObjectName, OnCommit, OneOrManyWithParens, Query, RowAccessPolicy, SqlOption, Statement,
31 TableConstraint, TableEngine, Tag, WrappedCollection,
32};
33use crate::parser::ParserError;
34
35#[derive(Debug, Clone, PartialEq, Eq, Hash)]
64#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
65#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
66pub struct CreateTableBuilder {
67 pub or_replace: bool,
68 pub temporary: bool,
69 pub external: bool,
70 pub global: Option<bool>,
71 pub if_not_exists: bool,
72 pub transient: bool,
73 pub volatile: bool,
74 pub name: ObjectName,
75 pub columns: Vec<ColumnDef>,
76 pub constraints: Vec<TableConstraint>,
77 pub hive_distribution: HiveDistributionStyle,
78 pub hive_formats: Option<HiveFormat>,
79 pub table_properties: Vec<SqlOption>,
80 pub with_options: Vec<SqlOption>,
81 pub file_format: Option<FileFormat>,
82 pub location: Option<String>,
83 pub query: Option<Box<Query>>,
84 pub without_rowid: bool,
85 pub like: Option<ObjectName>,
86 pub clone: Option<ObjectName>,
87 pub engine: Option<TableEngine>,
88 pub comment: Option<CommentDef>,
89 pub auto_increment_offset: Option<u32>,
90 pub default_charset: Option<String>,
91 pub collation: Option<String>,
92 pub on_commit: Option<OnCommit>,
93 pub on_cluster: Option<Ident>,
94 pub primary_key: Option<Box<Expr>>,
95 pub order_by: Option<OneOrManyWithParens<Expr>>,
96 pub partition_by: Option<Box<Expr>>,
97 pub cluster_by: Option<WrappedCollection<Vec<Ident>>>,
98 pub clustered_by: Option<ClusteredBy>,
99 pub options: Option<Vec<SqlOption>>,
100 pub strict: bool,
101 pub copy_grants: bool,
102 pub enable_schema_evolution: Option<bool>,
103 pub change_tracking: Option<bool>,
104 pub data_retention_time_in_days: Option<u64>,
105 pub max_data_extension_time_in_days: Option<u64>,
106 pub default_ddl_collation: Option<String>,
107 pub with_aggregation_policy: Option<ObjectName>,
108 pub with_row_access_policy: Option<RowAccessPolicy>,
109 pub with_tags: Option<Vec<Tag>>,
110}
111
112impl CreateTableBuilder {
113 pub fn new(name: ObjectName) -> Self {
114 Self {
115 or_replace: false,
116 temporary: false,
117 external: false,
118 global: None,
119 if_not_exists: false,
120 transient: false,
121 volatile: false,
122 name,
123 columns: vec![],
124 constraints: vec![],
125 hive_distribution: HiveDistributionStyle::NONE,
126 hive_formats: None,
127 table_properties: vec![],
128 with_options: vec![],
129 file_format: None,
130 location: None,
131 query: None,
132 without_rowid: false,
133 like: None,
134 clone: None,
135 engine: None,
136 comment: None,
137 auto_increment_offset: None,
138 default_charset: None,
139 collation: None,
140 on_commit: None,
141 on_cluster: None,
142 primary_key: None,
143 order_by: None,
144 partition_by: None,
145 cluster_by: None,
146 clustered_by: None,
147 options: None,
148 strict: false,
149 copy_grants: false,
150 enable_schema_evolution: None,
151 change_tracking: None,
152 data_retention_time_in_days: None,
153 max_data_extension_time_in_days: None,
154 default_ddl_collation: None,
155 with_aggregation_policy: None,
156 with_row_access_policy: None,
157 with_tags: None,
158 }
159 }
160 pub fn or_replace(mut self, or_replace: bool) -> Self {
161 self.or_replace = or_replace;
162 self
163 }
164
165 pub fn temporary(mut self, temporary: bool) -> Self {
166 self.temporary = temporary;
167 self
168 }
169
170 pub fn external(mut self, external: bool) -> Self {
171 self.external = external;
172 self
173 }
174
175 pub fn global(mut self, global: Option<bool>) -> Self {
176 self.global = global;
177 self
178 }
179
180 pub fn if_not_exists(mut self, if_not_exists: bool) -> Self {
181 self.if_not_exists = if_not_exists;
182 self
183 }
184
185 pub fn transient(mut self, transient: bool) -> Self {
186 self.transient = transient;
187 self
188 }
189
190 pub fn volatile(mut self, volatile: bool) -> Self {
191 self.volatile = volatile;
192 self
193 }
194
195 pub fn columns(mut self, columns: Vec<ColumnDef>) -> Self {
196 self.columns = columns;
197 self
198 }
199
200 pub fn constraints(mut self, constraints: Vec<TableConstraint>) -> Self {
201 self.constraints = constraints;
202 self
203 }
204
205 pub fn hive_distribution(mut self, hive_distribution: HiveDistributionStyle) -> Self {
206 self.hive_distribution = hive_distribution;
207 self
208 }
209
210 pub fn hive_formats(mut self, hive_formats: Option<HiveFormat>) -> Self {
211 self.hive_formats = hive_formats;
212 self
213 }
214
215 pub fn table_properties(mut self, table_properties: Vec<SqlOption>) -> Self {
216 self.table_properties = table_properties;
217 self
218 }
219
220 pub fn with_options(mut self, with_options: Vec<SqlOption>) -> Self {
221 self.with_options = with_options;
222 self
223 }
224 pub fn file_format(mut self, file_format: Option<FileFormat>) -> Self {
225 self.file_format = file_format;
226 self
227 }
228 pub fn location(mut self, location: Option<String>) -> Self {
229 self.location = location;
230 self
231 }
232
233 pub fn query(mut self, query: Option<Box<Query>>) -> Self {
234 self.query = query;
235 self
236 }
237 pub fn without_rowid(mut self, without_rowid: bool) -> Self {
238 self.without_rowid = without_rowid;
239 self
240 }
241
242 pub fn like(mut self, like: Option<ObjectName>) -> Self {
243 self.like = like;
244 self
245 }
246
247 pub fn clone_clause(mut self, clone: Option<ObjectName>) -> Self {
249 self.clone = clone;
250 self
251 }
252
253 pub fn engine(mut self, engine: Option<TableEngine>) -> Self {
254 self.engine = engine;
255 self
256 }
257
258 pub fn comment(mut self, comment: Option<CommentDef>) -> Self {
259 self.comment = comment;
260 self
261 }
262
263 pub fn auto_increment_offset(mut self, offset: Option<u32>) -> Self {
264 self.auto_increment_offset = offset;
265 self
266 }
267
268 pub fn default_charset(mut self, default_charset: Option<String>) -> Self {
269 self.default_charset = default_charset;
270 self
271 }
272
273 pub fn collation(mut self, collation: Option<String>) -> Self {
274 self.collation = collation;
275 self
276 }
277
278 pub fn on_commit(mut self, on_commit: Option<OnCommit>) -> Self {
279 self.on_commit = on_commit;
280 self
281 }
282
283 pub fn on_cluster(mut self, on_cluster: Option<Ident>) -> Self {
284 self.on_cluster = on_cluster;
285 self
286 }
287
288 pub fn primary_key(mut self, primary_key: Option<Box<Expr>>) -> Self {
289 self.primary_key = primary_key;
290 self
291 }
292
293 pub fn order_by(mut self, order_by: Option<OneOrManyWithParens<Expr>>) -> Self {
294 self.order_by = order_by;
295 self
296 }
297
298 pub fn partition_by(mut self, partition_by: Option<Box<Expr>>) -> Self {
299 self.partition_by = partition_by;
300 self
301 }
302
303 pub fn cluster_by(mut self, cluster_by: Option<WrappedCollection<Vec<Ident>>>) -> Self {
304 self.cluster_by = cluster_by;
305 self
306 }
307
308 pub fn clustered_by(mut self, clustered_by: Option<ClusteredBy>) -> Self {
309 self.clustered_by = clustered_by;
310 self
311 }
312
313 pub fn options(mut self, options: Option<Vec<SqlOption>>) -> Self {
314 self.options = options;
315 self
316 }
317
318 pub fn strict(mut self, strict: bool) -> Self {
319 self.strict = strict;
320 self
321 }
322
323 pub fn copy_grants(mut self, copy_grants: bool) -> Self {
324 self.copy_grants = copy_grants;
325 self
326 }
327
328 pub fn enable_schema_evolution(mut self, enable_schema_evolution: Option<bool>) -> Self {
329 self.enable_schema_evolution = enable_schema_evolution;
330 self
331 }
332
333 pub fn change_tracking(mut self, change_tracking: Option<bool>) -> Self {
334 self.change_tracking = change_tracking;
335 self
336 }
337
338 pub fn data_retention_time_in_days(mut self, data_retention_time_in_days: Option<u64>) -> Self {
339 self.data_retention_time_in_days = data_retention_time_in_days;
340 self
341 }
342
343 pub fn max_data_extension_time_in_days(
344 mut self,
345 max_data_extension_time_in_days: Option<u64>,
346 ) -> Self {
347 self.max_data_extension_time_in_days = max_data_extension_time_in_days;
348 self
349 }
350
351 pub fn default_ddl_collation(mut self, default_ddl_collation: Option<String>) -> Self {
352 self.default_ddl_collation = default_ddl_collation;
353 self
354 }
355
356 pub fn with_aggregation_policy(mut self, with_aggregation_policy: Option<ObjectName>) -> Self {
357 self.with_aggregation_policy = with_aggregation_policy;
358 self
359 }
360
361 pub fn with_row_access_policy(
362 mut self,
363 with_row_access_policy: Option<RowAccessPolicy>,
364 ) -> Self {
365 self.with_row_access_policy = with_row_access_policy;
366 self
367 }
368
369 pub fn with_tags(mut self, with_tags: Option<Vec<Tag>>) -> Self {
370 self.with_tags = with_tags;
371 self
372 }
373
374 pub fn build(self) -> Statement {
375 Statement::CreateTable(CreateTable {
376 or_replace: self.or_replace,
377 temporary: self.temporary,
378 external: self.external,
379 global: self.global,
380 if_not_exists: self.if_not_exists,
381 transient: self.transient,
382 volatile: self.volatile,
383 name: self.name,
384 columns: self.columns,
385 constraints: self.constraints,
386 hive_distribution: self.hive_distribution,
387 hive_formats: self.hive_formats,
388 table_properties: self.table_properties,
389 with_options: self.with_options,
390 file_format: self.file_format,
391 location: self.location,
392 query: self.query,
393 without_rowid: self.without_rowid,
394 like: self.like,
395 clone: self.clone,
396 engine: self.engine,
397 comment: self.comment,
398 auto_increment_offset: self.auto_increment_offset,
399 default_charset: self.default_charset,
400 collation: self.collation,
401 on_commit: self.on_commit,
402 on_cluster: self.on_cluster,
403 primary_key: self.primary_key,
404 order_by: self.order_by,
405 partition_by: self.partition_by,
406 cluster_by: self.cluster_by,
407 clustered_by: self.clustered_by,
408 options: self.options,
409 strict: self.strict,
410 copy_grants: self.copy_grants,
411 enable_schema_evolution: self.enable_schema_evolution,
412 change_tracking: self.change_tracking,
413 data_retention_time_in_days: self.data_retention_time_in_days,
414 max_data_extension_time_in_days: self.max_data_extension_time_in_days,
415 default_ddl_collation: self.default_ddl_collation,
416 with_aggregation_policy: self.with_aggregation_policy,
417 with_row_access_policy: self.with_row_access_policy,
418 with_tags: self.with_tags,
419 })
420 }
421}
422
423impl TryFrom<Statement> for CreateTableBuilder {
424 type Error = ParserError;
425
426 fn try_from(stmt: Statement) -> Result<Self, Self::Error> {
429 match stmt {
430 Statement::CreateTable(CreateTable {
431 or_replace,
432 temporary,
433 external,
434 global,
435 if_not_exists,
436 transient,
437 volatile,
438 name,
439 columns,
440 constraints,
441 hive_distribution,
442 hive_formats,
443 table_properties,
444 with_options,
445 file_format,
446 location,
447 query,
448 without_rowid,
449 like,
450 clone,
451 engine,
452 comment,
453 auto_increment_offset,
454 default_charset,
455 collation,
456 on_commit,
457 on_cluster,
458 primary_key,
459 order_by,
460 partition_by,
461 cluster_by,
462 clustered_by,
463 options,
464 strict,
465 copy_grants,
466 enable_schema_evolution,
467 change_tracking,
468 data_retention_time_in_days,
469 max_data_extension_time_in_days,
470 default_ddl_collation,
471 with_aggregation_policy,
472 with_row_access_policy,
473 with_tags,
474 }) => Ok(Self {
475 or_replace,
476 temporary,
477 external,
478 global,
479 if_not_exists,
480 transient,
481 name,
482 columns,
483 constraints,
484 hive_distribution,
485 hive_formats,
486 table_properties,
487 with_options,
488 file_format,
489 location,
490 query,
491 without_rowid,
492 like,
493 clone,
494 engine,
495 comment,
496 auto_increment_offset,
497 default_charset,
498 collation,
499 on_commit,
500 on_cluster,
501 primary_key,
502 order_by,
503 partition_by,
504 cluster_by,
505 clustered_by,
506 options,
507 strict,
508 copy_grants,
509 enable_schema_evolution,
510 change_tracking,
511 data_retention_time_in_days,
512 max_data_extension_time_in_days,
513 default_ddl_collation,
514 with_aggregation_policy,
515 with_row_access_policy,
516 with_tags,
517 volatile,
518 }),
519 _ => Err(ParserError::ParserError(format!(
520 "Expected create table statement, but received: {stmt}"
521 ))),
522 }
523 }
524}
525
526#[derive(Default)]
528pub(crate) struct CreateTableConfiguration {
529 pub partition_by: Option<Box<Expr>>,
530 pub cluster_by: Option<WrappedCollection<Vec<Ident>>>,
531 pub options: Option<Vec<SqlOption>>,
532}
533
534#[cfg(test)]
535mod tests {
536 use crate::ast::helpers::stmt_create_table::CreateTableBuilder;
537 use crate::ast::{Ident, ObjectName, Statement};
538 use crate::parser::ParserError;
539
540 #[test]
541 pub fn test_from_valid_statement() {
542 let builder = CreateTableBuilder::new(ObjectName(vec![Ident::new("table_name")]));
543
544 let stmt = builder.clone().build();
545
546 assert_eq!(builder, CreateTableBuilder::try_from(stmt).unwrap());
547 }
548
549 #[test]
550 pub fn test_from_invalid_statement() {
551 let stmt = Statement::Commit { chain: false };
552
553 assert_eq!(
554 CreateTableBuilder::try_from(stmt).unwrap_err(),
555 ParserError::ParserError(
556 "Expected create table statement, but received: COMMIT".to_owned()
557 )
558 );
559 }
560}