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