Skip to main content

sqlparser/ast/helpers/
stmt_create_table.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18#[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/// Builder for create table statement variant ([1]).
38///
39/// This structure helps building and accessing a create table with more ease, without needing to:
40/// - Match the enum itself a lot of times; or
41/// - Moving a lot of variables around the code.
42///
43/// # Example
44/// ```rust
45/// use sqlparser::ast::helpers::stmt_create_table::CreateTableBuilder;
46/// use sqlparser::ast::{ColumnDef, DataType, Ident, ObjectName};
47/// let builder = CreateTableBuilder::new(ObjectName::from(vec![Ident::new("table_name")]))
48///    .if_not_exists(true)
49///    .columns(vec![ColumnDef {
50///        name: Ident::new("c1"),
51///        data_type: DataType::Int(None),
52///        options: vec![],
53/// }]);
54/// // You can access internal elements with ease
55/// assert!(builder.if_not_exists);
56/// // Convert to a statement
57/// assert_eq!(
58///    builder.build().to_string(),
59///    "CREATE TABLE IF NOT EXISTS table_name (c1 INT)"
60/// )
61/// ```
62///
63/// [1]: crate::ast::Statement::CreateTable
64#[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    /// Whether the statement uses `OR REPLACE`.
69    pub or_replace: bool,
70    /// Whether the table is `TEMPORARY`.
71    pub temporary: bool,
72    /// Whether the table is `EXTERNAL`.
73    pub external: bool,
74    /// Optional `GLOBAL` flag for dialects that support it.
75    pub global: Option<bool>,
76    /// Whether `IF NOT EXISTS` was specified.
77    pub if_not_exists: bool,
78    /// Whether `TRANSIENT` was specified.
79    pub transient: bool,
80    /// Whether `VOLATILE` was specified.
81    pub volatile: bool,
82    /// Iceberg-specific table flag.
83    pub iceberg: bool,
84    /// `SNAPSHOT` table flag.
85    pub snapshot: bool,
86    /// Whether `DYNAMIC` table option is set.
87    pub dynamic: bool,
88    /// The table name.
89    pub name: ObjectName,
90    /// Column definitions for the table.
91    pub columns: Vec<ColumnDef>,
92    /// Table-level constraints.
93    pub constraints: Vec<TableConstraint>,
94    /// Hive distribution style.
95    pub hive_distribution: HiveDistributionStyle,
96    /// Optional Hive format settings.
97    pub hive_formats: Option<HiveFormat>,
98    /// Optional file format for storage.
99    pub file_format: Option<FileFormat>,
100    /// Optional storage location.
101    pub location: Option<String>,
102    /// Optional `AS SELECT` query for the table.
103    pub query: Option<Box<Query>>,
104    /// Whether `WITHOUT ROWID` is set.
105    pub without_rowid: bool,
106    /// Optional `LIKE` clause kind.
107    pub like: Option<CreateTableLikeKind>,
108    /// Optional `CLONE` source object name.
109    pub clone: Option<ObjectName>,
110    /// Optional table version.
111    pub version: Option<TableVersion>,
112    /// Optional table comment.
113    pub comment: Option<CommentDef>,
114    /// Optional `ON COMMIT` behavior.
115    pub on_commit: Option<OnCommit>,
116    /// Optional cluster identifier.
117    pub on_cluster: Option<Ident>,
118    /// Optional primary key expression.
119    pub primary_key: Option<Box<Expr>>,
120    /// Optional `ORDER BY` for clustering/sorting.
121    pub order_by: Option<OneOrManyWithParens<Expr>>,
122    /// Optional `PARTITION BY` expression.
123    pub partition_by: Option<Box<Expr>>,
124    /// Optional `CLUSTER BY` expressions.
125    pub cluster_by: Option<WrappedCollection<Vec<Expr>>>,
126    /// Optional `CLUSTERED BY` clause.
127    pub clustered_by: Option<ClusteredBy>,
128    /// Optional parent tables (`INHERITS`).
129    pub inherits: Option<Vec<ObjectName>>,
130    /// Optional partitioned table (`PARTITION OF`)
131    pub partition_of: Option<ObjectName>,
132    /// Range of values associated with the partition (`FOR VALUES`)
133    pub for_values: Option<ForValues>,
134    /// `STRICT` table flag.
135    pub strict: bool,
136    /// Whether to copy grants from the source.
137    pub copy_grants: bool,
138    /// Optional flag for schema evolution support.
139    pub enable_schema_evolution: Option<bool>,
140    /// Optional change tracking flag.
141    pub change_tracking: Option<bool>,
142    /// Optional data retention time in days.
143    pub data_retention_time_in_days: Option<u64>,
144    /// Optional max data extension time in days.
145    pub max_data_extension_time_in_days: Option<u64>,
146    /// Optional default DDL collation.
147    pub default_ddl_collation: Option<String>,
148    /// Optional aggregation policy object name.
149    pub with_aggregation_policy: Option<ObjectName>,
150    /// Optional row access policy applied to the table.
151    pub with_row_access_policy: Option<RowAccessPolicy>,
152    /// Optional storage lifecycle policy applied to the table.
153    pub with_storage_lifecycle_policy: Option<StorageLifecyclePolicy>,
154    /// Optional tags/labels attached to the table metadata.
155    pub with_tags: Option<Vec<Tag>>,
156    /// Optional base location for staged data.
157    pub base_location: Option<String>,
158    /// Optional external volume identifier.
159    pub external_volume: Option<String>,
160    /// Optional catalog name.
161    pub catalog: Option<String>,
162    /// Optional catalog synchronization option.
163    pub catalog_sync: Option<String>,
164    /// Optional storage serialization policy.
165    pub storage_serialization_policy: Option<StorageSerializationPolicy>,
166    /// Parsed table options from the statement.
167    pub table_options: CreateTableOptions,
168    /// Optional target lag configuration.
169    pub target_lag: Option<String>,
170    /// Optional warehouse identifier.
171    pub warehouse: Option<Ident>,
172    /// Optional refresh mode for materialized tables.
173    pub refresh_mode: Option<RefreshModeKind>,
174    /// Optional initialization kind for the table.
175    pub initialize: Option<InitializeKind>,
176    /// Whether operations require a user identity.
177    pub require_user: bool,
178    /// Redshift `DISTSTYLE` option.
179    pub diststyle: Option<DistStyle>,
180    /// Redshift `DISTKEY` option.
181    pub distkey: Option<Expr>,
182    /// Redshift `SORTKEY` option.
183    pub sortkey: Option<Vec<Expr>>,
184    /// Redshift `BACKUP` option.
185    pub backup: Option<bool>,
186}
187
188impl CreateTableBuilder {
189    /// Create a new `CreateTableBuilder` for the given table name.
190    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    /// Set `OR REPLACE` for the CREATE TABLE statement.
254    pub fn or_replace(mut self, or_replace: bool) -> Self {
255        self.or_replace = or_replace;
256        self
257    }
258    /// Mark the table as `TEMPORARY`.
259    pub fn temporary(mut self, temporary: bool) -> Self {
260        self.temporary = temporary;
261        self
262    }
263    /// Mark the table as `EXTERNAL`.
264    pub fn external(mut self, external: bool) -> Self {
265        self.external = external;
266        self
267    }
268    /// Set optional `GLOBAL` flag (dialect-specific).
269    pub fn global(mut self, global: Option<bool>) -> Self {
270        self.global = global;
271        self
272    }
273    /// Set `IF NOT EXISTS`.
274    pub fn if_not_exists(mut self, if_not_exists: bool) -> Self {
275        self.if_not_exists = if_not_exists;
276        self
277    }
278    /// Set `TRANSIENT` flag.
279    pub fn transient(mut self, transient: bool) -> Self {
280        self.transient = transient;
281        self
282    }
283    /// Set `VOLATILE` flag.
284    pub fn volatile(mut self, volatile: bool) -> Self {
285        self.volatile = volatile;
286        self
287    }
288    /// Enable Iceberg table semantics.
289    pub fn iceberg(mut self, iceberg: bool) -> Self {
290        self.iceberg = iceberg;
291        self
292    }
293    /// Set `SNAPSHOT` table flag (BigQuery).
294    pub fn snapshot(mut self, snapshot: bool) -> Self {
295        self.snapshot = snapshot;
296        self
297    }
298    /// Set `DYNAMIC` table option.
299    pub fn dynamic(mut self, dynamic: bool) -> Self {
300        self.dynamic = dynamic;
301        self
302    }
303    /// Set the table column definitions.
304    pub fn columns(mut self, columns: Vec<ColumnDef>) -> Self {
305        self.columns = columns;
306        self
307    }
308    /// Set table-level constraints.
309    pub fn constraints(mut self, constraints: Vec<TableConstraint>) -> Self {
310        self.constraints = constraints;
311        self
312    }
313    /// Set Hive distribution style.
314    pub fn hive_distribution(mut self, hive_distribution: HiveDistributionStyle) -> Self {
315        self.hive_distribution = hive_distribution;
316        self
317    }
318    /// Set Hive-specific formats.
319    pub fn hive_formats(mut self, hive_formats: Option<HiveFormat>) -> Self {
320        self.hive_formats = hive_formats;
321        self
322    }
323    /// Set file format for the table (e.g., PARQUET).
324    pub fn file_format(mut self, file_format: Option<FileFormat>) -> Self {
325        self.file_format = file_format;
326        self
327    }
328    /// Set storage `location` for the table.
329    pub fn location(mut self, location: Option<String>) -> Self {
330        self.location = location;
331        self
332    }
333    /// Set an underlying `AS SELECT` query for the table.
334    pub fn query(mut self, query: Option<Box<Query>>) -> Self {
335        self.query = query;
336        self
337    }
338    /// Set `WITHOUT ROWID` option.
339    pub fn without_rowid(mut self, without_rowid: bool) -> Self {
340        self.without_rowid = without_rowid;
341        self
342    }
343    /// Set `LIKE` clause for the table.
344    pub fn like(mut self, like: Option<CreateTableLikeKind>) -> Self {
345        self.like = like;
346        self
347    }
348    // Different name to allow the object to be cloned
349    /// Set `CLONE` source object name.
350    pub fn clone_clause(mut self, clone: Option<ObjectName>) -> Self {
351        self.clone = clone;
352        self
353    }
354    /// Set table `VERSION`.
355    pub fn version(mut self, version: Option<TableVersion>) -> Self {
356        self.version = version;
357        self
358    }
359    /// Set a comment for the table or following column definitions.
360    pub fn comment_after_column_def(mut self, comment: Option<CommentDef>) -> Self {
361        self.comment = comment;
362        self
363    }
364    /// Set `ON COMMIT` behavior for temporary tables.
365    pub fn on_commit(mut self, on_commit: Option<OnCommit>) -> Self {
366        self.on_commit = on_commit;
367        self
368    }
369    /// Set cluster identifier for the table.
370    pub fn on_cluster(mut self, on_cluster: Option<Ident>) -> Self {
371        self.on_cluster = on_cluster;
372        self
373    }
374    /// Set a primary key expression for the table.
375    pub fn primary_key(mut self, primary_key: Option<Box<Expr>>) -> Self {
376        self.primary_key = primary_key;
377        self
378    }
379    /// Set `ORDER BY` clause for clustered/sorted tables.
380    pub fn order_by(mut self, order_by: Option<OneOrManyWithParens<Expr>>) -> Self {
381        self.order_by = order_by;
382        self
383    }
384    /// Set `PARTITION BY` expression.
385    pub fn partition_by(mut self, partition_by: Option<Box<Expr>>) -> Self {
386        self.partition_by = partition_by;
387        self
388    }
389    /// Set `CLUSTER BY` expression(s).
390    pub fn cluster_by(mut self, cluster_by: Option<WrappedCollection<Vec<Expr>>>) -> Self {
391        self.cluster_by = cluster_by;
392        self
393    }
394    /// Set `CLUSTERED BY` clause.
395    pub fn clustered_by(mut self, clustered_by: Option<ClusteredBy>) -> Self {
396        self.clustered_by = clustered_by;
397        self
398    }
399    /// Set parent tables via `INHERITS`.
400    pub fn inherits(mut self, inherits: Option<Vec<ObjectName>>) -> Self {
401        self.inherits = inherits;
402        self
403    }
404
405    /// Sets the table which is partitioned to create the current table.
406    pub fn partition_of(mut self, partition_of: Option<ObjectName>) -> Self {
407        self.partition_of = partition_of;
408        self
409    }
410
411    /// Sets the range of values associated with the partition.
412    pub fn for_values(mut self, for_values: Option<ForValues>) -> Self {
413        self.for_values = for_values;
414        self
415    }
416
417    /// Set `STRICT` option.
418    pub fn strict(mut self, strict: bool) -> Self {
419        self.strict = strict;
420        self
421    }
422    /// Enable copying grants from source object.
423    pub fn copy_grants(mut self, copy_grants: bool) -> Self {
424        self.copy_grants = copy_grants;
425        self
426    }
427    /// Enable or disable schema evolution features.
428    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    /// Enable or disable change tracking.
433    pub fn change_tracking(mut self, change_tracking: Option<bool>) -> Self {
434        self.change_tracking = change_tracking;
435        self
436    }
437    /// Set data retention time (in days).
438    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    /// Set maximum data extension time (in days).
443    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    /// Set default DDL collation.
451    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    /// Set aggregation policy object.
456    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    /// Attach a row access policy to the table.
461    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    /// Attach a storage lifecycle policy to the table.
469    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    /// Attach tags/labels to the table metadata.
477    pub fn with_tags(mut self, with_tags: Option<Vec<Tag>>) -> Self {
478        self.with_tags = with_tags;
479        self
480    }
481    /// Set a base storage location for staged data.
482    pub fn base_location(mut self, base_location: Option<String>) -> Self {
483        self.base_location = base_location;
484        self
485    }
486    /// Set an external volume identifier.
487    pub fn external_volume(mut self, external_volume: Option<String>) -> Self {
488        self.external_volume = external_volume;
489        self
490    }
491    /// Set the catalog name for the table.
492    pub fn catalog(mut self, catalog: Option<String>) -> Self {
493        self.catalog = catalog;
494        self
495    }
496    /// Set catalog synchronization option.
497    pub fn catalog_sync(mut self, catalog_sync: Option<String>) -> Self {
498        self.catalog_sync = catalog_sync;
499        self
500    }
501    /// Set a storage serialization policy.
502    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    /// Set arbitrary table options parsed from the statement.
510    pub fn table_options(mut self, table_options: CreateTableOptions) -> Self {
511        self.table_options = table_options;
512        self
513    }
514    /// Set a target lag configuration (dialect-specific).
515    pub fn target_lag(mut self, target_lag: Option<String>) -> Self {
516        self.target_lag = target_lag;
517        self
518    }
519    /// Associate the table with a warehouse identifier.
520    pub fn warehouse(mut self, warehouse: Option<Ident>) -> Self {
521        self.warehouse = warehouse;
522        self
523    }
524    /// Set refresh mode for materialized/managed tables.
525    pub fn refresh_mode(mut self, refresh_mode: Option<RefreshModeKind>) -> Self {
526        self.refresh_mode = refresh_mode;
527        self
528    }
529    /// Set initialization mode for the table.
530    pub fn initialize(mut self, initialize: Option<InitializeKind>) -> Self {
531        self.initialize = initialize;
532        self
533    }
534    /// Require a user identity for table operations.
535    pub fn require_user(mut self, require_user: bool) -> Self {
536        self.require_user = require_user;
537        self
538    }
539    /// Set Redshift `DISTSTYLE` option.
540    pub fn diststyle(mut self, diststyle: Option<DistStyle>) -> Self {
541        self.diststyle = diststyle;
542        self
543    }
544    /// Set Redshift `DISTKEY` option.
545    pub fn distkey(mut self, distkey: Option<Expr>) -> Self {
546        self.distkey = distkey;
547        self
548    }
549    /// Set Redshift `SORTKEY` option.
550    pub fn sortkey(mut self, sortkey: Option<Vec<Expr>>) -> Self {
551        self.sortkey = sortkey;
552        self
553    }
554    /// Set the Redshift `BACKUP` option.
555    pub fn backup(mut self, backup: Option<bool>) -> Self {
556        self.backup = backup;
557        self
558    }
559    /// Consume the builder and produce a `CreateTable`.
560    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    // As the builder can be transformed back to a statement, it shouldn't be a problem to take the
629    // ownership.
630    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/// Helper return type when parsing configuration for a `CREATE TABLE` statement.
707#[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}