1use crate::ast::*;
6use crate::dialect::TokenType;
7use crate::dialect::TokenType::*;
8use std::fmt::{self, Display, Formatter};
9use std::ops::Deref;
10
11use super::functions_4::comma;
12use super::types::{FmtTokenStream, WriteTokenStream};
13
14pub trait TokenStream {
16 type Error;
18 fn append(&mut self, ty: TokenType, value: Option<&str>) -> Result<(), Self::Error>;
20}
21
22pub trait ToTokens {
24 fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error>;
26 fn to_fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
28 let mut s = FmtTokenStream { f, spaced: true };
29 self.to_tokens(&mut s)
30 }
31 fn format(&self) -> Result<String, fmt::Error> {
33 let mut s = String::new();
34
35 let mut w = WriteTokenStream {
36 write: &mut s,
37 spaced: true,
38 };
39
40 self.to_tokens(&mut w)?;
41
42 Ok(s)
43 }
44}
45
46impl<T: ?Sized + ToTokens> ToTokens for &T {
47 fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
48 ToTokens::to_tokens(&**self, s)
49 }
50}
51
52impl ToTokens for String {
53 fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
54 s.append(TK_ANY, Some(self.as_ref()))
55 }
56}
57
58impl ToTokens for Cmd {
59 fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
60 match self {
61 Self::Explain(stmt) => {
62 s.append(TK_EXPLAIN, None)?;
63 stmt.to_tokens(s)?;
64 }
65 Self::ExplainQueryPlan(stmt) => {
66 s.append(TK_EXPLAIN, None)?;
67 s.append(TK_QUERY, None)?;
68 s.append(TK_PLAN, None)?;
69 stmt.to_tokens(s)?;
70 }
71 Self::Stmt(stmt) => {
72 stmt.to_tokens(s)?;
73 }
74 }
75 s.append(TK_SEMI, None)
76 }
77}
78
79impl Display for Cmd {
80 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
81 self.to_fmt(f)
82 }
83}
84
85impl ToTokens for Stmt {
86 fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
87 match self {
88 Self::AlterTable(alter_table) => {
89 let (tbl_name, body) = &**alter_table;
90 s.append(TK_ALTER, None)?;
91 s.append(TK_TABLE, None)?;
92 tbl_name.to_tokens(s)?;
93 body.to_tokens(s)
94 }
95 Self::Analyze(obj_name) => {
96 s.append(TK_ANALYZE, None)?;
97 if let Some(obj_name) = obj_name {
98 obj_name.to_tokens(s)?;
99 }
100 Ok(())
101 }
102 Self::Attach {
103 expr,
104 db_name,
105 key,
106 database_kw,
107 } => {
108 s.append(TK_ATTACH, None)?;
109 if *database_kw {
110 s.append(TK_DATABASE, None)?;
111 }
112 expr.to_tokens(s)?;
113 s.append(TK_AS, None)?;
114 db_name.to_tokens(s)?;
115 if let Some(key) = key {
116 s.append(TK_KEY, None)?;
117 key.to_tokens(s)?;
118 }
119 Ok(())
120 }
121 Self::Begin(tx_type, tx_name) => {
122 s.append(TK_BEGIN, None)?;
123 if let Some(tx_type) = tx_type {
124 tx_type.to_tokens(s)?;
125 }
126 if let Some(tx_name) = tx_name {
127 s.append(TK_TRANSACTION, None)?;
128 tx_name.to_tokens(s)?;
129 }
130 Ok(())
131 }
132 Self::Commit(tx_name) => {
133 s.append(TK_COMMIT, None)?;
134 if let Some(tx_name) = tx_name {
135 s.append(TK_TRANSACTION, None)?;
136 tx_name.to_tokens(s)?;
137 }
138 Ok(())
139 }
140 Self::CreateIndex {
141 unique,
142 if_not_exists,
143 idx_name,
144 tbl_name,
145 columns,
146 where_clause,
147 } => {
148 s.append(TK_CREATE, None)?;
149 if *unique {
150 s.append(TK_UNIQUE, None)?;
151 }
152 s.append(TK_INDEX, None)?;
153 if *if_not_exists {
154 s.append(TK_IF, None)?;
155 s.append(TK_NOT, None)?;
156 s.append(TK_EXISTS, None)?;
157 }
158 idx_name.to_tokens(s)?;
159 s.append(TK_ON, None)?;
160 tbl_name.to_tokens(s)?;
161 s.append(TK_LP, None)?;
162 comma(columns, s)?;
163 s.append(TK_RP, None)?;
164 if let Some(where_clause) = where_clause {
165 s.append(TK_WHERE, None)?;
166 where_clause.to_tokens(s)?;
167 }
168 Ok(())
169 }
170 Self::CreateTable {
171 temporary,
172 if_not_exists,
173 tbl_name,
174 body,
175 } => {
176 s.append(TK_CREATE, None)?;
177 if *temporary {
178 s.append(TK_TEMP, None)?;
179 }
180 s.append(TK_TABLE, None)?;
181 if *if_not_exists {
182 s.append(TK_IF, None)?;
183 s.append(TK_NOT, None)?;
184 s.append(TK_EXISTS, None)?;
185 }
186 tbl_name.to_tokens(s)?;
187 body.to_tokens(s)
188 }
189 Self::CreateTrigger(trigger) => {
190 let CreateTrigger {
191 temporary,
192 if_not_exists,
193 trigger_name,
194 time,
195 event,
196 tbl_name,
197 for_each_row,
198 when_clause,
199 commands,
200 } = &**trigger;
201 s.append(TK_CREATE, None)?;
202 if *temporary {
203 s.append(TK_TEMP, None)?;
204 }
205 s.append(TK_TRIGGER, None)?;
206 if *if_not_exists {
207 s.append(TK_IF, None)?;
208 s.append(TK_NOT, None)?;
209 s.append(TK_EXISTS, None)?;
210 }
211 trigger_name.to_tokens(s)?;
212 if let Some(time) = time {
213 time.to_tokens(s)?;
214 }
215 event.to_tokens(s)?;
216 s.append(TK_ON, None)?;
217 tbl_name.to_tokens(s)?;
218 if *for_each_row {
219 s.append(TK_FOR, None)?;
220 s.append(TK_EACH, None)?;
221 s.append(TK_ROW, None)?;
222 }
223 if let Some(when_clause) = when_clause {
224 s.append(TK_WHEN, None)?;
225 when_clause.to_tokens(s)?;
226 }
227 s.append(TK_BEGIN, Some("\n"))?;
228 for command in commands {
229 command.to_tokens(s)?;
230 s.append(TK_SEMI, Some("\n"))?;
231 }
232 s.append(TK_END, None)
233 }
234 Self::CreateView {
235 temporary,
236 if_not_exists,
237 view_name,
238 columns,
239 select,
240 } => {
241 s.append(TK_CREATE, None)?;
242 if *temporary {
243 s.append(TK_TEMP, None)?;
244 }
245 s.append(TK_VIEW, None)?;
246 if *if_not_exists {
247 s.append(TK_IF, None)?;
248 s.append(TK_NOT, None)?;
249 s.append(TK_EXISTS, None)?;
250 }
251 view_name.to_tokens(s)?;
252 if let Some(columns) = columns {
253 s.append(TK_LP, None)?;
254 comma(columns, s)?;
255 s.append(TK_RP, None)?;
256 }
257 s.append(TK_AS, None)?;
258 select.to_tokens(s)
259 }
260 Self::CreateVirtualTable(create_virtual_table) => {
261 let CreateVirtualTable {
262 if_not_exists,
263 tbl_name,
264 module_name,
265 args,
266 } = &**create_virtual_table;
267 s.append(TK_CREATE, None)?;
268 s.append(TK_VIRTUAL, None)?;
269 s.append(TK_TABLE, None)?;
270 if *if_not_exists {
271 s.append(TK_IF, None)?;
272 s.append(TK_NOT, None)?;
273 s.append(TK_EXISTS, None)?;
274 }
275 tbl_name.to_tokens(s)?;
276 s.append(TK_USING, None)?;
277 module_name.to_tokens(s)?;
278 s.append(TK_LP, None)?;
279 if let Some(args) = args {
280 comma(args, s)?;
281 }
282 s.append(TK_RP, None)
283 }
284 Self::Delete(delete) => {
285 let Delete {
286 with,
287 tbl_name,
288 indexed,
289 where_clause,
290 returning,
291 order_by,
292 limit,
293 } = &**delete;
294 if let Some(with) = with {
295 with.to_tokens(s)?;
296 }
297 s.append(TK_DELETE, None)?;
298 s.append(TK_FROM, None)?;
299 tbl_name.to_tokens(s)?;
300 if let Some(indexed) = indexed {
301 indexed.to_tokens(s)?;
302 }
303 if let Some(where_clause) = where_clause {
304 s.append(TK_WHERE, None)?;
305 where_clause.to_tokens(s)?;
306 }
307 if let Some(returning) = returning {
308 s.append(TK_RETURNING, None)?;
309 comma(returning, s)?;
310 }
311 if let Some(order_by) = order_by {
312 s.append(TK_ORDER, None)?;
313 s.append(TK_BY, None)?;
314 comma(order_by, s)?;
315 }
316 if let Some(limit) = limit {
317 limit.to_tokens(s)?;
318 }
319 Ok(())
320 }
321 Self::Detach(expr) => {
322 s.append(TK_DETACH, None)?;
323 expr.to_tokens(s)
324 }
325 Self::DropIndex {
326 if_exists,
327 idx_name,
328 } => {
329 s.append(TK_DROP, None)?;
330 s.append(TK_INDEX, None)?;
331 if *if_exists {
332 s.append(TK_IF, None)?;
333 s.append(TK_EXISTS, None)?;
334 }
335 idx_name.to_tokens(s)
336 }
337 Self::DropTable {
338 if_exists,
339 tbl_name,
340 } => {
341 s.append(TK_DROP, None)?;
342 s.append(TK_TABLE, None)?;
343 if *if_exists {
344 s.append(TK_IF, None)?;
345 s.append(TK_EXISTS, None)?;
346 }
347 tbl_name.to_tokens(s)
348 }
349 Self::DropTrigger {
350 if_exists,
351 trigger_name,
352 } => {
353 s.append(TK_DROP, None)?;
354 s.append(TK_TRIGGER, None)?;
355 if *if_exists {
356 s.append(TK_IF, None)?;
357 s.append(TK_EXISTS, None)?;
358 }
359 trigger_name.to_tokens(s)
360 }
361 Self::DropView {
362 if_exists,
363 view_name,
364 } => {
365 s.append(TK_DROP, None)?;
366 s.append(TK_VIEW, None)?;
367 if *if_exists {
368 s.append(TK_IF, None)?;
369 s.append(TK_EXISTS, None)?;
370 }
371 view_name.to_tokens(s)
372 }
373 Self::Insert(insert) => {
374 let Insert {
375 with,
376 or_conflict,
377 tbl_name,
378 columns,
379 body,
380 returning,
381 } = &**insert;
382 if let Some(with) = with {
383 with.to_tokens(s)?;
384 }
385 if let Some(ResolveType::Replace) = or_conflict {
386 s.append(TK_REPLACE, None)?;
387 } else {
388 s.append(TK_INSERT, None)?;
389 if let Some(or_conflict) = or_conflict {
390 s.append(TK_OR, None)?;
391 or_conflict.to_tokens(s)?;
392 }
393 }
394 s.append(TK_INTO, None)?;
395 tbl_name.to_tokens(s)?;
396 if let Some(columns) = columns {
397 s.append(TK_LP, None)?;
398 comma(columns.deref(), s)?;
399 s.append(TK_RP, None)?;
400 }
401 body.to_tokens(s)?;
402 if let Some(returning) = returning {
403 s.append(TK_RETURNING, None)?;
404 comma(returning, s)?;
405 }
406 Ok(())
407 }
408 Self::Pragma(name, value) => {
409 s.append(TK_PRAGMA, None)?;
410 name.to_tokens(s)?;
411 if let Some(value) = value {
412 value.to_tokens(s)?;
413 }
414 Ok(())
415 }
416 Self::Reindex { obj_name } => {
417 s.append(TK_REINDEX, None)?;
418 if let Some(obj_name) = obj_name {
419 obj_name.to_tokens(s)?;
420 }
421 Ok(())
422 }
423 Self::Release(name) => {
424 s.append(TK_RELEASE, None)?;
425 name.to_tokens(s)
426 }
427 Self::Rollback {
428 tx_name,
429 savepoint_name,
430 } => {
431 s.append(TK_ROLLBACK, None)?;
432 if let Some(tx_name) = tx_name {
433 s.append(TK_TRANSACTION, None)?;
434 tx_name.to_tokens(s)?;
435 }
436 if let Some(savepoint_name) = savepoint_name {
437 s.append(TK_TO, None)?;
438 savepoint_name.to_tokens(s)?;
439 }
440 Ok(())
441 }
442 Self::Savepoint(name) => {
443 s.append(TK_SAVEPOINT, None)?;
444 name.to_tokens(s)
445 }
446 Self::Select(select) => select.to_tokens(s),
447 Self::Update(update) => {
448 let Update {
449 with,
450 or_conflict,
451 tbl_name,
452 indexed,
453 sets,
454 from,
455 where_clause,
456 returning,
457 order_by,
458 limit,
459 } = &**update;
460 if let Some(with) = with {
461 with.to_tokens(s)?;
462 }
463 s.append(TK_UPDATE, None)?;
464 if let Some(or_conflict) = or_conflict {
465 s.append(TK_OR, None)?;
466 or_conflict.to_tokens(s)?;
467 }
468 tbl_name.to_tokens(s)?;
469 if let Some(indexed) = indexed {
470 indexed.to_tokens(s)?;
471 }
472 s.append(TK_SET, None)?;
473 comma(sets, s)?;
474 if let Some(from) = from {
475 s.append(TK_FROM, None)?;
476 from.to_tokens(s)?;
477 }
478 if let Some(where_clause) = where_clause {
479 s.append(TK_WHERE, None)?;
480 where_clause.to_tokens(s)?;
481 }
482 if let Some(returning) = returning {
483 s.append(TK_RETURNING, None)?;
484 comma(returning, s)?;
485 }
486 if let Some(order_by) = order_by {
487 s.append(TK_ORDER, None)?;
488 s.append(TK_BY, None)?;
489 comma(order_by, s)?;
490 }
491 if let Some(limit) = limit {
492 limit.to_tokens(s)?;
493 }
494 Ok(())
495 }
496 Self::Vacuum(name, expr) => {
497 s.append(TK_VACUUM, None)?;
498 if let Some(ref name) = name {
499 name.to_tokens(s)?;
500 }
501 if let Some(ref expr) = expr {
502 s.append(TK_INTO, None)?;
503 expr.to_tokens(s)?;
504 }
505 Ok(())
506 }
507 }
508 }
509}