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