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 sqlparser_derive::{Visit, VisitMut};
26
27use crate::ast::{
28 ClusteredBy, ColumnDef, CommentDef, CreateTable, CreateTableLikeKind, CreateTableOptions,
29 DistStyle, Expr, FileFormat, ForValues, HiveDistributionStyle, HiveFormat, Ident,
30 InitializeKind, ObjectName, OnCommit, OneOrManyWithParens, Query, RefreshModeKind,
31 RowAccessPolicy, Statement, StorageLifecyclePolicy, StorageSerializationPolicy,
32 TableConstraint, TableVersion, Tag, WrappedCollection,
33};
34
35use crate::parser::ParserError;
36
37#[derive(Debug, Clone, PartialEq, Eq, Hash)]
65#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
66#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
67pub struct CreateTableBuilder {
68 pub or_replace: bool,
70 pub temporary: bool,
72 pub external: bool,
74 pub global: Option<bool>,
76 pub if_not_exists: bool,
78 pub transient: bool,
80 pub volatile: bool,
82 pub iceberg: bool,
84 pub snapshot: bool,
86 pub dynamic: bool,
88 pub name: ObjectName,
90 pub columns: Vec<ColumnDef>,
92 pub constraints: Vec<TableConstraint>,
94 pub hive_distribution: HiveDistributionStyle,
96 pub hive_formats: Option<HiveFormat>,
98 pub file_format: Option<FileFormat>,
100 pub location: Option<String>,
102 pub query: Option<Box<Query>>,
104 pub without_rowid: bool,
106 pub like: Option<CreateTableLikeKind>,
108 pub clone: Option<ObjectName>,
110 pub version: Option<TableVersion>,
112 pub comment: Option<CommentDef>,
114 pub on_commit: Option<OnCommit>,
116 pub on_cluster: Option<Ident>,
118 pub primary_key: Option<Box<Expr>>,
120 pub order_by: Option<OneOrManyWithParens<Expr>>,
122 pub partition_by: Option<Box<Expr>>,
124 pub cluster_by: Option<WrappedCollection<Vec<Expr>>>,
126 pub clustered_by: Option<ClusteredBy>,
128 pub inherits: Option<Vec<ObjectName>>,
130 pub partition_of: Option<ObjectName>,
132 pub for_values: Option<ForValues>,
134 pub strict: bool,
136 pub copy_grants: bool,
138 pub enable_schema_evolution: Option<bool>,
140 pub change_tracking: Option<bool>,
142 pub data_retention_time_in_days: Option<u64>,
144 pub max_data_extension_time_in_days: Option<u64>,
146 pub default_ddl_collation: Option<String>,
148 pub with_aggregation_policy: Option<ObjectName>,
150 pub with_row_access_policy: Option<RowAccessPolicy>,
152 pub with_storage_lifecycle_policy: Option<StorageLifecyclePolicy>,
154 pub with_tags: Option<Vec<Tag>>,
156 pub base_location: Option<String>,
158 pub external_volume: Option<String>,
160 pub catalog: Option<String>,
162 pub catalog_sync: Option<String>,
164 pub storage_serialization_policy: Option<StorageSerializationPolicy>,
166 pub table_options: CreateTableOptions,
168 pub target_lag: Option<String>,
170 pub warehouse: Option<Ident>,
172 pub refresh_mode: Option<RefreshModeKind>,
174 pub initialize: Option<InitializeKind>,
176 pub require_user: bool,
178 pub diststyle: Option<DistStyle>,
180 pub distkey: Option<Expr>,
182 pub sortkey: Option<Vec<Expr>>,
184 pub backup: Option<bool>,
186}
187
188impl CreateTableBuilder {
189 pub fn new(name: ObjectName) -> Self {
191 Self {
192 or_replace: false,
193 temporary: false,
194 external: false,
195 global: None,
196 if_not_exists: false,
197 transient: false,
198 volatile: false,
199 iceberg: false,
200 snapshot: false,
201 dynamic: false,
202 name,
203 columns: vec![],
204 constraints: vec![],
205 hive_distribution: HiveDistributionStyle::NONE,
206 hive_formats: None,
207 file_format: None,
208 location: None,
209 query: None,
210 without_rowid: false,
211 like: None,
212 clone: None,
213 version: None,
214 comment: None,
215 on_commit: None,
216 on_cluster: None,
217 primary_key: None,
218 order_by: None,
219 partition_by: None,
220 cluster_by: None,
221 clustered_by: None,
222 inherits: None,
223 partition_of: None,
224 for_values: None,
225 strict: false,
226 copy_grants: false,
227 enable_schema_evolution: None,
228 change_tracking: None,
229 data_retention_time_in_days: None,
230 max_data_extension_time_in_days: None,
231 default_ddl_collation: None,
232 with_aggregation_policy: None,
233 with_row_access_policy: None,
234 with_storage_lifecycle_policy: None,
235 with_tags: None,
236 base_location: None,
237 external_volume: None,
238 catalog: None,
239 catalog_sync: None,
240 storage_serialization_policy: None,
241 table_options: CreateTableOptions::None,
242 target_lag: None,
243 warehouse: None,
244 refresh_mode: None,
245 initialize: None,
246 require_user: false,
247 diststyle: None,
248 distkey: None,
249 sortkey: None,
250 backup: None,
251 }
252 }
253 pub fn or_replace(mut self, or_replace: bool) -> Self {
255 self.or_replace = or_replace;
256 self
257 }
258 pub fn temporary(mut self, temporary: bool) -> Self {
260 self.temporary = temporary;
261 self
262 }
263 pub fn external(mut self, external: bool) -> Self {
265 self.external = external;
266 self
267 }
268 pub fn global(mut self, global: Option<bool>) -> Self {
270 self.global = global;
271 self
272 }
273 pub fn if_not_exists(mut self, if_not_exists: bool) -> Self {
275 self.if_not_exists = if_not_exists;
276 self
277 }
278 pub fn transient(mut self, transient: bool) -> Self {
280 self.transient = transient;
281 self
282 }
283 pub fn volatile(mut self, volatile: bool) -> Self {
285 self.volatile = volatile;
286 self
287 }
288 pub fn iceberg(mut self, iceberg: bool) -> Self {
290 self.iceberg = iceberg;
291 self
292 }
293 pub fn snapshot(mut self, snapshot: bool) -> Self {
295 self.snapshot = snapshot;
296 self
297 }
298 pub fn dynamic(mut self, dynamic: bool) -> Self {
300 self.dynamic = dynamic;
301 self
302 }
303 pub fn columns(mut self, columns: Vec<ColumnDef>) -> Self {
305 self.columns = columns;
306 self
307 }
308 pub fn constraints(mut self, constraints: Vec<TableConstraint>) -> Self {
310 self.constraints = constraints;
311 self
312 }
313 pub fn hive_distribution(mut self, hive_distribution: HiveDistributionStyle) -> Self {
315 self.hive_distribution = hive_distribution;
316 self
317 }
318 pub fn hive_formats(mut self, hive_formats: Option<HiveFormat>) -> Self {
320 self.hive_formats = hive_formats;
321 self
322 }
323 pub fn file_format(mut self, file_format: Option<FileFormat>) -> Self {
325 self.file_format = file_format;
326 self
327 }
328 pub fn location(mut self, location: Option<String>) -> Self {
330 self.location = location;
331 self
332 }
333 pub fn query(mut self, query: Option<Box<Query>>) -> Self {
335 self.query = query;
336 self
337 }
338 pub fn without_rowid(mut self, without_rowid: bool) -> Self {
340 self.without_rowid = without_rowid;
341 self
342 }
343 pub fn like(mut self, like: Option<CreateTableLikeKind>) -> Self {
345 self.like = like;
346 self
347 }
348 pub fn clone_clause(mut self, clone: Option<ObjectName>) -> Self {
351 self.clone = clone;
352 self
353 }
354 pub fn version(mut self, version: Option<TableVersion>) -> Self {
356 self.version = version;
357 self
358 }
359 pub fn comment_after_column_def(mut self, comment: Option<CommentDef>) -> Self {
361 self.comment = comment;
362 self
363 }
364 pub fn on_commit(mut self, on_commit: Option<OnCommit>) -> Self {
366 self.on_commit = on_commit;
367 self
368 }
369 pub fn on_cluster(mut self, on_cluster: Option<Ident>) -> Self {
371 self.on_cluster = on_cluster;
372 self
373 }
374 pub fn primary_key(mut self, primary_key: Option<Box<Expr>>) -> Self {
376 self.primary_key = primary_key;
377 self
378 }
379 pub fn order_by(mut self, order_by: Option<OneOrManyWithParens<Expr>>) -> Self {
381 self.order_by = order_by;
382 self
383 }
384 pub fn partition_by(mut self, partition_by: Option<Box<Expr>>) -> Self {
386 self.partition_by = partition_by;
387 self
388 }
389 pub fn cluster_by(mut self, cluster_by: Option<WrappedCollection<Vec<Expr>>>) -> Self {
391 self.cluster_by = cluster_by;
392 self
393 }
394 pub fn clustered_by(mut self, clustered_by: Option<ClusteredBy>) -> Self {
396 self.clustered_by = clustered_by;
397 self
398 }
399 pub fn inherits(mut self, inherits: Option<Vec<ObjectName>>) -> Self {
401 self.inherits = inherits;
402 self
403 }
404
405 pub fn partition_of(mut self, partition_of: Option<ObjectName>) -> Self {
407 self.partition_of = partition_of;
408 self
409 }
410
411 pub fn for_values(mut self, for_values: Option<ForValues>) -> Self {
413 self.for_values = for_values;
414 self
415 }
416
417 pub fn strict(mut self, strict: bool) -> Self {
419 self.strict = strict;
420 self
421 }
422 pub fn copy_grants(mut self, copy_grants: bool) -> Self {
424 self.copy_grants = copy_grants;
425 self
426 }
427 pub fn enable_schema_evolution(mut self, enable_schema_evolution: Option<bool>) -> Self {
429 self.enable_schema_evolution = enable_schema_evolution;
430 self
431 }
432 pub fn change_tracking(mut self, change_tracking: Option<bool>) -> Self {
434 self.change_tracking = change_tracking;
435 self
436 }
437 pub fn data_retention_time_in_days(mut self, data_retention_time_in_days: Option<u64>) -> Self {
439 self.data_retention_time_in_days = data_retention_time_in_days;
440 self
441 }
442 pub fn max_data_extension_time_in_days(
444 mut self,
445 max_data_extension_time_in_days: Option<u64>,
446 ) -> Self {
447 self.max_data_extension_time_in_days = max_data_extension_time_in_days;
448 self
449 }
450 pub fn default_ddl_collation(mut self, default_ddl_collation: Option<String>) -> Self {
452 self.default_ddl_collation = default_ddl_collation;
453 self
454 }
455 pub fn with_aggregation_policy(mut self, with_aggregation_policy: Option<ObjectName>) -> Self {
457 self.with_aggregation_policy = with_aggregation_policy;
458 self
459 }
460 pub fn with_row_access_policy(
462 mut self,
463 with_row_access_policy: Option<RowAccessPolicy>,
464 ) -> Self {
465 self.with_row_access_policy = with_row_access_policy;
466 self
467 }
468 pub fn with_storage_lifecycle_policy(
470 mut self,
471 with_storage_lifecycle_policy: Option<StorageLifecyclePolicy>,
472 ) -> Self {
473 self.with_storage_lifecycle_policy = with_storage_lifecycle_policy;
474 self
475 }
476 pub fn with_tags(mut self, with_tags: Option<Vec<Tag>>) -> Self {
478 self.with_tags = with_tags;
479 self
480 }
481 pub fn base_location(mut self, base_location: Option<String>) -> Self {
483 self.base_location = base_location;
484 self
485 }
486 pub fn external_volume(mut self, external_volume: Option<String>) -> Self {
488 self.external_volume = external_volume;
489 self
490 }
491 pub fn catalog(mut self, catalog: Option<String>) -> Self {
493 self.catalog = catalog;
494 self
495 }
496 pub fn catalog_sync(mut self, catalog_sync: Option<String>) -> Self {
498 self.catalog_sync = catalog_sync;
499 self
500 }
501 pub fn storage_serialization_policy(
503 mut self,
504 storage_serialization_policy: Option<StorageSerializationPolicy>,
505 ) -> Self {
506 self.storage_serialization_policy = storage_serialization_policy;
507 self
508 }
509 pub fn table_options(mut self, table_options: CreateTableOptions) -> Self {
511 self.table_options = table_options;
512 self
513 }
514 pub fn target_lag(mut self, target_lag: Option<String>) -> Self {
516 self.target_lag = target_lag;
517 self
518 }
519 pub fn warehouse(mut self, warehouse: Option<Ident>) -> Self {
521 self.warehouse = warehouse;
522 self
523 }
524 pub fn refresh_mode(mut self, refresh_mode: Option<RefreshModeKind>) -> Self {
526 self.refresh_mode = refresh_mode;
527 self
528 }
529 pub fn initialize(mut self, initialize: Option<InitializeKind>) -> Self {
531 self.initialize = initialize;
532 self
533 }
534 pub fn require_user(mut self, require_user: bool) -> Self {
536 self.require_user = require_user;
537 self
538 }
539 pub fn diststyle(mut self, diststyle: Option<DistStyle>) -> Self {
541 self.diststyle = diststyle;
542 self
543 }
544 pub fn distkey(mut self, distkey: Option<Expr>) -> Self {
546 self.distkey = distkey;
547 self
548 }
549 pub fn sortkey(mut self, sortkey: Option<Vec<Expr>>) -> Self {
551 self.sortkey = sortkey;
552 self
553 }
554 pub fn backup(mut self, backup: Option<bool>) -> Self {
556 self.backup = backup;
557 self
558 }
559 pub fn build(self) -> CreateTable {
561 CreateTable {
562 or_replace: self.or_replace,
563 temporary: self.temporary,
564 external: self.external,
565 global: self.global,
566 if_not_exists: self.if_not_exists,
567 transient: self.transient,
568 volatile: self.volatile,
569 iceberg: self.iceberg,
570 snapshot: self.snapshot,
571 dynamic: self.dynamic,
572 name: self.name,
573 columns: self.columns,
574 constraints: self.constraints,
575 hive_distribution: self.hive_distribution,
576 hive_formats: self.hive_formats,
577 file_format: self.file_format,
578 location: self.location,
579 query: self.query,
580 without_rowid: self.without_rowid,
581 like: self.like,
582 clone: self.clone,
583 version: self.version,
584 comment: self.comment,
585 on_commit: self.on_commit,
586 on_cluster: self.on_cluster,
587 primary_key: self.primary_key,
588 order_by: self.order_by,
589 partition_by: self.partition_by,
590 cluster_by: self.cluster_by,
591 clustered_by: self.clustered_by,
592 inherits: self.inherits,
593 partition_of: self.partition_of,
594 for_values: self.for_values,
595 strict: self.strict,
596 copy_grants: self.copy_grants,
597 enable_schema_evolution: self.enable_schema_evolution,
598 change_tracking: self.change_tracking,
599 data_retention_time_in_days: self.data_retention_time_in_days,
600 max_data_extension_time_in_days: self.max_data_extension_time_in_days,
601 default_ddl_collation: self.default_ddl_collation,
602 with_aggregation_policy: self.with_aggregation_policy,
603 with_row_access_policy: self.with_row_access_policy,
604 with_storage_lifecycle_policy: self.with_storage_lifecycle_policy,
605 with_tags: self.with_tags,
606 base_location: self.base_location,
607 external_volume: self.external_volume,
608 catalog: self.catalog,
609 catalog_sync: self.catalog_sync,
610 storage_serialization_policy: self.storage_serialization_policy,
611 table_options: self.table_options,
612 target_lag: self.target_lag,
613 warehouse: self.warehouse,
614 refresh_mode: self.refresh_mode,
615 initialize: self.initialize,
616 require_user: self.require_user,
617 diststyle: self.diststyle,
618 distkey: self.distkey,
619 sortkey: self.sortkey,
620 backup: self.backup,
621 }
622 }
623}
624
625impl TryFrom<Statement> for CreateTableBuilder {
626 type Error = ParserError;
627
628 fn try_from(stmt: Statement) -> Result<Self, Self::Error> {
631 match stmt {
632 Statement::CreateTable(create_table) => Ok(create_table.into()),
633 _ => Err(ParserError::ParserError(format!(
634 "Expected create table statement, but received: {stmt}"
635 ))),
636 }
637 }
638}
639
640impl From<CreateTable> for CreateTableBuilder {
641 fn from(table: CreateTable) -> Self {
642 Self {
643 or_replace: table.or_replace,
644 temporary: table.temporary,
645 external: table.external,
646 global: table.global,
647 if_not_exists: table.if_not_exists,
648 transient: table.transient,
649 volatile: table.volatile,
650 iceberg: table.iceberg,
651 snapshot: table.snapshot,
652 dynamic: table.dynamic,
653 name: table.name,
654 columns: table.columns,
655 constraints: table.constraints,
656 hive_distribution: table.hive_distribution,
657 hive_formats: table.hive_formats,
658 file_format: table.file_format,
659 location: table.location,
660 query: table.query,
661 without_rowid: table.without_rowid,
662 like: table.like,
663 clone: table.clone,
664 version: table.version,
665 comment: table.comment,
666 on_commit: table.on_commit,
667 on_cluster: table.on_cluster,
668 primary_key: table.primary_key,
669 order_by: table.order_by,
670 partition_by: table.partition_by,
671 cluster_by: table.cluster_by,
672 clustered_by: table.clustered_by,
673 inherits: table.inherits,
674 partition_of: table.partition_of,
675 for_values: table.for_values,
676 strict: table.strict,
677 copy_grants: table.copy_grants,
678 enable_schema_evolution: table.enable_schema_evolution,
679 change_tracking: table.change_tracking,
680 data_retention_time_in_days: table.data_retention_time_in_days,
681 max_data_extension_time_in_days: table.max_data_extension_time_in_days,
682 default_ddl_collation: table.default_ddl_collation,
683 with_aggregation_policy: table.with_aggregation_policy,
684 with_row_access_policy: table.with_row_access_policy,
685 with_storage_lifecycle_policy: table.with_storage_lifecycle_policy,
686 with_tags: table.with_tags,
687 base_location: table.base_location,
688 external_volume: table.external_volume,
689 catalog: table.catalog,
690 catalog_sync: table.catalog_sync,
691 storage_serialization_policy: table.storage_serialization_policy,
692 table_options: table.table_options,
693 target_lag: table.target_lag,
694 warehouse: table.warehouse,
695 refresh_mode: table.refresh_mode,
696 initialize: table.initialize,
697 require_user: table.require_user,
698 diststyle: table.diststyle,
699 distkey: table.distkey,
700 sortkey: table.sortkey,
701 backup: table.backup,
702 }
703 }
704}
705
706#[derive(Default)]
708pub(crate) struct CreateTableConfiguration {
709 pub partition_by: Option<Box<Expr>>,
710 pub cluster_by: Option<WrappedCollection<Vec<Expr>>>,
711 pub inherits: Option<Vec<ObjectName>>,
712 pub table_options: CreateTableOptions,
713}
714
715#[cfg(test)]
716mod tests {
717 use crate::ast::helpers::stmt_create_table::CreateTableBuilder;
718 use crate::ast::{Ident, ObjectName, Statement};
719 use crate::parser::ParserError;
720
721 #[test]
722 pub fn test_from_valid_statement() {
723 let builder = CreateTableBuilder::new(ObjectName::from(vec![Ident::new("table_name")]));
724
725 let create_table = builder.clone().build();
726 let stmt: Statement = create_table.into();
727
728 assert_eq!(builder, CreateTableBuilder::try_from(stmt).unwrap());
729 }
730
731 #[test]
732 pub fn test_from_invalid_statement() {
733 let stmt = Statement::Commit {
734 chain: false,
735 end: false,
736 modifier: None,
737 };
738
739 assert_eq!(
740 CreateTableBuilder::try_from(stmt).unwrap_err(),
741 ParserError::ParserError(
742 "Expected create table statement, but received: COMMIT".to_owned()
743 )
744 );
745 }
746}