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