1#[cfg(not(feature = "std"))]
2use alloc::{boxed::Box, format, string::String, vec, vec::Vec};
3
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7#[cfg(feature = "visitor")]
8use sqlparser_derive::{Visit, VisitMut};
9
10use crate::ast::{
11 ColumnDef, Expr, FileFormat, HiveDistributionStyle, HiveFormat, Ident, ObjectName, OnCommit,
12 Query, SqlOption, Statement, TableConstraint,
13};
14use crate::parser::ParserError;
15
16#[derive(Debug, Clone, PartialEq, Eq, Hash)]
45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
46#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
47pub struct CreateTableBuilder {
48 pub or_replace: bool,
49 pub temporary: bool,
50 pub external: bool,
51 pub global: Option<bool>,
52 pub if_not_exists: bool,
53 pub transient: bool,
54 pub name: ObjectName,
55 pub columns: Vec<ColumnDef>,
56 pub constraints: Vec<TableConstraint>,
57 pub hive_distribution: HiveDistributionStyle,
58 pub hive_formats: Option<HiveFormat>,
59 pub table_properties: Vec<SqlOption>,
60 pub with_options: Vec<SqlOption>,
61 pub file_format: Option<FileFormat>,
62 pub location: Option<String>,
63 pub query: Option<Box<Query>>,
64 pub without_rowid: bool,
65 pub like: Option<ObjectName>,
66 pub clone: Option<ObjectName>,
67 pub engine: Option<String>,
68 pub comment: Option<String>,
69 pub auto_increment_offset: Option<u32>,
70 pub default_charset: Option<String>,
71 pub collation: Option<String>,
72 pub on_commit: Option<OnCommit>,
73 pub on_cluster: Option<String>,
74 pub order_by: Option<Vec<Ident>>,
75 pub partition_by: Option<Box<Expr>>,
76 pub cluster_by: Option<Vec<Ident>>,
77 pub options: Option<Vec<SqlOption>>,
78 pub strict: bool,
79}
80
81impl CreateTableBuilder {
82 pub fn new(name: ObjectName) -> Self {
83 Self {
84 or_replace: false,
85 temporary: false,
86 external: false,
87 global: None,
88 if_not_exists: false,
89 transient: false,
90 name,
91 columns: vec![],
92 constraints: vec![],
93 hive_distribution: HiveDistributionStyle::NONE,
94 hive_formats: None,
95 table_properties: vec![],
96 with_options: vec![],
97 file_format: None,
98 location: None,
99 query: None,
100 without_rowid: false,
101 like: None,
102 clone: None,
103 engine: None,
104 comment: None,
105 auto_increment_offset: None,
106 default_charset: None,
107 collation: None,
108 on_commit: None,
109 on_cluster: None,
110 order_by: None,
111 partition_by: None,
112 cluster_by: None,
113 options: None,
114 strict: false,
115 }
116 }
117 pub fn or_replace(mut self, or_replace: bool) -> Self {
118 self.or_replace = or_replace;
119 self
120 }
121
122 pub fn temporary(mut self, temporary: bool) -> Self {
123 self.temporary = temporary;
124 self
125 }
126
127 pub fn external(mut self, external: bool) -> Self {
128 self.external = external;
129 self
130 }
131
132 pub fn global(mut self, global: Option<bool>) -> Self {
133 self.global = global;
134 self
135 }
136
137 pub fn if_not_exists(mut self, if_not_exists: bool) -> Self {
138 self.if_not_exists = if_not_exists;
139 self
140 }
141
142 pub fn transient(mut self, transient: bool) -> Self {
143 self.transient = transient;
144 self
145 }
146
147 pub fn columns(mut self, columns: Vec<ColumnDef>) -> Self {
148 self.columns = columns;
149 self
150 }
151
152 pub fn constraints(mut self, constraints: Vec<TableConstraint>) -> Self {
153 self.constraints = constraints;
154 self
155 }
156
157 pub fn hive_distribution(mut self, hive_distribution: HiveDistributionStyle) -> Self {
158 self.hive_distribution = hive_distribution;
159 self
160 }
161
162 pub fn hive_formats(mut self, hive_formats: Option<HiveFormat>) -> Self {
163 self.hive_formats = hive_formats;
164 self
165 }
166
167 pub fn table_properties(mut self, table_properties: Vec<SqlOption>) -> Self {
168 self.table_properties = table_properties;
169 self
170 }
171
172 pub fn with_options(mut self, with_options: Vec<SqlOption>) -> Self {
173 self.with_options = with_options;
174 self
175 }
176 pub fn file_format(mut self, file_format: Option<FileFormat>) -> Self {
177 self.file_format = file_format;
178 self
179 }
180 pub fn location(mut self, location: Option<String>) -> Self {
181 self.location = location;
182 self
183 }
184
185 pub fn query(mut self, query: Option<Box<Query>>) -> Self {
186 self.query = query;
187 self
188 }
189 pub fn without_rowid(mut self, without_rowid: bool) -> Self {
190 self.without_rowid = without_rowid;
191 self
192 }
193
194 pub fn like(mut self, like: Option<ObjectName>) -> Self {
195 self.like = like;
196 self
197 }
198
199 pub fn clone_clause(mut self, clone: Option<ObjectName>) -> Self {
201 self.clone = clone;
202 self
203 }
204
205 pub fn engine(mut self, engine: Option<String>) -> Self {
206 self.engine = engine;
207 self
208 }
209
210 pub fn comment(mut self, comment: Option<String>) -> Self {
211 self.comment = comment;
212 self
213 }
214
215 pub fn auto_increment_offset(mut self, offset: Option<u32>) -> Self {
216 self.auto_increment_offset = offset;
217 self
218 }
219
220 pub fn default_charset(mut self, default_charset: Option<String>) -> Self {
221 self.default_charset = default_charset;
222 self
223 }
224
225 pub fn collation(mut self, collation: Option<String>) -> Self {
226 self.collation = collation;
227 self
228 }
229
230 pub fn on_commit(mut self, on_commit: Option<OnCommit>) -> Self {
231 self.on_commit = on_commit;
232 self
233 }
234
235 pub fn on_cluster(mut self, on_cluster: Option<String>) -> Self {
236 self.on_cluster = on_cluster;
237 self
238 }
239
240 pub fn order_by(mut self, order_by: Option<Vec<Ident>>) -> Self {
241 self.order_by = order_by;
242 self
243 }
244
245 pub fn partition_by(mut self, partition_by: Option<Box<Expr>>) -> Self {
246 self.partition_by = partition_by;
247 self
248 }
249
250 pub fn cluster_by(mut self, cluster_by: Option<Vec<Ident>>) -> Self {
251 self.cluster_by = cluster_by;
252 self
253 }
254
255 pub fn options(mut self, options: Option<Vec<SqlOption>>) -> Self {
256 self.options = options;
257 self
258 }
259
260 pub fn strict(mut self, strict: bool) -> Self {
261 self.strict = strict;
262 self
263 }
264
265 pub fn build(self) -> Statement {
266 Statement::CreateTable {
267 or_replace: self.or_replace,
268 temporary: self.temporary,
269 external: self.external,
270 global: self.global,
271 if_not_exists: self.if_not_exists,
272 transient: self.transient,
273 name: self.name,
274 columns: self.columns,
275 constraints: self.constraints,
276 hive_distribution: self.hive_distribution,
277 hive_formats: self.hive_formats,
278 table_properties: self.table_properties,
279 with_options: self.with_options,
280 file_format: self.file_format,
281 location: self.location,
282 query: self.query,
283 without_rowid: self.without_rowid,
284 like: self.like,
285 clone: self.clone,
286 engine: self.engine,
287 comment: self.comment,
288 auto_increment_offset: self.auto_increment_offset,
289 default_charset: self.default_charset,
290 collation: self.collation,
291 on_commit: self.on_commit,
292 on_cluster: self.on_cluster,
293 order_by: self.order_by,
294 partition_by: self.partition_by,
295 cluster_by: self.cluster_by,
296 options: self.options,
297 strict: self.strict,
298 }
299 }
300}
301
302impl TryFrom<Statement> for CreateTableBuilder {
303 type Error = ParserError;
304
305 fn try_from(stmt: Statement) -> Result<Self, Self::Error> {
308 match stmt {
309 Statement::CreateTable {
310 or_replace,
311 temporary,
312 external,
313 global,
314 if_not_exists,
315 transient,
316 name,
317 columns,
318 constraints,
319 hive_distribution,
320 hive_formats,
321 table_properties,
322 with_options,
323 file_format,
324 location,
325 query,
326 without_rowid,
327 like,
328 clone,
329 engine,
330 comment,
331 auto_increment_offset,
332 default_charset,
333 collation,
334 on_commit,
335 on_cluster,
336 order_by,
337 partition_by,
338 cluster_by,
339 options,
340 strict,
341 } => Ok(Self {
342 or_replace,
343 temporary,
344 external,
345 global,
346 if_not_exists,
347 transient,
348 name,
349 columns,
350 constraints,
351 hive_distribution,
352 hive_formats,
353 table_properties,
354 with_options,
355 file_format,
356 location,
357 query,
358 without_rowid,
359 like,
360 clone,
361 engine,
362 comment,
363 auto_increment_offset,
364 default_charset,
365 collation,
366 on_commit,
367 on_cluster,
368 order_by,
369 partition_by,
370 cluster_by,
371 options,
372 strict,
373 }),
374 _ => Err(ParserError::ParserError(format!(
375 "Expected create table statement, but received: {stmt}"
376 ))),
377 }
378 }
379}
380
381#[derive(Default)]
383pub(crate) struct BigQueryTableConfiguration {
384 pub partition_by: Option<Box<Expr>>,
385 pub cluster_by: Option<Vec<Ident>>,
386 pub options: Option<Vec<SqlOption>>,
387}
388
389#[cfg(test)]
390mod tests {
391 use crate::ast::helpers::stmt_create_table::CreateTableBuilder;
392 use crate::ast::{Ident, ObjectName, Statement};
393 use crate::parser::ParserError;
394
395 #[test]
396 pub fn test_from_valid_statement() {
397 let builder = CreateTableBuilder::new(ObjectName(vec![Ident::new("table_name")]));
398
399 let stmt = builder.clone().build();
400
401 assert_eq!(builder, CreateTableBuilder::try_from(stmt).unwrap());
402 }
403
404 #[test]
405 pub fn test_from_invalid_statement() {
406 let stmt = Statement::Commit { chain: false };
407
408 assert_eq!(
409 CreateTableBuilder::try_from(stmt).unwrap_err(),
410 ParserError::ParserError(
411 "Expected create table statement, but received: COMMIT".to_owned()
412 )
413 );
414 }
415}