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, Expr,
29 FileFormat, ForValues, HiveDistributionStyle, HiveFormat, Ident, InitializeKind, ObjectName,
30 OnCommit, OneOrManyWithParens, Query, RefreshModeKind, RowAccessPolicy, Statement,
31 StorageSerializationPolicy, TableConstraint, TableVersion, Tag, WrappedCollection,
32};
33
34use crate::parser::ParserError;
35
36#[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 iceberg: bool,
75 pub dynamic: bool,
76 pub name: ObjectName,
77 pub columns: Vec<ColumnDef>,
78 pub constraints: Vec<TableConstraint>,
79 pub hive_distribution: HiveDistributionStyle,
80 pub hive_formats: Option<HiveFormat>,
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<CreateTableLikeKind>,
86 pub clone: Option<ObjectName>,
87 pub version: Option<TableVersion>,
88 pub comment: Option<CommentDef>,
89 pub on_commit: Option<OnCommit>,
90 pub on_cluster: Option<Ident>,
91 pub primary_key: Option<Box<Expr>>,
92 pub order_by: Option<OneOrManyWithParens<Expr>>,
93 pub partition_by: Option<Box<Expr>>,
94 pub cluster_by: Option<WrappedCollection<Vec<Expr>>>,
95 pub clustered_by: Option<ClusteredBy>,
96 pub inherits: Option<Vec<ObjectName>>,
97 pub partition_of: Option<ObjectName>,
98 pub for_values: Option<ForValues>,
99 pub strict: bool,
100 pub copy_grants: bool,
101 pub enable_schema_evolution: Option<bool>,
102 pub change_tracking: Option<bool>,
103 pub data_retention_time_in_days: Option<u64>,
104 pub max_data_extension_time_in_days: Option<u64>,
105 pub default_ddl_collation: Option<String>,
106 pub with_aggregation_policy: Option<ObjectName>,
107 pub with_row_access_policy: Option<RowAccessPolicy>,
108 pub with_tags: Option<Vec<Tag>>,
109 pub base_location: Option<String>,
110 pub external_volume: Option<String>,
111 pub catalog: Option<String>,
112 pub catalog_sync: Option<String>,
113 pub storage_serialization_policy: Option<StorageSerializationPolicy>,
114 pub table_options: CreateTableOptions,
115 pub target_lag: Option<String>,
116 pub warehouse: Option<Ident>,
117 pub refresh_mode: Option<RefreshModeKind>,
118 pub initialize: Option<InitializeKind>,
119 pub require_user: bool,
120}
121
122impl CreateTableBuilder {
123 pub fn new(name: ObjectName) -> Self {
124 Self {
125 or_replace: false,
126 temporary: false,
127 external: false,
128 global: None,
129 if_not_exists: false,
130 transient: false,
131 volatile: false,
132 iceberg: false,
133 dynamic: false,
134 name,
135 columns: vec![],
136 constraints: vec![],
137 hive_distribution: HiveDistributionStyle::NONE,
138 hive_formats: None,
139 file_format: None,
140 location: None,
141 query: None,
142 without_rowid: false,
143 like: None,
144 clone: None,
145 version: None,
146 comment: None,
147 on_commit: None,
148 on_cluster: None,
149 primary_key: None,
150 order_by: None,
151 partition_by: None,
152 cluster_by: None,
153 clustered_by: None,
154 inherits: None,
155 partition_of: None,
156 for_values: None,
157 strict: false,
158 copy_grants: false,
159 enable_schema_evolution: None,
160 change_tracking: None,
161 data_retention_time_in_days: None,
162 max_data_extension_time_in_days: None,
163 default_ddl_collation: None,
164 with_aggregation_policy: None,
165 with_row_access_policy: None,
166 with_tags: None,
167 base_location: None,
168 external_volume: None,
169 catalog: None,
170 catalog_sync: None,
171 storage_serialization_policy: None,
172 table_options: CreateTableOptions::None,
173 target_lag: None,
174 warehouse: None,
175 refresh_mode: None,
176 initialize: None,
177 require_user: false,
178 }
179 }
180 pub fn or_replace(mut self, or_replace: bool) -> Self {
181 self.or_replace = or_replace;
182 self
183 }
184
185 pub fn temporary(mut self, temporary: bool) -> Self {
186 self.temporary = temporary;
187 self
188 }
189
190 pub fn external(mut self, external: bool) -> Self {
191 self.external = external;
192 self
193 }
194
195 pub fn global(mut self, global: Option<bool>) -> Self {
196 self.global = global;
197 self
198 }
199
200 pub fn if_not_exists(mut self, if_not_exists: bool) -> Self {
201 self.if_not_exists = if_not_exists;
202 self
203 }
204
205 pub fn transient(mut self, transient: bool) -> Self {
206 self.transient = transient;
207 self
208 }
209
210 pub fn volatile(mut self, volatile: bool) -> Self {
211 self.volatile = volatile;
212 self
213 }
214
215 pub fn iceberg(mut self, iceberg: bool) -> Self {
216 self.iceberg = iceberg;
217 self
218 }
219
220 pub fn dynamic(mut self, dynamic: bool) -> Self {
221 self.dynamic = dynamic;
222 self
223 }
224
225 pub fn columns(mut self, columns: Vec<ColumnDef>) -> Self {
226 self.columns = columns;
227 self
228 }
229
230 pub fn constraints(mut self, constraints: Vec<TableConstraint>) -> Self {
231 self.constraints = constraints;
232 self
233 }
234
235 pub fn hive_distribution(mut self, hive_distribution: HiveDistributionStyle) -> Self {
236 self.hive_distribution = hive_distribution;
237 self
238 }
239
240 pub fn hive_formats(mut self, hive_formats: Option<HiveFormat>) -> Self {
241 self.hive_formats = hive_formats;
242 self
243 }
244
245 pub fn file_format(mut self, file_format: Option<FileFormat>) -> Self {
246 self.file_format = file_format;
247 self
248 }
249 pub fn location(mut self, location: Option<String>) -> Self {
250 self.location = location;
251 self
252 }
253
254 pub fn query(mut self, query: Option<Box<Query>>) -> Self {
255 self.query = query;
256 self
257 }
258 pub fn without_rowid(mut self, without_rowid: bool) -> Self {
259 self.without_rowid = without_rowid;
260 self
261 }
262
263 pub fn like(mut self, like: Option<CreateTableLikeKind>) -> Self {
264 self.like = like;
265 self
266 }
267
268 pub fn clone_clause(mut self, clone: Option<ObjectName>) -> Self {
270 self.clone = clone;
271 self
272 }
273
274 pub fn version(mut self, version: Option<TableVersion>) -> Self {
275 self.version = version;
276 self
277 }
278
279 pub fn comment_after_column_def(mut self, comment: Option<CommentDef>) -> Self {
280 self.comment = comment;
281 self
282 }
283
284 pub fn on_commit(mut self, on_commit: Option<OnCommit>) -> Self {
285 self.on_commit = on_commit;
286 self
287 }
288
289 pub fn on_cluster(mut self, on_cluster: Option<Ident>) -> Self {
290 self.on_cluster = on_cluster;
291 self
292 }
293
294 pub fn primary_key(mut self, primary_key: Option<Box<Expr>>) -> Self {
295 self.primary_key = primary_key;
296 self
297 }
298
299 pub fn order_by(mut self, order_by: Option<OneOrManyWithParens<Expr>>) -> Self {
300 self.order_by = order_by;
301 self
302 }
303
304 pub fn partition_by(mut self, partition_by: Option<Box<Expr>>) -> Self {
305 self.partition_by = partition_by;
306 self
307 }
308
309 pub fn cluster_by(mut self, cluster_by: Option<WrappedCollection<Vec<Expr>>>) -> Self {
310 self.cluster_by = cluster_by;
311 self
312 }
313
314 pub fn clustered_by(mut self, clustered_by: Option<ClusteredBy>) -> Self {
315 self.clustered_by = clustered_by;
316 self
317 }
318
319 pub fn inherits(mut self, inherits: Option<Vec<ObjectName>>) -> Self {
320 self.inherits = inherits;
321 self
322 }
323
324 pub fn partition_of(mut self, partition_of: Option<ObjectName>) -> Self {
325 self.partition_of = partition_of;
326 self
327 }
328
329 pub fn for_values(mut self, for_values: Option<ForValues>) -> Self {
330 self.for_values = for_values;
331 self
332 }
333
334 pub fn strict(mut self, strict: bool) -> Self {
335 self.strict = strict;
336 self
337 }
338
339 pub fn copy_grants(mut self, copy_grants: bool) -> Self {
340 self.copy_grants = copy_grants;
341 self
342 }
343
344 pub fn enable_schema_evolution(mut self, enable_schema_evolution: Option<bool>) -> Self {
345 self.enable_schema_evolution = enable_schema_evolution;
346 self
347 }
348
349 pub fn change_tracking(mut self, change_tracking: Option<bool>) -> Self {
350 self.change_tracking = change_tracking;
351 self
352 }
353
354 pub fn data_retention_time_in_days(mut self, data_retention_time_in_days: Option<u64>) -> Self {
355 self.data_retention_time_in_days = data_retention_time_in_days;
356 self
357 }
358
359 pub fn max_data_extension_time_in_days(
360 mut self,
361 max_data_extension_time_in_days: Option<u64>,
362 ) -> Self {
363 self.max_data_extension_time_in_days = max_data_extension_time_in_days;
364 self
365 }
366
367 pub fn default_ddl_collation(mut self, default_ddl_collation: Option<String>) -> Self {
368 self.default_ddl_collation = default_ddl_collation;
369 self
370 }
371
372 pub fn with_aggregation_policy(mut self, with_aggregation_policy: Option<ObjectName>) -> Self {
373 self.with_aggregation_policy = with_aggregation_policy;
374 self
375 }
376
377 pub fn with_row_access_policy(
378 mut self,
379 with_row_access_policy: Option<RowAccessPolicy>,
380 ) -> Self {
381 self.with_row_access_policy = with_row_access_policy;
382 self
383 }
384
385 pub fn with_tags(mut self, with_tags: Option<Vec<Tag>>) -> Self {
386 self.with_tags = with_tags;
387 self
388 }
389
390 pub fn base_location(mut self, base_location: Option<String>) -> Self {
391 self.base_location = base_location;
392 self
393 }
394
395 pub fn external_volume(mut self, external_volume: Option<String>) -> Self {
396 self.external_volume = external_volume;
397 self
398 }
399
400 pub fn catalog(mut self, catalog: Option<String>) -> Self {
401 self.catalog = catalog;
402 self
403 }
404
405 pub fn catalog_sync(mut self, catalog_sync: Option<String>) -> Self {
406 self.catalog_sync = catalog_sync;
407 self
408 }
409
410 pub fn storage_serialization_policy(
411 mut self,
412 storage_serialization_policy: Option<StorageSerializationPolicy>,
413 ) -> Self {
414 self.storage_serialization_policy = storage_serialization_policy;
415 self
416 }
417
418 pub fn table_options(mut self, table_options: CreateTableOptions) -> Self {
419 self.table_options = table_options;
420 self
421 }
422
423 pub fn target_lag(mut self, target_lag: Option<String>) -> Self {
424 self.target_lag = target_lag;
425 self
426 }
427
428 pub fn warehouse(mut self, warehouse: Option<Ident>) -> Self {
429 self.warehouse = warehouse;
430 self
431 }
432
433 pub fn refresh_mode(mut self, refresh_mode: Option<RefreshModeKind>) -> Self {
434 self.refresh_mode = refresh_mode;
435 self
436 }
437
438 pub fn initialize(mut self, initialize: Option<InitializeKind>) -> Self {
439 self.initialize = initialize;
440 self
441 }
442
443 pub fn require_user(mut self, require_user: bool) -> Self {
444 self.require_user = require_user;
445 self
446 }
447
448 pub fn build(self) -> Statement {
449 CreateTable {
450 or_replace: self.or_replace,
451 temporary: self.temporary,
452 external: self.external,
453 global: self.global,
454 if_not_exists: self.if_not_exists,
455 transient: self.transient,
456 volatile: self.volatile,
457 iceberg: self.iceberg,
458 dynamic: self.dynamic,
459 name: self.name,
460 columns: self.columns,
461 constraints: self.constraints,
462 hive_distribution: self.hive_distribution,
463 hive_formats: self.hive_formats,
464 file_format: self.file_format,
465 location: self.location,
466 query: self.query,
467 without_rowid: self.without_rowid,
468 like: self.like,
469 clone: self.clone,
470 version: self.version,
471 comment: self.comment,
472 on_commit: self.on_commit,
473 on_cluster: self.on_cluster,
474 primary_key: self.primary_key,
475 order_by: self.order_by,
476 partition_by: self.partition_by,
477 cluster_by: self.cluster_by,
478 clustered_by: self.clustered_by,
479 inherits: self.inherits,
480 partition_of: self.partition_of,
481 for_values: self.for_values,
482 strict: self.strict,
483 copy_grants: self.copy_grants,
484 enable_schema_evolution: self.enable_schema_evolution,
485 change_tracking: self.change_tracking,
486 data_retention_time_in_days: self.data_retention_time_in_days,
487 max_data_extension_time_in_days: self.max_data_extension_time_in_days,
488 default_ddl_collation: self.default_ddl_collation,
489 with_aggregation_policy: self.with_aggregation_policy,
490 with_row_access_policy: self.with_row_access_policy,
491 with_tags: self.with_tags,
492 base_location: self.base_location,
493 external_volume: self.external_volume,
494 catalog: self.catalog,
495 catalog_sync: self.catalog_sync,
496 storage_serialization_policy: self.storage_serialization_policy,
497 table_options: self.table_options,
498 target_lag: self.target_lag,
499 warehouse: self.warehouse,
500 refresh_mode: self.refresh_mode,
501 initialize: self.initialize,
502 require_user: self.require_user,
503 }
504 .into()
505 }
506}
507
508impl TryFrom<Statement> for CreateTableBuilder {
509 type Error = ParserError;
510
511 fn try_from(stmt: Statement) -> Result<Self, Self::Error> {
514 match stmt {
515 Statement::CreateTable(CreateTable {
516 or_replace,
517 temporary,
518 external,
519 global,
520 if_not_exists,
521 transient,
522 volatile,
523 iceberg,
524 dynamic,
525 name,
526 columns,
527 constraints,
528 hive_distribution,
529 hive_formats,
530 file_format,
531 location,
532 query,
533 without_rowid,
534 like,
535 clone,
536 version,
537 comment,
538 on_commit,
539 on_cluster,
540 primary_key,
541 order_by,
542 partition_by,
543 cluster_by,
544 clustered_by,
545 inherits,
546 partition_of,
547 for_values,
548 strict,
549 copy_grants,
550 enable_schema_evolution,
551 change_tracking,
552 data_retention_time_in_days,
553 max_data_extension_time_in_days,
554 default_ddl_collation,
555 with_aggregation_policy,
556 with_row_access_policy,
557 with_tags,
558 base_location,
559 external_volume,
560 catalog,
561 catalog_sync,
562 storage_serialization_policy,
563 table_options,
564 target_lag,
565 warehouse,
566 refresh_mode,
567 initialize,
568 require_user,
569 }) => Ok(Self {
570 or_replace,
571 temporary,
572 external,
573 global,
574 if_not_exists,
575 transient,
576 dynamic,
577 name,
578 columns,
579 constraints,
580 hive_distribution,
581 hive_formats,
582 file_format,
583 location,
584 query,
585 without_rowid,
586 like,
587 clone,
588 version,
589 comment,
590 on_commit,
591 on_cluster,
592 primary_key,
593 order_by,
594 partition_by,
595 cluster_by,
596 clustered_by,
597 inherits,
598 partition_of,
599 for_values,
600 strict,
601 iceberg,
602 copy_grants,
603 enable_schema_evolution,
604 change_tracking,
605 data_retention_time_in_days,
606 max_data_extension_time_in_days,
607 default_ddl_collation,
608 with_aggregation_policy,
609 with_row_access_policy,
610 with_tags,
611 volatile,
612 base_location,
613 external_volume,
614 catalog,
615 catalog_sync,
616 storage_serialization_policy,
617 table_options,
618 target_lag,
619 warehouse,
620 refresh_mode,
621 initialize,
622 require_user,
623 }),
624 _ => Err(ParserError::ParserError(format!(
625 "Expected create table statement, but received: {stmt}"
626 ))),
627 }
628 }
629}
630
631#[derive(Default)]
633pub(crate) struct CreateTableConfiguration {
634 pub partition_by: Option<Box<Expr>>,
635 pub cluster_by: Option<WrappedCollection<Vec<Expr>>>,
636 pub inherits: Option<Vec<ObjectName>>,
637 pub table_options: CreateTableOptions,
638}
639
640#[cfg(test)]
641mod tests {
642 use crate::ast::helpers::stmt_create_table::CreateTableBuilder;
643 use crate::ast::{Ident, ObjectName, Statement};
644 use crate::parser::ParserError;
645
646 #[test]
647 pub fn test_from_valid_statement() {
648 let builder = CreateTableBuilder::new(ObjectName::from(vec![Ident::new("table_name")]));
649
650 let stmt = builder.clone().build();
651
652 assert_eq!(builder, CreateTableBuilder::try_from(stmt).unwrap());
653 }
654
655 #[test]
656 pub fn test_from_invalid_statement() {
657 let stmt = Statement::Commit {
658 chain: false,
659 end: false,
660 modifier: None,
661 };
662
663 assert_eq!(
664 CreateTableBuilder::try_from(stmt).unwrap_err(),
665 ParserError::ParserError(
666 "Expected create table statement, but received: COMMIT".to_owned()
667 )
668 );
669 }
670}