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, FileFormat, HiveDistributionStyle, HiveFormat, Ident, ObjectName, OnCommit, Query,
12 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 strict: bool,
76}
77
78impl CreateTableBuilder {
79 pub fn new(name: ObjectName) -> Self {
80 Self {
81 or_replace: false,
82 temporary: false,
83 external: false,
84 global: None,
85 if_not_exists: false,
86 transient: false,
87 name,
88 columns: vec![],
89 constraints: vec![],
90 hive_distribution: HiveDistributionStyle::NONE,
91 hive_formats: None,
92 table_properties: vec![],
93 with_options: vec![],
94 file_format: None,
95 location: None,
96 query: None,
97 without_rowid: false,
98 like: None,
99 clone: None,
100 engine: None,
101 comment: None,
102 auto_increment_offset: None,
103 default_charset: None,
104 collation: None,
105 on_commit: None,
106 on_cluster: None,
107 order_by: None,
108 strict: false,
109 }
110 }
111 pub fn or_replace(mut self, or_replace: bool) -> Self {
112 self.or_replace = or_replace;
113 self
114 }
115
116 pub fn temporary(mut self, temporary: bool) -> Self {
117 self.temporary = temporary;
118 self
119 }
120
121 pub fn external(mut self, external: bool) -> Self {
122 self.external = external;
123 self
124 }
125
126 pub fn global(mut self, global: Option<bool>) -> Self {
127 self.global = global;
128 self
129 }
130
131 pub fn if_not_exists(mut self, if_not_exists: bool) -> Self {
132 self.if_not_exists = if_not_exists;
133 self
134 }
135
136 pub fn transient(mut self, transient: bool) -> Self {
137 self.transient = transient;
138 self
139 }
140
141 pub fn columns(mut self, columns: Vec<ColumnDef>) -> Self {
142 self.columns = columns;
143 self
144 }
145
146 pub fn constraints(mut self, constraints: Vec<TableConstraint>) -> Self {
147 self.constraints = constraints;
148 self
149 }
150
151 pub fn hive_distribution(mut self, hive_distribution: HiveDistributionStyle) -> Self {
152 self.hive_distribution = hive_distribution;
153 self
154 }
155
156 pub fn hive_formats(mut self, hive_formats: Option<HiveFormat>) -> Self {
157 self.hive_formats = hive_formats;
158 self
159 }
160
161 pub fn table_properties(mut self, table_properties: Vec<SqlOption>) -> Self {
162 self.table_properties = table_properties;
163 self
164 }
165
166 pub fn with_options(mut self, with_options: Vec<SqlOption>) -> Self {
167 self.with_options = with_options;
168 self
169 }
170 pub fn file_format(mut self, file_format: Option<FileFormat>) -> Self {
171 self.file_format = file_format;
172 self
173 }
174 pub fn location(mut self, location: Option<String>) -> Self {
175 self.location = location;
176 self
177 }
178
179 pub fn query(mut self, query: Option<Box<Query>>) -> Self {
180 self.query = query;
181 self
182 }
183 pub fn without_rowid(mut self, without_rowid: bool) -> Self {
184 self.without_rowid = without_rowid;
185 self
186 }
187
188 pub fn like(mut self, like: Option<ObjectName>) -> Self {
189 self.like = like;
190 self
191 }
192
193 pub fn clone_clause(mut self, clone: Option<ObjectName>) -> Self {
195 self.clone = clone;
196 self
197 }
198
199 pub fn engine(mut self, engine: Option<String>) -> Self {
200 self.engine = engine;
201 self
202 }
203
204 pub fn comment(mut self, comment: Option<String>) -> Self {
205 self.comment = comment;
206 self
207 }
208
209 pub fn auto_increment_offset(mut self, offset: Option<u32>) -> Self {
210 self.auto_increment_offset = offset;
211 self
212 }
213
214 pub fn default_charset(mut self, default_charset: Option<String>) -> Self {
215 self.default_charset = default_charset;
216 self
217 }
218
219 pub fn collation(mut self, collation: Option<String>) -> Self {
220 self.collation = collation;
221 self
222 }
223
224 pub fn on_commit(mut self, on_commit: Option<OnCommit>) -> Self {
225 self.on_commit = on_commit;
226 self
227 }
228
229 pub fn on_cluster(mut self, on_cluster: Option<String>) -> Self {
230 self.on_cluster = on_cluster;
231 self
232 }
233
234 pub fn order_by(mut self, order_by: Option<Vec<Ident>>) -> Self {
235 self.order_by = order_by;
236 self
237 }
238
239 pub fn strict(mut self, strict: bool) -> Self {
240 self.strict = strict;
241 self
242 }
243
244 pub fn build(self) -> Statement {
245 Statement::CreateTable {
246 or_replace: self.or_replace,
247 temporary: self.temporary,
248 external: self.external,
249 global: self.global,
250 if_not_exists: self.if_not_exists,
251 transient: self.transient,
252 name: self.name,
253 columns: self.columns,
254 constraints: self.constraints,
255 hive_distribution: self.hive_distribution,
256 hive_formats: self.hive_formats,
257 table_properties: self.table_properties,
258 with_options: self.with_options,
259 file_format: self.file_format,
260 location: self.location,
261 query: self.query,
262 without_rowid: self.without_rowid,
263 like: self.like,
264 clone: self.clone,
265 engine: self.engine,
266 comment: self.comment,
267 auto_increment_offset: self.auto_increment_offset,
268 default_charset: self.default_charset,
269 collation: self.collation,
270 on_commit: self.on_commit,
271 on_cluster: self.on_cluster,
272 order_by: self.order_by,
273 strict: self.strict,
274 }
275 }
276}
277
278impl TryFrom<Statement> for CreateTableBuilder {
279 type Error = ParserError;
280
281 fn try_from(stmt: Statement) -> Result<Self, Self::Error> {
284 match stmt {
285 Statement::CreateTable {
286 or_replace,
287 temporary,
288 external,
289 global,
290 if_not_exists,
291 transient,
292 name,
293 columns,
294 constraints,
295 hive_distribution,
296 hive_formats,
297 table_properties,
298 with_options,
299 file_format,
300 location,
301 query,
302 without_rowid,
303 like,
304 clone,
305 engine,
306 comment,
307 auto_increment_offset,
308 default_charset,
309 collation,
310 on_commit,
311 on_cluster,
312 order_by,
313 strict,
314 } => Ok(Self {
315 or_replace,
316 temporary,
317 external,
318 global,
319 if_not_exists,
320 transient,
321 name,
322 columns,
323 constraints,
324 hive_distribution,
325 hive_formats,
326 table_properties,
327 with_options,
328 file_format,
329 location,
330 query,
331 without_rowid,
332 like,
333 clone,
334 engine,
335 comment,
336 auto_increment_offset,
337 default_charset,
338 collation,
339 on_commit,
340 on_cluster,
341 order_by,
342 strict,
343 }),
344 _ => Err(ParserError::ParserError(format!(
345 "Expected create table statement, but received: {stmt}"
346 ))),
347 }
348 }
349}
350
351#[cfg(test)]
352mod tests {
353 use crate::ast::helpers::stmt_create_table::CreateTableBuilder;
354 use crate::ast::{Ident, ObjectName, Statement};
355 use crate::parser::ParserError;
356
357 #[test]
358 pub fn test_from_valid_statement() {
359 let builder = CreateTableBuilder::new(ObjectName(vec![Ident::new("table_name")]));
360
361 let stmt = builder.clone().build();
362
363 assert_eq!(builder, CreateTableBuilder::try_from(stmt).unwrap());
364 }
365
366 #[test]
367 pub fn test_from_invalid_statement() {
368 let stmt = Statement::Commit { chain: false };
369
370 assert_eq!(
371 CreateTableBuilder::try_from(stmt).unwrap_err(),
372 ParserError::ParserError(
373 "Expected create table statement, but received: COMMIT".to_owned()
374 )
375 );
376 }
377}