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 yachtsql_sqlparser_derive::{Visit, VisitMut};
26
27use crate::ast::{
28 CatalogSyncNamespaceMode, ContactEntry, ObjectName, Statement, StorageSerializationPolicy, Tag,
29};
30use crate::parser::ParserError;
31
32#[derive(Debug, Clone, PartialEq, Eq, Hash)]
55#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
56#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
57pub struct CreateDatabaseBuilder {
58 pub db_name: ObjectName,
59 pub if_not_exists: bool,
60 pub location: Option<String>,
61 pub managed_location: Option<String>,
62 pub or_replace: bool,
63 pub transient: bool,
64 pub clone: Option<ObjectName>,
65 pub data_retention_time_in_days: Option<u64>,
66 pub max_data_extension_time_in_days: Option<u64>,
67 pub external_volume: Option<String>,
68 pub catalog: Option<String>,
69 pub replace_invalid_characters: Option<bool>,
70 pub default_ddl_collation: Option<String>,
71 pub storage_serialization_policy: Option<StorageSerializationPolicy>,
72 pub comment: Option<String>,
73 pub catalog_sync: Option<String>,
74 pub catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
75 pub catalog_sync_namespace_flatten_delimiter: Option<String>,
76 pub with_tags: Option<Vec<Tag>>,
77 pub with_contacts: Option<Vec<ContactEntry>>,
78}
79
80impl CreateDatabaseBuilder {
81 pub fn new(name: ObjectName) -> Self {
82 Self {
83 db_name: name,
84 if_not_exists: false,
85 location: None,
86 managed_location: None,
87 or_replace: false,
88 transient: false,
89 clone: None,
90 data_retention_time_in_days: None,
91 max_data_extension_time_in_days: None,
92 external_volume: None,
93 catalog: None,
94 replace_invalid_characters: None,
95 default_ddl_collation: None,
96 storage_serialization_policy: None,
97 comment: None,
98 catalog_sync: None,
99 catalog_sync_namespace_mode: None,
100 catalog_sync_namespace_flatten_delimiter: None,
101 with_tags: None,
102 with_contacts: None,
103 }
104 }
105
106 pub fn location(mut self, location: Option<String>) -> Self {
107 self.location = location;
108 self
109 }
110
111 pub fn managed_location(mut self, managed_location: Option<String>) -> Self {
112 self.managed_location = managed_location;
113 self
114 }
115
116 pub fn or_replace(mut self, or_replace: bool) -> Self {
117 self.or_replace = or_replace;
118 self
119 }
120
121 pub fn transient(mut self, transient: bool) -> Self {
122 self.transient = transient;
123 self
124 }
125
126 pub fn if_not_exists(mut self, if_not_exists: bool) -> Self {
127 self.if_not_exists = if_not_exists;
128 self
129 }
130
131 pub fn clone_clause(mut self, clone: Option<ObjectName>) -> Self {
132 self.clone = clone;
133 self
134 }
135
136 pub fn data_retention_time_in_days(mut self, data_retention_time_in_days: Option<u64>) -> Self {
137 self.data_retention_time_in_days = data_retention_time_in_days;
138 self
139 }
140
141 pub fn max_data_extension_time_in_days(
142 mut self,
143 max_data_extension_time_in_days: Option<u64>,
144 ) -> Self {
145 self.max_data_extension_time_in_days = max_data_extension_time_in_days;
146 self
147 }
148
149 pub fn external_volume(mut self, external_volume: Option<String>) -> Self {
150 self.external_volume = external_volume;
151 self
152 }
153
154 pub fn catalog(mut self, catalog: Option<String>) -> Self {
155 self.catalog = catalog;
156 self
157 }
158
159 pub fn replace_invalid_characters(mut self, replace_invalid_characters: Option<bool>) -> Self {
160 self.replace_invalid_characters = replace_invalid_characters;
161 self
162 }
163
164 pub fn default_ddl_collation(mut self, default_ddl_collation: Option<String>) -> Self {
165 self.default_ddl_collation = default_ddl_collation;
166 self
167 }
168
169 pub fn storage_serialization_policy(
170 mut self,
171 storage_serialization_policy: Option<StorageSerializationPolicy>,
172 ) -> Self {
173 self.storage_serialization_policy = storage_serialization_policy;
174 self
175 }
176
177 pub fn comment(mut self, comment: Option<String>) -> Self {
178 self.comment = comment;
179 self
180 }
181
182 pub fn catalog_sync(mut self, catalog_sync: Option<String>) -> Self {
183 self.catalog_sync = catalog_sync;
184 self
185 }
186
187 pub fn catalog_sync_namespace_mode(
188 mut self,
189 catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
190 ) -> Self {
191 self.catalog_sync_namespace_mode = catalog_sync_namespace_mode;
192 self
193 }
194
195 pub fn catalog_sync_namespace_flatten_delimiter(
196 mut self,
197 catalog_sync_namespace_flatten_delimiter: Option<String>,
198 ) -> Self {
199 self.catalog_sync_namespace_flatten_delimiter = catalog_sync_namespace_flatten_delimiter;
200 self
201 }
202
203 pub fn with_tags(mut self, with_tags: Option<Vec<Tag>>) -> Self {
204 self.with_tags = with_tags;
205 self
206 }
207
208 pub fn with_contacts(mut self, with_contacts: Option<Vec<ContactEntry>>) -> Self {
209 self.with_contacts = with_contacts;
210 self
211 }
212
213 pub fn build(self) -> Statement {
214 Statement::CreateDatabase {
215 db_name: self.db_name,
216 if_not_exists: self.if_not_exists,
217 managed_location: self.managed_location,
218 location: self.location,
219 or_replace: self.or_replace,
220 transient: self.transient,
221 clone: self.clone,
222 data_retention_time_in_days: self.data_retention_time_in_days,
223 max_data_extension_time_in_days: self.max_data_extension_time_in_days,
224 external_volume: self.external_volume,
225 catalog: self.catalog,
226 replace_invalid_characters: self.replace_invalid_characters,
227 default_ddl_collation: self.default_ddl_collation,
228 storage_serialization_policy: self.storage_serialization_policy,
229 comment: self.comment,
230 catalog_sync: self.catalog_sync,
231 catalog_sync_namespace_mode: self.catalog_sync_namespace_mode,
232 catalog_sync_namespace_flatten_delimiter: self.catalog_sync_namespace_flatten_delimiter,
233 with_tags: self.with_tags,
234 with_contacts: self.with_contacts,
235 }
236 }
237}
238
239impl TryFrom<Statement> for CreateDatabaseBuilder {
240 type Error = ParserError;
241
242 fn try_from(stmt: Statement) -> Result<Self, Self::Error> {
243 match stmt {
244 Statement::CreateDatabase {
245 db_name,
246 if_not_exists,
247 location,
248 managed_location,
249 or_replace,
250 transient,
251 clone,
252 data_retention_time_in_days,
253 max_data_extension_time_in_days,
254 external_volume,
255 catalog,
256 replace_invalid_characters,
257 default_ddl_collation,
258 storage_serialization_policy,
259 comment,
260 catalog_sync,
261 catalog_sync_namespace_mode,
262 catalog_sync_namespace_flatten_delimiter,
263 with_tags,
264 with_contacts,
265 } => Ok(Self {
266 db_name,
267 if_not_exists,
268 location,
269 managed_location,
270 or_replace,
271 transient,
272 clone,
273 data_retention_time_in_days,
274 max_data_extension_time_in_days,
275 external_volume,
276 catalog,
277 replace_invalid_characters,
278 default_ddl_collation,
279 storage_serialization_policy,
280 comment,
281 catalog_sync,
282 catalog_sync_namespace_mode,
283 catalog_sync_namespace_flatten_delimiter,
284 with_tags,
285 with_contacts,
286 }),
287 _ => Err(ParserError::ParserError(format!(
288 "Expected create database statement, but received: {stmt}"
289 ))),
290 }
291 }
292}
293
294#[cfg(test)]
295mod tests {
296 use crate::ast::helpers::stmt_create_database::CreateDatabaseBuilder;
297 use crate::ast::{Ident, ObjectName, Statement};
298 use crate::parser::ParserError;
299
300 #[test]
301 pub fn test_from_valid_statement() {
302 let builder = CreateDatabaseBuilder::new(ObjectName::from(vec![Ident::new("db_name")]));
303
304 let stmt = builder.clone().build();
305
306 assert_eq!(builder, CreateDatabaseBuilder::try_from(stmt).unwrap());
307 }
308
309 #[test]
310 pub fn test_from_invalid_statement() {
311 let stmt = Statement::Commit {
312 chain: false,
313 end: false,
314 modifier: None,
315 };
316
317 assert_eq!(
318 CreateDatabaseBuilder::try_from(stmt).unwrap_err(),
319 ParserError::ParserError(
320 "Expected create database statement, but received: COMMIT".to_owned()
321 )
322 );
323 }
324}