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