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{:02X}", 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) => {
594 if context.fragment == Fragment::Aliasing {
595 self.write_identifier_quoted(context, out, v);
596 } else {
597 out.push_str(v);
598 }
599 }
600 Operand::LitField(v) => separated_by(out, *v, |out, v| out.push_str(v), "."),
601 Operand::LitInt(v) => write_integer!(out, *v, delimiter),
602 Operand::LitStr(v) => self.write_value_string(context, out, v),
603 Operand::LitArray(v) => {
604 out.push('[');
605 separated_by(
606 out,
607 *v,
608 |out, op| {
609 op.write_query(self.as_dyn(), context, out);
610 },
611 ", ",
612 );
613 out.push(']');
614 }
615 Operand::LitTuple(v) => {
616 out.push('(');
617 separated_by(
618 out,
619 *v,
620 |out, op| {
621 op.write_query(self.as_dyn(), context, out);
622 },
623 ", ",
624 );
625 out.push(')');
626 }
627 Operand::Null => drop(out.push_str("NULL")),
628 Operand::Type(v) => self.write_column_type(context, out, v),
629 Operand::Variable(v) => self.write_value(context, out, v),
630 Operand::Call(f, args) => {
631 out.push_str(f);
632 out.push('(');
633 separated_by(
634 out,
635 *args,
636 |out, expr| {
637 expr.write_query(self.as_dyn(), context, out);
638 },
639 ",",
640 );
641 out.push(')');
642 }
643 Operand::Asterisk => drop(out.push('*')),
644 Operand::QuestionMark => self.write_expression_operand_question_mark(context, out),
645 };
646 }
647
648 fn write_expression_operand_question_mark(&self, _context: &mut Context, out: &mut String) {
650 out.push('?');
651 }
652
653 fn write_expression_unary_op(
655 &self,
656 context: &mut Context,
657 out: &mut String,
658 value: &UnaryOp<&dyn Expression>,
659 ) {
660 match value.op {
661 UnaryOpType::Negative => out.push('-'),
662 UnaryOpType::Not => out.push_str("NOT "),
663 };
664 possibly_parenthesized!(
665 out,
666 value.arg.precedence(self.as_dyn()) <= self.expression_unary_op_precedence(&value.op),
667 value.arg.write_query(self.as_dyn(), context, out)
668 );
669 }
670
671 fn write_expression_binary_op(
673 &self,
674 context: &mut Context,
675 out: &mut String,
676 value: &BinaryOp<&dyn Expression, &dyn Expression>,
677 ) {
678 let (prefix, infix, suffix, lhs_parenthesized, rhs_parenthesized) = match value.op {
679 BinaryOpType::Indexing => ("", "[", "]", false, true),
680 BinaryOpType::Cast => {
681 return self.write_expression_cast(context, out, value.lhs, value.rhs);
682 }
683 BinaryOpType::Multiplication => ("", " * ", "", false, false),
684 BinaryOpType::Division => ("", " / ", "", false, false),
685 BinaryOpType::Remainder => ("", " % ", "", false, false),
686 BinaryOpType::Addition => ("", " + ", "", false, false),
687 BinaryOpType::Subtraction => ("", " - ", "", false, false),
688 BinaryOpType::ShiftLeft => ("", " << ", "", false, false),
689 BinaryOpType::ShiftRight => ("", " >> ", "", false, false),
690 BinaryOpType::BitwiseAnd => ("", " & ", "", false, false),
691 BinaryOpType::BitwiseOr => ("", " | ", "", false, false),
692 BinaryOpType::In => ("", " IN ", "", false, false),
693 BinaryOpType::NotIn => ("", " NOT IN ", "", false, false),
694 BinaryOpType::Is => ("", " IS ", "", false, false),
695 BinaryOpType::IsNot => ("", " IS NOT ", "", false, false),
696 BinaryOpType::Like => ("", " LIKE ", "", false, false),
697 BinaryOpType::NotLike => ("", " NOT LIKE ", "", false, false),
698 BinaryOpType::Regexp => ("", " REGEXP ", "", false, false),
699 BinaryOpType::NotRegexp => ("", " NOT REGEXP ", "", false, false),
700 BinaryOpType::Glob => ("", " GLOB ", "", false, false),
701 BinaryOpType::NotGlob => ("", " NOT GLOB ", "", false, false),
702 BinaryOpType::Equal => ("", " = ", "", false, false),
703 BinaryOpType::NotEqual => ("", " != ", "", false, false),
704 BinaryOpType::Less => ("", " < ", "", false, false),
705 BinaryOpType::LessEqual => ("", " <= ", "", false, false),
706 BinaryOpType::Greater => ("", " > ", "", false, false),
707 BinaryOpType::GreaterEqual => ("", " >= ", "", false, false),
708 BinaryOpType::And => ("", " AND ", "", false, false),
709 BinaryOpType::Or => ("", " OR ", "", false, false),
710 BinaryOpType::Alias => {
711 if context.fragment == Fragment::SqlSelectOrderBy {
712 return value.lhs.write_query(self.as_dyn(), context, out);
713 } else {
714 ("", " AS ", "", false, false)
715 }
716 }
717 };
718 let precedence = self.expression_binary_op_precedence(&value.op);
719 out.push_str(prefix);
720 possibly_parenthesized!(
721 out,
722 !lhs_parenthesized && value.lhs.precedence(self.as_dyn()) < precedence,
723 value.lhs.write_query(self.as_dyn(), context, out)
724 );
725 out.push_str(infix);
726 let mut context = context.switch_fragment(if value.op == BinaryOpType::Alias {
727 Fragment::Aliasing
728 } else {
729 context.fragment
730 });
731 possibly_parenthesized!(
732 out,
733 !rhs_parenthesized && value.rhs.precedence(self.as_dyn()) <= precedence,
734 value
735 .rhs
736 .write_query(self.as_dyn(), &mut context.current, out)
737 );
738 out.push_str(suffix);
739 }
740
741 fn write_expression_cast(
743 &self,
744 context: &mut Context,
745 out: &mut String,
746 expr: &dyn Expression,
747 ty: &dyn Expression,
748 ) {
749 let mut context = context.switch_fragment(Fragment::Casting);
750 out.push_str("CAST(");
751 expr.write_query(self.as_dyn(), &mut context.current, out);
752 out.push_str(" AS ");
753 ty.write_query(self.as_dyn(), &mut context.current, out);
754 out.push(')');
755 }
756
757 fn write_expression_ordered(
759 &self,
760 context: &mut Context,
761 out: &mut String,
762 value: &Ordered<&dyn Expression>,
763 ) {
764 value.expression.write_query(self.as_dyn(), context, out);
765 if context.fragment == Fragment::SqlSelectOrderBy {
766 let _ = write!(
767 out,
768 " {}",
769 match value.order {
770 Order::ASC => "ASC",
771 Order::DESC => "DESC",
772 }
773 );
774 }
775 }
776
777 fn write_join_type(&self, _context: &mut Context, out: &mut String, join_type: &JoinType) {
779 out.push_str(match &join_type {
780 JoinType::Default => "JOIN",
781 JoinType::Inner => "INNER JOIN",
782 JoinType::Outer => "OUTER JOIN",
783 JoinType::Left => "LEFT JOIN",
784 JoinType::Right => "RIGHT JOIN",
785 JoinType::Cross => "CROSS",
786 JoinType::Natural => "NATURAL JOIN",
787 });
788 }
789
790 fn write_join(
792 &self,
793 context: &mut Context,
794 out: &mut String,
795 join: &Join<&dyn DataSet, &dyn DataSet, &dyn Expression>,
796 ) {
797 let mut context = context.switch_fragment(Fragment::SqlJoin);
798 context.current.qualify_columns = true;
799 join.lhs
800 .write_query(self.as_dyn(), &mut context.current, out);
801 out.push(' ');
802 self.write_join_type(&mut context.current, out, &join.join);
803 out.push(' ');
804 join.rhs
805 .write_query(self.as_dyn(), &mut context.current, out);
806 if let Some(on) = &join.on {
807 out.push_str(" ON ");
808 on.write_query(self.as_dyn(), &mut context.current, out);
809 }
810 }
811
812 fn write_transaction_begin(&self, out: &mut String) {
814 out.push_str("BEGIN;");
815 }
816
817 fn write_transaction_commit(&self, out: &mut String) {
819 out.push_str("COMMIT;");
820 }
821
822 fn write_transaction_rollback(&self, out: &mut String) {
824 out.push_str("ROLLBACK;");
825 }
826
827 fn write_create_schema<E>(&self, out: &mut String, if_not_exists: bool)
829 where
830 Self: Sized,
831 E: Entity,
832 {
833 out.reserve(32 + E::table().schema.len());
834 if !out.is_empty() {
835 out.push('\n');
836 }
837 out.push_str("CREATE SCHEMA ");
838 let mut context = Context::new(Fragment::SqlCreateSchema, E::qualified_columns());
839 if if_not_exists {
840 out.push_str("IF NOT EXISTS ");
841 }
842 self.write_identifier_quoted(&mut context, out, E::table().schema());
843 out.push(';');
844 }
845
846 fn write_drop_schema<E>(&self, out: &mut String, if_exists: bool)
848 where
849 Self: Sized,
850 E: Entity,
851 {
852 out.reserve(24 + E::table().schema.len());
853 if !out.is_empty() {
854 out.push('\n');
855 }
856 out.push_str("DROP SCHEMA ");
857 let mut context = Context::new(Fragment::SqlDropSchema, E::qualified_columns());
858 if if_exists {
859 out.push_str("IF EXISTS ");
860 }
861 self.write_identifier_quoted(&mut context, out, E::table().schema());
862 out.push(';');
863 }
864
865 fn write_create_table<E>(&self, out: &mut String, if_not_exists: bool)
867 where
868 Self: Sized,
869 E: Entity,
870 {
871 let mut context = Context::new(Fragment::SqlCreateTable, E::qualified_columns());
872 let estimated = 128 + E::columns().len() * 64 + E::primary_key_def().len() * 24;
873 out.reserve(estimated);
874 if !out.is_empty() {
875 out.push('\n');
876 }
877 out.push_str("CREATE TABLE ");
878 if if_not_exists {
879 out.push_str("IF NOT EXISTS ");
880 }
881 self.write_table_ref(&mut context, out, E::table());
882 out.push_str(" (\n");
883 separated_by(
884 out,
885 E::columns(),
886 |out, col| {
887 self.write_create_table_column_fragment(&mut context, out, col);
888 },
889 ",\n",
890 );
891 let pk = E::primary_key_def();
892 if pk.len() > 1 {
893 self.write_create_table_primary_key_fragment(&mut context, out, pk.iter().map(|v| *v));
894 }
895 for unique in E::unique_defs() {
896 if unique.len() > 1 {
897 out.push_str(",\nUNIQUE (");
898 separated_by(
899 out,
900 unique,
901 |out, col| {
902 self.write_identifier_quoted(
903 &mut context
904 .switch_fragment(Fragment::SqlCreateTableUnique)
905 .current,
906 out,
907 col.name(),
908 );
909 },
910 ", ",
911 );
912 out.push(')');
913 }
914 }
915 let foreign_keys = E::columns().iter().filter(|c| c.references.is_some());
916 separated_by(
917 out,
918 foreign_keys,
919 |out, column| {
920 let references = column.references.unwrap();
921 out.push_str(",\nFOREIGN KEY (");
922 self.write_identifier_quoted(&mut context, out, &column.name());
923 out.push_str(") REFERENCES ");
924 self.write_table_ref(&mut context, out, &references.table());
925 out.push('(');
926 self.write_column_ref(&mut context, out, &references);
927 out.push(')');
928 if let Some(on_delete) = &column.on_delete {
929 out.push_str(" ON DELETE ");
930 self.write_create_table_references_action(&mut context, out, on_delete);
931 }
932 if let Some(on_update) = &column.on_update {
933 out.push_str(" ON UPDATE ");
934 self.write_create_table_references_action(&mut context, out, on_update);
935 }
936 },
937 "",
938 );
939 out.push_str(");");
940 self.write_column_comments_statements::<E>(&mut context, out);
941 }
942
943 fn write_create_table_column_fragment(
945 &self,
946 context: &mut Context,
947 out: &mut String,
948 column: &ColumnDef,
949 ) where
950 Self: Sized,
951 {
952 self.write_identifier_quoted(context, out, &column.name());
953 out.push(' ');
954 let len = out.len();
955 self.write_column_overridden_type(context, out, column, &column.column_type);
956 let didnt_write_type = out.len() == len;
957 if didnt_write_type {
958 SqlWriter::write_column_type(self, context, out, &column.value);
959 }
960 if !column.nullable && column.primary_key == PrimaryKeyType::None {
961 out.push_str(" NOT NULL");
962 }
963 if column.default.is_set() {
964 out.push_str(" DEFAULT ");
965 column.default.write_query(self.as_dyn(), context, out);
966 }
967 if column.primary_key == PrimaryKeyType::PrimaryKey {
968 out.push_str(" PRIMARY KEY");
970 }
971 if column.unique && column.primary_key != PrimaryKeyType::PrimaryKey {
972 out.push_str(" UNIQUE");
973 }
974 if !column.comment.is_empty() {
975 self.write_column_comment_inline(context, out, column);
976 }
977 }
978
979 fn write_create_table_primary_key_fragment<'a, It>(
981 &self,
982 context: &mut Context,
983 out: &mut String,
984 primary_key: It,
985 ) where
986 Self: Sized,
987 It: IntoIterator<Item = &'a ColumnDef>,
988 It::IntoIter: Clone,
989 {
990 out.push_str(",\nPRIMARY KEY (");
991 separated_by(
992 out,
993 primary_key,
994 |out, col| {
995 self.write_identifier_quoted(
996 &mut context
997 .switch_fragment(Fragment::SqlCreateTablePrimaryKey)
998 .current,
999 out,
1000 col.name(),
1001 );
1002 },
1003 ", ",
1004 );
1005 out.push(')');
1006 }
1007
1008 fn write_create_table_references_action(
1010 &self,
1011 _context: &mut Context,
1012 out: &mut String,
1013 action: &Action,
1014 ) {
1015 out.push_str(match action {
1016 Action::NoAction => "NO ACTION",
1017 Action::Restrict => "RESTRICT",
1018 Action::Cascade => "CASCADE",
1019 Action::SetNull => "SET NULL",
1020 Action::SetDefault => "SET DEFAULT",
1021 });
1022 }
1023
1024 fn write_column_comment_inline(
1025 &self,
1026 _context: &mut Context,
1027 _out: &mut String,
1028 _column: &ColumnDef,
1029 ) where
1030 Self: Sized,
1031 {
1032 }
1033
1034 fn write_column_comments_statements<E>(&self, context: &mut Context, out: &mut String)
1036 where
1037 Self: Sized,
1038 E: Entity,
1039 {
1040 let mut context = context.switch_fragment(Fragment::SqlCommentOnColumn);
1041 context.current.qualify_columns = true;
1042 for c in E::columns().iter().filter(|c| !c.comment.is_empty()) {
1043 out.push_str("\nCOMMENT ON COLUMN ");
1044 self.write_column_ref(&mut context.current, out, c.into());
1045 out.push_str(" IS ");
1046 self.write_value_string(&mut context.current, out, c.comment);
1047 out.push(';');
1048 }
1049 }
1050
1051 fn write_drop_table<E>(&self, out: &mut String, if_exists: bool)
1053 where
1054 Self: Sized,
1055 E: Entity,
1056 {
1057 out.reserve(24 + E::table().schema.len() + E::table().name.len());
1058 if !out.is_empty() {
1059 out.push('\n');
1060 }
1061 out.push_str("DROP TABLE ");
1062 let mut context = Context::new(Fragment::SqlDropTable, E::qualified_columns());
1063 if if_exists {
1064 out.push_str("IF EXISTS ");
1065 }
1066 self.write_table_ref(&mut context, out, E::table());
1067 out.push(';');
1068 }
1069
1070 fn write_select<Item, Data>(
1072 &self,
1073 out: &mut String,
1074 columns: impl IntoIterator<Item = Item> + Clone,
1075 from: &Data,
1076 condition: impl Expression,
1077 limit: Option<u32>,
1078 ) where
1079 Self: Sized,
1080 Item: Expression,
1081 Data: DataSet,
1082 {
1083 let cols = columns.clone().into_iter().count();
1084 out.reserve(128 + cols * 32);
1085 if !out.is_empty() {
1086 out.push('\n');
1087 }
1088 out.push_str("SELECT ");
1089 let mut has_order_by = false;
1090 let mut context = Context::new(Fragment::SqlSelect, Data::qualified_columns());
1091 separated_by(
1092 out,
1093 columns.clone(),
1094 |out, col| {
1095 col.write_query(self, &mut context, out);
1096 has_order_by = has_order_by || col.is_ordered();
1097 },
1098 ", ",
1099 );
1100 out.push_str("\nFROM ");
1101 from.write_query(
1102 self,
1103 &mut context.switch_fragment(Fragment::SqlSelectFrom).current,
1104 out,
1105 );
1106 if !condition.is_true() {
1107 out.push_str("\nWHERE ");
1108 condition.write_query(
1109 self,
1110 &mut context.switch_fragment(Fragment::SqlSelectWhere).current,
1111 out,
1112 );
1113 }
1114 if has_order_by {
1115 out.push_str("\nORDER BY ");
1116 let mut order_context = context.switch_fragment(Fragment::SqlSelectOrderBy);
1117 separated_by(
1118 out,
1119 columns.into_iter().filter(Expression::is_ordered),
1120 |out, col| {
1121 col.write_query(self, &mut order_context.current, out);
1122 },
1123 ", ",
1124 );
1125 }
1126 if let Some(limit) = limit {
1127 let _ = write!(out, "\nLIMIT {limit}");
1128 }
1129 out.push(';');
1130 }
1131
1132 fn write_insert<'b, E>(
1134 &self,
1135 out: &mut String,
1136 entities: impl IntoIterator<Item = &'b E>,
1137 update: bool,
1138 ) where
1139 Self: Sized,
1140 E: Entity + 'b,
1141 {
1142 let mut rows = entities.into_iter().map(Entity::row_filtered).peekable();
1143 let Some(mut row) = rows.next() else {
1144 return;
1145 };
1146 let single = rows.peek().is_none();
1147 let cols = E::columns().len();
1148 out.reserve(128 + cols * 48);
1149 if !out.is_empty() {
1150 out.push('\n');
1151 }
1152 out.push_str("INSERT INTO ");
1153 let mut context = Context::new(Fragment::SqlInsertInto, E::qualified_columns());
1154 self.write_table_ref(&mut context, out, E::table());
1155 out.push_str(" (");
1156 let columns = E::columns().iter();
1157 if single {
1158 separated_by(
1160 out,
1161 row.iter(),
1162 |out, (name, ..)| {
1163 self.write_identifier_quoted(&mut context, out, name);
1164 },
1165 ", ",
1166 );
1167 } else {
1168 separated_by(
1169 out,
1170 columns.clone(),
1171 |out, col| {
1172 self.write_identifier_quoted(&mut context, out, col.name());
1173 },
1174 ", ",
1175 );
1176 };
1177 out.push_str(") VALUES\n");
1178 let mut context = context.switch_fragment(Fragment::SqlInsertIntoValues);
1179 let mut first_row = None;
1180 let mut separate = false;
1181 loop {
1182 if separate {
1183 out.push_str(",\n");
1184 }
1185 out.push('(');
1186 let mut fields = row.iter();
1187 let mut field = fields.next();
1188 separated_by(
1189 out,
1190 E::columns(),
1191 |out, col| {
1192 if Some(col.name()) == field.map(|v| v.0) {
1193 self.write_value(
1194 &mut context.current,
1195 out,
1196 field
1197 .map(|v| &v.1)
1198 .expect(&format!("Column {} does not have a value", col.name())),
1199 );
1200 field = fields.next();
1201 } else if !single {
1202 out.push_str("DEFAULT");
1203 }
1204 },
1205 ", ",
1206 );
1207 out.push(')');
1208 separate = true;
1209 if first_row.is_none() {
1210 first_row = row.into();
1211 }
1212 if let Some(next) = rows.next() {
1213 row = next;
1214 } else {
1215 break;
1216 };
1217 }
1218 let first_row = first_row
1219 .expect("Should have at least one row")
1220 .into_iter()
1221 .map(|(v, _)| v);
1222 if update {
1223 self.write_insert_update_fragment::<E>(
1224 &mut context.current,
1225 out,
1226 if single {
1227 EitherIterator::Left(
1228 columns.filter(|c| first_row.clone().find(|n| *n == c.name()).is_some()),
1230 )
1231 } else {
1232 EitherIterator::Right(columns)
1233 },
1234 );
1235 }
1236 out.push(';');
1237 }
1238
1239 fn write_insert_update_fragment<'a, E>(
1241 &self,
1242 context: &mut Context,
1243 out: &mut String,
1244 columns: impl Iterator<Item = &'a ColumnDef> + Clone,
1245 ) where
1246 Self: Sized,
1247 E: Entity,
1248 {
1249 let pk = E::primary_key_def();
1250 if pk.len() == 0 {
1251 return;
1252 }
1253 out.push_str("\nON CONFLICT");
1254 context.fragment = Fragment::SqlInsertIntoOnConflict;
1255 if pk.len() > 0 {
1256 out.push_str(" (");
1257 separated_by(
1258 out,
1259 pk,
1260 |out, col| {
1261 self.write_identifier_quoted(context, out, col.name());
1262 },
1263 ", ",
1264 );
1265 out.push(')');
1266 }
1267 let mut update_cols = columns
1268 .filter(|c| c.primary_key == PrimaryKeyType::None)
1269 .peekable();
1270 if update_cols.peek().is_some() {
1271 out.push_str(" DO UPDATE SET\n");
1272 separated_by(
1273 out,
1274 update_cols,
1275 |out, col| {
1276 self.write_identifier_quoted(context, out, col.name());
1277 out.push_str(" = EXCLUDED.");
1278 self.write_identifier_quoted(context, out, col.name());
1279 },
1280 ",\n",
1281 );
1282 } else {
1283 out.push_str(" DO NOTHING");
1284 }
1285 }
1286
1287 fn write_delete<E>(&self, out: &mut String, condition: impl Expression)
1289 where
1290 Self: Sized,
1291 E: Entity,
1292 {
1293 out.reserve(128 + E::table().schema().len() + E::table().name().len());
1294 if !out.is_empty() {
1295 out.push('\n');
1296 }
1297 out.push_str("DELETE FROM ");
1298 let mut context = Context::new(Fragment::SqlDeleteFrom, E::qualified_columns());
1299 self.write_table_ref(&mut context, out, E::table());
1300 out.push_str("\nWHERE ");
1301 condition.write_query(
1302 self,
1303 &mut context
1304 .switch_fragment(Fragment::SqlDeleteFromWhere)
1305 .current,
1306 out,
1307 );
1308 out.push(';');
1309 }
1310}
1311
1312pub struct GenericSqlWriter;
1314impl GenericSqlWriter {
1315 pub fn new() -> Self {
1317 Self {}
1318 }
1319}
1320impl SqlWriter for GenericSqlWriter {
1321 fn as_dyn(&self) -> &dyn SqlWriter {
1322 self
1323 }
1324}