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