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