1use crate::{
2 Action, BinaryOp, BinaryOpType, ColumnDef, ColumnRef, DataSet, EitherIterator, Entity,
3 Expression, Fragment, Interval, Join, JoinType, Operand, Order, Ordered, PrimaryKeyType,
4 TableRef, UnaryOp, UnaryOpType, Value, possibly_parenthesized, separated_by, writer::Context,
5};
6use core::f64;
7use futures::future::Either;
8use std::{collections::HashMap, fmt::Write};
9use time::{Date, OffsetDateTime, PrimitiveDateTime, Time};
10
11macro_rules! write_integer {
12 ($out:ident, $value:expr) => {{
13 let mut buffer = itoa::Buffer::new();
14 $out.push_str(buffer.format($value));
15 }};
16}
17macro_rules! write_float {
18 ($this:ident, $context:ident,$out:ident, $value:expr) => {{
19 if $value.is_infinite() {
20 $this.write_value_infinity($context, $out, $value.is_sign_negative());
21 } else if $value.is_nan() {
22 $this.write_value_nan($context, $out);
23 } else {
24 let mut buffer = ryu::Buffer::new();
25 $out.push_str(buffer.format($value));
26 }
27 }};
28}
29
30pub trait SqlWriter {
32 fn as_dyn(&self) -> &dyn SqlWriter;
33
34 fn alias_declaration(&self, context: &mut Context) -> bool {
36 match context.fragment {
37 Fragment::SqlSelectFrom | Fragment::SqlJoin => true,
38 _ => false,
39 }
40 }
41
42 fn write_escaped(
44 &self,
45 _context: &mut Context,
46 out: &mut String,
47 value: &str,
48 search: char,
49 replace: &str,
50 ) {
51 let mut position = 0;
52 for (i, c) in value.char_indices() {
53 if c == search {
54 out.push_str(&value[position..i]);
55 out.push_str(replace);
56 position = i + 1;
57 }
58 }
59 out.push_str(&value[position..]);
60 }
61
62 fn write_identifier_quoted(&self, context: &mut Context, out: &mut String, value: &str) {
64 out.push('"');
65 self.write_escaped(context, out, value, '"', "\"\"");
66 out.push('"');
67 }
68
69 fn write_table_ref(&self, context: &mut Context, out: &mut String, value: &TableRef) {
71 if self.alias_declaration(context) || value.alias.is_empty() {
72 if !value.schema.is_empty() {
73 self.write_identifier_quoted(context, out, &value.schema);
74 out.push('.');
75 }
76 self.write_identifier_quoted(context, out, &value.name);
77 }
78 if !value.alias.is_empty() {
79 let _ = write!(out, " {}", value.alias);
80 }
81 }
82
83 fn write_column_ref(&self, context: &mut Context, out: &mut String, value: &ColumnRef) {
85 if context.qualify_columns && !value.table.is_empty() {
86 if !value.schema.is_empty() {
87 self.write_identifier_quoted(context, out, &value.schema);
88 out.push('.');
89 }
90 self.write_identifier_quoted(context, out, &value.table);
91 out.push('.');
92 }
93 self.write_identifier_quoted(context, out, &value.name);
94 }
95
96 fn write_column_type(&self, context: &mut Context, out: &mut String, value: &Value) {
98 match value {
99 Value::Boolean(..) => out.push_str("BOOLEAN"),
100 Value::Int8(..) => out.push_str("TINYINT"),
101 Value::Int16(..) => out.push_str("SMALLINT"),
102 Value::Int32(..) => out.push_str("INTEGER"),
103 Value::Int64(..) => out.push_str("BIGINT"),
104 Value::Int128(..) => out.push_str("HUGEINT"),
105 Value::UInt8(..) => out.push_str("UTINYINT"),
106 Value::UInt16(..) => out.push_str("USMALLINT"),
107 Value::UInt32(..) => out.push_str("UINTEGER"),
108 Value::UInt64(..) => out.push_str("UBIGINT"),
109 Value::UInt128(..) => out.push_str("UHUGEINT"),
110 Value::Float32(..) => out.push_str("FLOAT"),
111 Value::Float64(..) => out.push_str("DOUBLE"),
112 Value::Decimal(.., precision, scale) => {
113 out.push_str("DECIMAL");
114 if (precision, scale) != (&0, &0) {
115 let _ = write!(out, "({},{})", precision, scale);
116 }
117 }
118 Value::Char(..) => out.push_str("CHAR(1)"),
119 Value::Varchar(..) => out.push_str("VARCHAR"),
120 Value::Blob(..) => out.push_str("BLOB"),
121 Value::Date(..) => out.push_str("DATE"),
122 Value::Time(..) => out.push_str("TIME"),
123 Value::Timestamp(..) => out.push_str("TIMESTAMP"),
124 Value::TimestampWithTimezone(..) => out.push_str("TIMESTAMPTZ"),
125 Value::Interval(..) => out.push_str("INTERVAL"),
126 Value::Uuid(..) => out.push_str("UUID"),
127 Value::Array(.., inner, size) => {
128 self.write_column_type(context, out, inner);
129 let _ = write!(out, "[{}]", size);
130 }
131 Value::List(.., inner) => {
132 self.write_column_type(context, out, inner);
133 out.push_str("[]");
134 }
135 Value::Map(.., key, value) => {
136 out.push_str("MAP(");
137 self.write_column_type(context, out, key);
138 out.push(',');
139 self.write_column_type(context, out, value);
140 out.push(')');
141 }
142 _ => log::error!(
143 "Unexpected tank::Value, variant {:?} is not supported",
144 value
145 ),
146 };
147 }
148
149 fn write_value(&self, context: &mut Context, out: &mut String, value: &Value) {
151 match value {
152 v if v.is_null() => self.write_value_none(context, out),
153 Value::Boolean(Some(v), ..) => self.write_value_bool(context, out, *v),
154 Value::Int8(Some(v), ..) => write_integer!(out, *v),
155 Value::Int16(Some(v), ..) => write_integer!(out, *v),
156 Value::Int32(Some(v), ..) => write_integer!(out, *v),
157 Value::Int64(Some(v), ..) => write_integer!(out, *v),
158 Value::Int128(Some(v), ..) => write_integer!(out, *v),
159 Value::UInt8(Some(v), ..) => write_integer!(out, *v),
160 Value::UInt16(Some(v), ..) => write_integer!(out, *v),
161 Value::UInt32(Some(v), ..) => write_integer!(out, *v),
162 Value::UInt64(Some(v), ..) => write_integer!(out, *v),
163 Value::UInt128(Some(v), ..) => write_integer!(out, *v),
164 Value::Float32(Some(v), ..) => write_float!(self, context, out, *v),
165 Value::Float64(Some(v), ..) => write_float!(self, context, out, *v),
166 Value::Decimal(Some(v), ..) => drop(write!(out, "{}", v)),
167 Value::Char(Some(v), ..) => {
168 out.push('\'');
169 out.push(*v);
170 out.push('\'');
171 }
172 Value::Varchar(Some(v), ..) => self.write_value_string(context, out, v),
173 Value::Blob(Some(v), ..) => self.write_value_blob(context, out, v.as_ref()),
174 Value::Date(Some(v), ..) => self.write_value_date(context, out, v, false),
175 Value::Time(Some(v), ..) => self.write_value_time(context, out, v, false),
176 Value::Timestamp(Some(v), ..) => self.write_value_timestamp(context, out, v),
177 Value::TimestampWithTimezone(Some(v), ..) => {
178 self.write_value_timestamptz(context, out, v)
179 }
180 Value::Interval(Some(v), ..) => self.write_value_interval(context, out, v),
181 Value::Uuid(Some(v), ..) => drop(write!(out, "'{}'", v)),
182 Value::Array(Some(..), ..) | Value::List(Some(..), ..) => match value {
183 Value::Array(Some(v), ..) => {
184 self.write_value_list(context, out, Either::Left(v), value)
185 }
186 Value::List(Some(v), ..) => {
187 self.write_value_list(context, out, Either::Right(v), value)
188 }
189 _ => unreachable!(),
190 },
191 Value::Map(Some(v), ..) => self.write_value_map(context, out, v),
192 Value::Struct(Some(v), ..) => self.write_value_struct(context, out, v),
193 _ => {
194 log::error!("Cannot write {:?}", value);
195 }
196 };
197 }
198
199 fn write_value_none(&self, _context: &mut Context, out: &mut String) {
201 out.push_str("NULL");
202 }
203
204 fn write_value_bool(&self, _context: &mut Context, out: &mut String, value: bool) {
206 out.push_str(["false", "true"][value as usize]);
207 }
208
209 fn write_value_infinity(&self, context: &mut Context, out: &mut String, negative: bool) {
211 let mut buffer = ryu::Buffer::new();
212 self.write_expression_binary_op(
213 context,
214 out,
215 &BinaryOp {
216 op: BinaryOpType::Cast,
217 lhs: &Operand::LitStr(buffer.format(if negative {
218 f64::NEG_INFINITY
219 } else {
220 f64::INFINITY
221 })),
222 rhs: &Operand::Type(Value::Float64(None)),
223 },
224 );
225 }
226
227 fn write_value_nan(&self, context: &mut Context, out: &mut String) {
229 let mut buffer = ryu::Buffer::new();
230 self.write_expression_binary_op(
231 context,
232 out,
233 &BinaryOp {
234 op: BinaryOpType::Cast,
235 lhs: &Operand::LitStr(buffer.format(f64::NAN)),
236 rhs: &Operand::Type(Value::Float64(None)),
237 },
238 );
239 }
240
241 fn write_value_string(&self, _context: &mut Context, out: &mut String, value: &str) {
243 out.push('\'');
244 let mut pos = 0;
245 for (i, c) in value.char_indices() {
246 if c == '\'' {
247 out.push_str(&value[pos..i]);
248 out.push_str("''");
249 pos = i + 1;
250 } else if c == '\n' {
251 out.push_str(&value[pos..i]);
252 out.push_str("\\n");
253 pos = i + 1;
254 }
255 }
256 out.push_str(&value[pos..]);
257 out.push('\'');
258 }
259
260 fn write_value_blob(&self, _context: &mut Context, out: &mut String, value: &[u8]) {
262 out.push('\'');
263 for b in value {
264 let _ = write!(out, "\\x{:X}", b);
265 }
266 out.push('\'');
267 }
268
269 fn write_value_date(
271 &self,
272 _context: &mut Context,
273 out: &mut String,
274 value: &Date,
275 timestamp: bool,
276 ) {
277 let b = if timestamp { "" } else { "'" };
278 let _ = write!(
279 out,
280 "{b}{:04}-{:02}-{:02}{b}",
281 value.year(),
282 value.month() as u8,
283 value.day()
284 );
285 }
286
287 fn write_value_time(
289 &self,
290 _context: &mut Context,
291 out: &mut String,
292 value: &Time,
293 timestamp: bool,
294 ) {
295 let mut subsecond = value.nanosecond();
296 let mut width = 9;
297 while width > 1 && subsecond % 10 == 0 {
298 subsecond /= 10;
299 width -= 1;
300 }
301 let b = if timestamp { "" } else { "'" };
302 let _ = write!(
303 out,
304 "{b}{:02}:{:02}:{:02}.{:0width$}{b}",
305 value.hour(),
306 value.minute(),
307 value.second(),
308 subsecond
309 );
310 }
311
312 fn write_value_timestamp(
314 &self,
315 context: &mut Context,
316 out: &mut String,
317 value: &PrimitiveDateTime,
318 ) {
319 out.push('\'');
320 self.write_value_date(context, out, &value.date(), true);
321 out.push('T');
322 self.write_value_time(context, out, &value.time(), true);
323 out.push('\'');
324 }
325
326 fn write_value_timestamptz(
328 &self,
329 context: &mut Context,
330 out: &mut String,
331 value: &OffsetDateTime,
332 ) {
333 let date_time = value.to_utc();
334 self.write_value_timestamp(
335 context,
336 out,
337 &PrimitiveDateTime::new(date_time.date(), date_time.time()),
338 );
339 }
340
341 fn value_interval_units(&self) -> &[(&str, i128)] {
343 static UNITS: &[(&str, i128)] = &[
344 ("DAY", Interval::NANOS_IN_DAY),
345 ("HOUR", Interval::NANOS_IN_SEC * 3600),
346 ("MINUTE", Interval::NANOS_IN_SEC * 60),
347 ("SECOND", Interval::NANOS_IN_SEC),
348 ("MICROSECOND", 1_000),
349 ("NANOSECOND", 1),
350 ];
351 UNITS
352 }
353
354 fn write_value_interval(&self, _context: &mut Context, out: &mut String, value: &Interval) {
356 out.push_str("INTERVAL '");
357 if value.is_zero() {
358 out.push_str("0 SECONDS");
359 }
360 macro_rules! write_unit {
361 ($out:ident, $len:ident, $val:expr, $unit:expr) => {
362 if $out.len() > $len {
363 $out.push(' ');
364 $len = $out.len();
365 }
366 let _ = write!(
367 $out,
368 "{} {}{}",
369 $val,
370 $unit,
371 if $val != 1 { "S" } else { "" }
372 );
373 };
374 }
375 let mut months = value.months;
376 let mut nanos = value.nanos + value.days as i128 * Interval::NANOS_IN_DAY;
377 let mut len = out.len();
378 if months != 0 {
379 if months > 48 || months % 12 == 0 {
380 write_unit!(out, len, months / 12, "YEAR");
381 months = months % 12;
382 }
383 if months != 0 {
384 write_unit!(out, len, months, "MONTH");
385 }
386 }
387 for &(name, factor) in self.value_interval_units() {
388 let rem = nanos % factor;
389 if rem == 0 || factor / rem > 1_000_000 {
390 let value = nanos / factor;
391 if value != 0 {
392 write_unit!(out, len, value, name);
393 nanos = rem;
394 if nanos == 0 {
395 break;
396 }
397 }
398 }
399 }
400 out.push('\'');
401 }
402
403 fn write_value_list<'a>(
405 &self,
406 context: &mut Context,
407 out: &mut String,
408 value: Either<&Box<[Value]>, &Vec<Value>>,
409 _ty: &Value,
410 ) {
411 out.push('[');
412 separated_by(
413 out,
414 match value {
415 Either::Left(v) => v.iter(),
416 Either::Right(v) => v.iter(),
417 },
418 |out, v| {
419 self.write_value(context, out, v);
420 },
421 ",",
422 );
423 out.push(']');
424 }
425
426 fn write_value_map(
428 &self,
429 context: &mut Context,
430 out: &mut String,
431 value: &HashMap<Value, Value>,
432 ) {
433 out.push('{');
434 separated_by(
435 out,
436 value,
437 |out, (k, v)| {
438 self.write_value(context, out, k);
439 out.push(':');
440 self.write_value(context, out, v);
441 },
442 ",",
443 );
444 out.push('}');
445 }
446
447 fn write_value_struct(
449 &self,
450 context: &mut Context,
451 out: &mut String,
452 value: &Vec<(String, Value)>,
453 ) {
454 out.push('{');
455 separated_by(
456 out,
457 value,
458 |out, (k, v)| {
459 self.write_value_string(context, out, k);
460 out.push(':');
461 self.write_value(context, out, v);
462 },
463 ",",
464 );
465 out.push('}');
466 }
467
468 fn expression_unary_op_precedence<'a>(&self, value: &UnaryOpType) -> i32 {
470 match value {
471 UnaryOpType::Negative => 1250,
472 UnaryOpType::Not => 250,
473 }
474 }
475
476 fn expression_binary_op_precedence<'a>(&self, value: &BinaryOpType) -> i32 {
478 match value {
479 BinaryOpType::Or => 100,
480 BinaryOpType::And => 200,
481 BinaryOpType::Equal => 300,
482 BinaryOpType::NotEqual => 300,
483 BinaryOpType::Less => 300,
484 BinaryOpType::Greater => 300,
485 BinaryOpType::LessEqual => 300,
486 BinaryOpType::GreaterEqual => 300,
487 BinaryOpType::Is => 400,
488 BinaryOpType::IsNot => 400,
489 BinaryOpType::Like => 400,
490 BinaryOpType::NotLike => 400,
491 BinaryOpType::Regexp => 400,
492 BinaryOpType::NotRegexp => 400,
493 BinaryOpType::Glob => 400,
494 BinaryOpType::NotGlob => 400,
495 BinaryOpType::BitwiseOr => 500,
496 BinaryOpType::BitwiseAnd => 600,
497 BinaryOpType::ShiftLeft => 700,
498 BinaryOpType::ShiftRight => 700,
499 BinaryOpType::Subtraction => 800,
500 BinaryOpType::Addition => 800,
501 BinaryOpType::Multiplication => 900,
502 BinaryOpType::Division => 900,
503 BinaryOpType::Remainder => 900,
504 BinaryOpType::Indexing => 1000,
505 BinaryOpType::Cast => 1100,
506 BinaryOpType::Alias => 1200,
507 }
508 }
509
510 fn write_expression_operand(&self, context: &mut Context, out: &mut String, value: &Operand) {
512 match value {
513 Operand::LitBool(v) => self.write_value_bool(context, out, *v),
514 Operand::LitFloat(v) => write_float!(self, context, out, *v),
515 Operand::LitIdent(v) => drop(out.push_str(v)),
516 Operand::LitField(v) => separated_by(out, *v, |out, v| out.push_str(v), "."),
517 Operand::LitInt(v) => write_integer!(out, *v),
518 Operand::LitStr(v) => self.write_value_string(context, out, v),
519 Operand::LitArray(v) => {
520 out.push('[');
521 separated_by(
522 out,
523 *v,
524 |out, v| {
525 v.write_query(self.as_dyn(), context, out);
526 },
527 ", ",
528 );
529 out.push(']');
530 }
531 Operand::Null => drop(out.push_str("NULL")),
532 Operand::Type(v) => self.write_column_type(context, out, v),
533 Operand::Variable(v) => self.write_value(context, out, v),
534 Operand::Call(f, args) => {
535 out.push_str(f);
536 out.push('(');
537 separated_by(
538 out,
539 *args,
540 |out, v| {
541 v.write_query(self.as_dyn(), context, out);
542 },
543 ",",
544 );
545 out.push(')');
546 }
547 Operand::Asterisk => drop(out.push('*')),
548 Operand::QuestionMark => self.write_expression_operand_question_mark(context, out),
549 };
550 }
551
552 fn write_expression_operand_question_mark(&self, _context: &mut Context, out: &mut String) {
554 out.push('?');
555 }
556
557 fn write_expression_unary_op(
559 &self,
560 context: &mut Context,
561 out: &mut String,
562 value: &UnaryOp<&dyn Expression>,
563 ) {
564 match value.op {
565 UnaryOpType::Negative => out.push('-'),
566 UnaryOpType::Not => out.push_str("NOT "),
567 };
568 possibly_parenthesized!(
569 out,
570 value.arg.precedence(self.as_dyn()) <= self.expression_unary_op_precedence(&value.op),
571 value.arg.write_query(self.as_dyn(), context, out)
572 );
573 }
574
575 fn write_expression_binary_op(
577 &self,
578 context: &mut Context,
579 out: &mut String,
580 value: &BinaryOp<&dyn Expression, &dyn Expression>,
581 ) {
582 let (prefix, infix, suffix, lhs_parenthesized, rhs_parenthesized) = match value.op {
583 BinaryOpType::Indexing => ("", "[", "]", false, true),
584 BinaryOpType::Cast => ("CAST(", " AS ", ")", true, true),
585 BinaryOpType::Multiplication => ("", " * ", "", false, false),
586 BinaryOpType::Division => ("", " / ", "", false, false),
587 BinaryOpType::Remainder => ("", " % ", "", false, false),
588 BinaryOpType::Addition => ("", " + ", "", false, false),
589 BinaryOpType::Subtraction => ("", " - ", "", false, false),
590 BinaryOpType::ShiftLeft => ("", " << ", "", false, false),
591 BinaryOpType::ShiftRight => ("", " >> ", "", false, false),
592 BinaryOpType::BitwiseAnd => ("", " & ", "", false, false),
593 BinaryOpType::BitwiseOr => ("", " | ", "", false, false),
594 BinaryOpType::Is => ("", " IS ", "", false, false),
595 BinaryOpType::IsNot => ("", " IS NOT ", "", false, false),
596 BinaryOpType::Like => ("", " LIKE ", "", false, false),
597 BinaryOpType::NotLike => ("", " NOT LIKE ", "", false, false),
598 BinaryOpType::Regexp => ("", " REGEXP ", "", false, false),
599 BinaryOpType::NotRegexp => ("", " NOT REGEXP ", "", false, false),
600 BinaryOpType::Glob => ("", " GLOB ", "", false, false),
601 BinaryOpType::NotGlob => ("", " NOT GLOB ", "", false, false),
602 BinaryOpType::Equal => ("", " = ", "", false, false),
603 BinaryOpType::NotEqual => ("", " != ", "", false, false),
604 BinaryOpType::Less => ("", " < ", "", false, false),
605 BinaryOpType::LessEqual => ("", " <= ", "", false, false),
606 BinaryOpType::Greater => ("", " > ", "", false, false),
607 BinaryOpType::GreaterEqual => ("", " >= ", "", false, false),
608 BinaryOpType::And => ("", " AND ", "", false, false),
609 BinaryOpType::Or => ("", " OR ", "", false, false),
610 BinaryOpType::Alias => {
611 if context.fragment == Fragment::SqlSelectOrderBy {
612 return value.lhs.write_query(self.as_dyn(), context, out);
613 } else {
614 ("", " AS ", "", false, false)
615 }
616 }
617 };
618 let mut context = context.switch_fragment(if value.op == BinaryOpType::Cast {
619 Fragment::Casting
620 } else {
621 context.fragment
622 });
623 let precedence = self.expression_binary_op_precedence(&value.op);
624 out.push_str(prefix);
625 possibly_parenthesized!(
626 out,
627 !lhs_parenthesized && value.lhs.precedence(self.as_dyn()) < precedence,
628 value
629 .lhs
630 .write_query(self.as_dyn(), &mut context.current, out)
631 );
632 out.push_str(infix);
633 possibly_parenthesized!(
634 out,
635 !rhs_parenthesized && value.rhs.precedence(self.as_dyn()) <= precedence,
636 value
637 .rhs
638 .write_query(self.as_dyn(), &mut context.current, out)
639 );
640 out.push_str(suffix);
641 }
642
643 fn write_expression_ordered(
645 &self,
646 context: &mut Context,
647 out: &mut String,
648 value: &Ordered<&dyn Expression>,
649 ) {
650 value.expression.write_query(self.as_dyn(), context, out);
651 if context.fragment == Fragment::SqlSelectOrderBy {
652 let _ = write!(
653 out,
654 " {}",
655 match value.order {
656 Order::ASC => "ASC",
657 Order::DESC => "DESC",
658 }
659 );
660 }
661 }
662
663 fn write_join_type(&self, _context: &mut Context, out: &mut String, join_type: &JoinType) {
665 out.push_str(match &join_type {
666 JoinType::Default => "JOIN",
667 JoinType::Inner => "INNER JOIN",
668 JoinType::Outer => "OUTER JOIN",
669 JoinType::Left => "LEFT JOIN",
670 JoinType::Right => "RIGHT JOIN",
671 JoinType::Cross => "CROSS",
672 JoinType::Natural => "NATURAL JOIN",
673 });
674 }
675
676 fn write_join(
678 &self,
679 context: &mut Context,
680 out: &mut String,
681 join: &Join<&dyn DataSet, &dyn DataSet, &dyn Expression>,
682 ) {
683 let mut context = context.switch_fragment(Fragment::SqlJoin);
684 context.current.qualify_columns = true;
685 join.lhs
686 .write_query(self.as_dyn(), &mut context.current, out);
687 out.push(' ');
688 self.write_join_type(&mut context.current, out, &join.join);
689 out.push(' ');
690 join.rhs
691 .write_query(self.as_dyn(), &mut context.current, out);
692 if let Some(on) = &join.on {
693 out.push_str(" ON ");
694 on.write_query(self.as_dyn(), &mut context.current, out);
695 }
696 }
697
698 fn write_transaction_begin(&self, out: &mut String) {
700 out.push_str("BEGIN;");
701 }
702
703 fn write_transaction_commit(&self, out: &mut String) {
705 out.push_str("COMMIT;");
706 }
707
708 fn write_transaction_rollback(&self, out: &mut String) {
710 out.push_str("ROLLBACK;");
711 }
712
713 fn write_create_schema<E>(&self, out: &mut String, if_not_exists: bool)
715 where
716 Self: Sized,
717 E: Entity,
718 {
719 out.reserve(32 + E::table().schema.len());
720 if !out.is_empty() {
721 out.push('\n');
722 }
723 out.push_str("CREATE SCHEMA ");
724 let mut context = Context::new(Fragment::SqlCreateSchema, E::qualified_columns());
725 if if_not_exists {
726 out.push_str("IF NOT EXISTS ");
727 }
728 self.write_identifier_quoted(&mut context, out, E::table().schema);
729 out.push(';');
730 }
731
732 fn write_drop_schema<E>(&self, out: &mut String, if_exists: bool)
734 where
735 Self: Sized,
736 E: Entity,
737 {
738 out.reserve(24 + E::table().schema.len());
739 if !out.is_empty() {
740 out.push('\n');
741 }
742 out.push_str("DROP SCHEMA ");
743 let mut context = Context::new(Fragment::SqlDropSchema, E::qualified_columns());
744 if if_exists {
745 out.push_str("IF EXISTS ");
746 }
747 self.write_identifier_quoted(&mut context, out, E::table().schema);
748 out.push(';');
749 }
750
751 fn write_create_table<E>(&self, out: &mut String, if_not_exists: bool)
753 where
754 Self: Sized,
755 E: Entity,
756 {
757 let mut context = Context::new(Fragment::SqlCreateTable, E::qualified_columns());
758 let estimated = 128 + E::columns().len() * 64 + E::primary_key_def().len() * 24;
759 out.reserve(estimated);
760 if !out.is_empty() {
761 out.push('\n');
762 }
763 out.push_str("CREATE TABLE ");
764 if if_not_exists {
765 out.push_str("IF NOT EXISTS ");
766 }
767 self.write_table_ref(&mut context, out, E::table());
768 out.push_str(" (\n");
769 separated_by(
770 out,
771 E::columns(),
772 |out, v| {
773 self.write_create_table_column_fragment(&mut context, out, v);
774 },
775 ",\n",
776 );
777 let primary_key = E::primary_key_def();
778 if primary_key.len() > 1 {
779 out.push_str(",\nPRIMARY KEY (");
780 separated_by(
781 out,
782 primary_key,
783 |out, v| {
784 self.write_identifier_quoted(
785 &mut context
786 .switch_fragment(Fragment::SqlCreateTablePrimaryKey)
787 .current,
788 out,
789 v.name(),
790 );
791 },
792 ", ",
793 );
794 out.push(')');
795 }
796 for unique in E::unique_defs() {
797 if unique.len() > 1 {
798 out.push_str(",\nUNIQUE (");
799 separated_by(
800 out,
801 unique,
802 |out, v| {
803 self.write_identifier_quoted(
804 &mut context
805 .switch_fragment(Fragment::SqlCreateTableUnique)
806 .current,
807 out,
808 v.name(),
809 );
810 },
811 ", ",
812 );
813 out.push(')');
814 }
815 }
816 out.push_str(");");
817 self.write_column_comments::<E>(&mut context, out);
818 }
819
820 fn write_column_comments<E>(&self, context: &mut Context, out: &mut String)
822 where
823 Self: Sized,
824 E: Entity,
825 {
826 let mut context = context.switch_fragment(Fragment::SqlCommentOnColumn);
827 context.current.qualify_columns = true;
828 for c in E::columns().iter().filter(|c| !c.comment.is_empty()) {
829 out.push_str("\nCOMMENT ON COLUMN ");
830 self.write_column_ref(&mut context.current, out, c.into());
831 out.push_str(" IS ");
832 self.write_value_string(&mut context.current, out, c.comment);
833 out.push(';');
834 }
835 }
836
837 fn write_create_table_column_fragment(
839 &self,
840 context: &mut Context,
841 out: &mut String,
842 column: &ColumnDef,
843 ) where
844 Self: Sized,
845 {
846 self.write_identifier_quoted(context, out, &column.name());
847 out.push(' ');
848 if !column.column_type.is_empty() {
849 out.push_str(&column.column_type);
850 } else {
851 SqlWriter::write_column_type(self, context, out, &column.value);
852 }
853 if !column.nullable && column.primary_key == PrimaryKeyType::None {
854 out.push_str(" NOT NULL");
855 }
856 if let Some(default) = &column.default {
857 out.push_str(" DEFAULT ");
858 default.write_query(self.as_dyn(), context, out);
859 }
860 if column.primary_key == PrimaryKeyType::PrimaryKey {
861 out.push_str(" PRIMARY KEY");
863 }
864 if column.unique && column.primary_key != PrimaryKeyType::PrimaryKey {
865 out.push_str(" UNIQUE");
866 }
867 if let Some(references) = column.references {
868 out.push_str(" REFERENCES ");
869 self.write_table_ref(context, out, &references.table());
870 out.push('(');
871 self.write_column_ref(context, out, &references);
872 out.push(')');
873 if let Some(on_delete) = &column.on_delete {
874 out.push_str(" ON DELETE ");
875 self.write_create_table_references_action(context, out, on_delete);
876 }
877 if let Some(on_update) = &column.on_update {
878 out.push_str(" ON UPDATE ");
879 self.write_create_table_references_action(context, out, on_update);
880 }
881 }
882 }
883
884 fn write_create_table_references_action(
886 &self,
887 _context: &mut Context,
888 out: &mut String,
889 action: &Action,
890 ) {
891 out.push_str(match action {
892 Action::NoAction => "NO ACTION",
893 Action::Restrict => "RESTRICT",
894 Action::Cascade => "CASCADE",
895 Action::SetNull => "SET NULL",
896 Action::SetDefault => "SET DEFAULT",
897 });
898 }
899
900 fn write_drop_table<E>(&self, out: &mut String, if_exists: bool)
902 where
903 Self: Sized,
904 E: Entity,
905 {
906 out.reserve(24 + E::table().schema.len() + E::table().name.len());
907 if !out.is_empty() {
908 out.push('\n');
909 }
910 out.push_str("DROP TABLE ");
911 let mut context = Context::new(Fragment::SqlDropTable, E::qualified_columns());
912 if if_exists {
913 out.push_str("IF EXISTS ");
914 }
915 self.write_table_ref(&mut context, out, E::table());
916 out.push(';');
917 }
918
919 fn write_select<Item, Cols, Data, Cond>(
921 &self,
922 out: &mut String,
923 columns: Cols,
924 from: &Data,
925 condition: &Cond,
926 limit: Option<u32>,
927 ) where
928 Self: Sized,
929 Item: Expression,
930 Cols: IntoIterator<Item = Item> + Clone,
931 Data: DataSet,
932 Cond: Expression,
933 {
934 let cols = columns.clone().into_iter().count();
935 out.reserve(128 + cols * 32);
936 if !out.is_empty() {
937 out.push('\n');
938 }
939 out.push_str("SELECT ");
940 let mut has_order_by = false;
941 let mut context = Context::new(Fragment::SqlSelect, Data::qualified_columns());
942 separated_by(
943 out,
944 columns.clone(),
945 |out, col| {
946 col.write_query(self, &mut context, out);
947 has_order_by = has_order_by || col.is_ordered();
948 },
949 ", ",
950 );
951 out.push_str("\nFROM ");
952 from.write_query(
953 self,
954 &mut context.switch_fragment(Fragment::SqlSelectFrom).current,
955 out,
956 );
957 out.push_str("\nWHERE ");
958 condition.write_query(
959 self,
960 &mut context.switch_fragment(Fragment::SqlSelectWhere).current,
961 out,
962 );
963 if has_order_by {
964 out.push_str("\nORDER BY ");
965 let mut order_context = context.switch_fragment(Fragment::SqlSelectOrderBy);
966 separated_by(
967 out,
968 columns.into_iter().filter(Expression::is_ordered),
969 |out, col| {
970 col.write_query(self, &mut order_context.current, out);
971 },
972 ", ",
973 );
974 }
975 if let Some(limit) = limit {
976 let _ = write!(out, "\nLIMIT {}", limit);
977 }
978 out.push(';');
979 }
980
981 fn write_insert<'b, E, It>(&self, out: &mut String, entities: It, update: bool)
983 where
984 Self: Sized,
985 E: Entity + 'b,
986 It: IntoIterator<Item = &'b E>,
987 {
988 let mut rows = entities.into_iter().map(Entity::row_filtered).peekable();
989 let Some(mut row) = rows.next() else {
990 return;
991 };
992 let cols = E::columns().len();
993 out.reserve(128 + cols * 48);
994 if !out.is_empty() {
995 out.push('\n');
996 }
997 out.push_str("INSERT INTO ");
998 let mut context = Context::new(Fragment::SqlInsertInto, E::qualified_columns());
999 self.write_table_ref(&mut context, out, E::table());
1000 out.push_str(" (");
1001 let columns = E::columns().iter();
1002 let single = rows.peek().is_none();
1003 if single {
1004 separated_by(
1006 out,
1007 row.iter(),
1008 |out, v| {
1009 self.write_identifier_quoted(&mut context, out, v.0);
1010 },
1011 ", ",
1012 );
1013 } else {
1014 separated_by(
1015 out,
1016 columns.clone(),
1017 |out, v| {
1018 self.write_identifier_quoted(&mut context, out, v.name());
1019 },
1020 ", ",
1021 );
1022 };
1023 out.push_str(") VALUES\n");
1024 let mut context = context.switch_fragment(Fragment::SqlInsertIntoValues);
1025 let mut first_row = None;
1026 let mut separate = false;
1027 loop {
1028 if separate {
1029 out.push_str(",\n");
1030 }
1031 out.push('(');
1032 let mut fields = row.iter();
1033 let mut field = fields.next();
1034 separated_by(
1035 out,
1036 E::columns(),
1037 |out, col| {
1038 if Some(col.name()) == field.map(|v| v.0) {
1039 self.write_value(
1040 &mut context.current,
1041 out,
1042 field
1043 .map(|v| &v.1)
1044 .expect(&format!("Column {} does not have a value", col.name())),
1045 );
1046 field = fields.next();
1047 } else if !single {
1048 out.push_str("DEFAULT");
1049 }
1050 },
1051 ", ",
1052 );
1053 out.push(')');
1054 separate = true;
1055 if first_row.is_none() {
1056 first_row = row.into();
1057 }
1058 if let Some(next) = rows.next() {
1059 row = next;
1060 } else {
1061 break;
1062 };
1063 }
1064 let first_row = first_row
1065 .expect("Should have at least one row")
1066 .into_iter()
1067 .map(|(v, _)| v);
1068 if update {
1069 self.write_insert_update_fragment::<E, _>(
1070 &mut context.current,
1071 out,
1072 if single {
1073 EitherIterator::Left(
1074 columns.filter(|c| first_row.clone().find(|n| *n == c.name()).is_some()),
1076 )
1077 } else {
1078 EitherIterator::Right(columns)
1079 },
1080 );
1081 }
1082 out.push(';');
1083 }
1084
1085 fn write_insert_update_fragment<'a, E, It>(
1087 &self,
1088 context: &mut Context,
1089 out: &mut String,
1090 columns: It,
1091 ) where
1092 Self: Sized,
1093 E: Entity,
1094 It: Iterator<Item = &'a ColumnDef>,
1095 {
1096 let pk = E::primary_key_def();
1097 if pk.len() == 0 {
1098 return;
1099 }
1100 out.push_str("\nON CONFLICT");
1101 context.fragment = Fragment::SqlInsertIntoOnConflict;
1102 if pk.len() > 0 {
1103 out.push_str(" (");
1104 separated_by(
1105 out,
1106 pk,
1107 |out, v| {
1108 self.write_identifier_quoted(context, out, v.name());
1109 },
1110 ", ",
1111 );
1112 out.push(')');
1113 }
1114 out.push_str(" DO UPDATE SET\n");
1115 separated_by(
1116 out,
1117 columns.filter(|c| c.primary_key == PrimaryKeyType::None),
1118 |out, v| {
1119 self.write_identifier_quoted(context, out, v.name());
1120 out.push_str(" = EXCLUDED.");
1121 self.write_identifier_quoted(context, out, v.name());
1122 },
1123 ",\n",
1124 );
1125 }
1126
1127 fn write_delete<E>(&self, out: &mut String, condition: &impl Expression)
1129 where
1130 Self: Sized,
1131 E: Entity,
1132 {
1133 out.reserve(128 + E::table().schema.len() + E::table().name.len());
1134 if !out.is_empty() {
1135 out.push('\n');
1136 }
1137 out.push_str("DELETE FROM ");
1138 let mut context = Context::new(Fragment::SqlDeleteFrom, E::qualified_columns());
1139 self.write_table_ref(&mut context, out, E::table());
1140 out.push_str("\nWHERE ");
1141 condition.write_query(
1142 self,
1143 &mut context
1144 .switch_fragment(Fragment::SqlDeleteFromWhere)
1145 .current,
1146 out,
1147 );
1148 out.push(';');
1149 }
1150}
1151
1152pub struct GenericSqlWriter;
1154impl GenericSqlWriter {
1155 pub fn new() -> Self {
1157 Self {}
1158 }
1159}
1160impl SqlWriter for GenericSqlWriter {
1161 fn as_dyn(&self) -> &dyn SqlWriter {
1162 self
1163 }
1164}