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