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 = if timestamp { "" } else { "'" };
331 let _ = write!(
332 out,
333 "{b}{:04}-{:02}-{:02}{b}",
334 value.year(),
335 value.month() as u8,
336 value.day()
337 );
338 }
339
340 fn write_value_time(
342 &self,
343 _context: &mut Context,
344 out: &mut String,
345 value: &Time,
346 timestamp: bool,
347 ) {
348 print_timer(
349 out,
350 if timestamp { "" } else { "'" },
351 value.hour() as _,
352 value.minute(),
353 value.second(),
354 value.nanosecond(),
355 );
356 }
357
358 fn write_value_timestamp(
360 &self,
361 context: &mut Context,
362 out: &mut String,
363 value: &PrimitiveDateTime,
364 ) {
365 let delimiter = if context.fragment == Fragment::Json {
366 '"'
367 } else {
368 '\''
369 };
370 out.push(delimiter);
371 self.write_value_date(context, out, &value.date(), true);
372 out.push('T');
373 self.write_value_time(context, out, &value.time(), true);
374 out.push(delimiter);
375 }
376
377 fn write_value_timestamptz(
379 &self,
380 context: &mut Context,
381 out: &mut String,
382 value: &OffsetDateTime,
383 ) {
384 let date_time = value.to_utc();
385 self.write_value_timestamp(
386 context,
387 out,
388 &PrimitiveDateTime::new(date_time.date(), date_time.time()),
389 );
390 }
391
392 fn value_interval_units(&self) -> &[(&str, i128)] {
394 static UNITS: &[(&str, i128)] = &[
395 ("DAY", Interval::NANOS_IN_DAY),
396 ("HOUR", Interval::NANOS_IN_SEC * 3600),
397 ("MINUTE", Interval::NANOS_IN_SEC * 60),
398 ("SECOND", Interval::NANOS_IN_SEC),
399 ("MICROSECOND", 1_000),
400 ("NANOSECOND", 1),
401 ];
402 UNITS
403 }
404
405 fn write_value_interval(&self, context: &mut Context, out: &mut String, value: &Interval) {
407 out.push_str("INTERVAL ");
408 let delimiter = if context.fragment == Fragment::Json {
409 '"'
410 } else {
411 '\''
412 };
413 out.push(delimiter);
414 if value.is_zero() {
415 out.push_str("0 SECONDS");
416 }
417 macro_rules! write_unit {
418 ($out:ident, $len:ident, $val:expr, $unit:expr) => {
419 if $out.len() > $len {
420 $out.push(' ');
421 $len = $out.len();
422 }
423 let _ = write!(
424 $out,
425 "{} {}{}",
426 $val,
427 $unit,
428 if $val != 1 { "S" } else { "" }
429 );
430 };
431 }
432 let mut months = value.months;
433 let mut nanos = value.nanos + value.days as i128 * Interval::NANOS_IN_DAY;
434 let mut len = out.len();
435 if months != 0 {
436 if months > 48 || months % 12 == 0 {
437 write_unit!(out, len, months / 12, "YEAR");
438 months = months % 12;
439 }
440 if months != 0 {
441 write_unit!(out, len, months, "MONTH");
442 }
443 }
444 for &(name, factor) in self.value_interval_units() {
445 let rem = nanos % factor;
446 if rem == 0 || factor / rem > 1_000_000 {
447 let value = nanos / factor;
448 if value != 0 {
449 write_unit!(out, len, value, name);
450 nanos = rem;
451 if nanos == 0 {
452 break;
453 }
454 }
455 }
456 }
457 out.push(delimiter);
458 }
459
460 fn write_value_list(
462 &self,
463 context: &mut Context,
464 out: &mut String,
465 value: Either<&Box<[Value]>, &Vec<Value>>,
466 _ty: &Value,
467 ) {
468 out.push('[');
469 separated_by(
470 out,
471 match value {
472 Either::Left(v) => v.iter(),
473 Either::Right(v) => v.iter(),
474 },
475 |out, v| {
476 self.write_value(context, out, v);
477 },
478 ",",
479 );
480 out.push(']');
481 }
482
483 fn write_value_map(
485 &self,
486 context: &mut Context,
487 out: &mut String,
488 value: &HashMap<Value, Value>,
489 ) {
490 out.push('{');
491 separated_by(
492 out,
493 value,
494 |out, (k, v)| {
495 self.write_value(context, out, k);
496 out.push(':');
497 self.write_value(context, out, v);
498 },
499 ",",
500 );
501 out.push('}');
502 }
503
504 fn write_value_struct(
506 &self,
507 context: &mut Context,
508 out: &mut String,
509 value: &Vec<(String, Value)>,
510 ) {
511 out.push('{');
512 separated_by(
513 out,
514 value,
515 |out, (k, v)| {
516 self.write_value_string(context, out, k);
517 out.push(':');
518 self.write_value(context, out, v);
519 },
520 ",",
521 );
522 out.push('}');
523 }
524
525 fn expression_unary_op_precedence(&self, value: &UnaryOpType) -> i32 {
527 match value {
528 UnaryOpType::Negative => 1250,
529 UnaryOpType::Not => 250,
530 }
531 }
532
533 fn expression_binary_op_precedence(&self, value: &BinaryOpType) -> i32 {
535 match value {
536 BinaryOpType::Or => 100,
537 BinaryOpType::And => 200,
538 BinaryOpType::Equal => 300,
539 BinaryOpType::NotEqual => 300,
540 BinaryOpType::Less => 300,
541 BinaryOpType::Greater => 300,
542 BinaryOpType::LessEqual => 300,
543 BinaryOpType::GreaterEqual => 300,
544 BinaryOpType::Is => 400,
545 BinaryOpType::IsNot => 400,
546 BinaryOpType::Like => 400,
547 BinaryOpType::NotLike => 400,
548 BinaryOpType::Regexp => 400,
549 BinaryOpType::NotRegexp => 400,
550 BinaryOpType::Glob => 400,
551 BinaryOpType::NotGlob => 400,
552 BinaryOpType::BitwiseOr => 500,
553 BinaryOpType::BitwiseAnd => 600,
554 BinaryOpType::ShiftLeft => 700,
555 BinaryOpType::ShiftRight => 700,
556 BinaryOpType::Subtraction => 800,
557 BinaryOpType::Addition => 800,
558 BinaryOpType::Multiplication => 900,
559 BinaryOpType::Division => 900,
560 BinaryOpType::Remainder => 900,
561 BinaryOpType::Indexing => 1000,
562 BinaryOpType::Cast => 1100,
563 BinaryOpType::Alias => 1200,
564 }
565 }
566
567 fn write_expression_operand(&self, context: &mut Context, out: &mut String, value: &Operand) {
569 let delimiter = if context.fragment == Fragment::JsonKey {
570 "\""
571 } else {
572 ""
573 };
574 match value {
575 Operand::LitBool(v) => self.write_value_bool(context, out, *v),
576 Operand::LitFloat(v) => write_float!(self, context, out, *v, delimiter),
577 Operand::LitIdent(v) => drop(out.push_str(v)),
578 Operand::LitField(v) => separated_by(out, *v, |out, v| out.push_str(v), "."),
579 Operand::LitInt(v) => write_integer!(out, *v, delimiter),
580 Operand::LitStr(v) => self.write_value_string(context, out, v),
581 Operand::LitArray(v) => {
582 out.push('[');
583 separated_by(
584 out,
585 *v,
586 |out, v| {
587 v.write_query(self.as_dyn(), context, out);
588 },
589 ", ",
590 );
591 out.push(']');
592 }
593 Operand::Null => drop(out.push_str("NULL")),
594 Operand::Type(v) => self.write_column_type(context, out, v),
595 Operand::Variable(v) => self.write_value(context, out, v),
596 Operand::Call(f, args) => {
597 out.push_str(f);
598 out.push('(');
599 separated_by(
600 out,
601 *args,
602 |out, v| {
603 v.write_query(self.as_dyn(), context, out);
604 },
605 ",",
606 );
607 out.push(')');
608 }
609 Operand::Asterisk => drop(out.push('*')),
610 Operand::QuestionMark => self.write_expression_operand_question_mark(context, out),
611 };
612 }
613
614 fn write_expression_operand_question_mark(&self, _context: &mut Context, out: &mut String) {
616 out.push('?');
617 }
618
619 fn write_expression_unary_op(
621 &self,
622 context: &mut Context,
623 out: &mut String,
624 value: &UnaryOp<&dyn Expression>,
625 ) {
626 match value.op {
627 UnaryOpType::Negative => out.push('-'),
628 UnaryOpType::Not => out.push_str("NOT "),
629 };
630 possibly_parenthesized!(
631 out,
632 value.arg.precedence(self.as_dyn()) <= self.expression_unary_op_precedence(&value.op),
633 value.arg.write_query(self.as_dyn(), context, out)
634 );
635 }
636
637 fn write_expression_binary_op(
639 &self,
640 context: &mut Context,
641 out: &mut String,
642 value: &BinaryOp<&dyn Expression, &dyn Expression>,
643 ) {
644 let (prefix, infix, suffix, lhs_parenthesized, rhs_parenthesized) = match value.op {
645 BinaryOpType::Indexing => ("", "[", "]", false, true),
646 BinaryOpType::Cast => ("CAST(", " AS ", ")", true, true),
647 BinaryOpType::Multiplication => ("", " * ", "", false, false),
648 BinaryOpType::Division => ("", " / ", "", false, false),
649 BinaryOpType::Remainder => ("", " % ", "", false, false),
650 BinaryOpType::Addition => ("", " + ", "", false, false),
651 BinaryOpType::Subtraction => ("", " - ", "", false, false),
652 BinaryOpType::ShiftLeft => ("", " << ", "", false, false),
653 BinaryOpType::ShiftRight => ("", " >> ", "", false, false),
654 BinaryOpType::BitwiseAnd => ("", " & ", "", false, false),
655 BinaryOpType::BitwiseOr => ("", " | ", "", false, false),
656 BinaryOpType::Is => ("", " IS ", "", false, false),
657 BinaryOpType::IsNot => ("", " IS NOT ", "", false, false),
658 BinaryOpType::Like => ("", " LIKE ", "", false, false),
659 BinaryOpType::NotLike => ("", " NOT LIKE ", "", false, false),
660 BinaryOpType::Regexp => ("", " REGEXP ", "", false, false),
661 BinaryOpType::NotRegexp => ("", " NOT REGEXP ", "", false, false),
662 BinaryOpType::Glob => ("", " GLOB ", "", false, false),
663 BinaryOpType::NotGlob => ("", " NOT GLOB ", "", false, false),
664 BinaryOpType::Equal => ("", " = ", "", false, false),
665 BinaryOpType::NotEqual => ("", " != ", "", false, false),
666 BinaryOpType::Less => ("", " < ", "", false, false),
667 BinaryOpType::LessEqual => ("", " <= ", "", false, false),
668 BinaryOpType::Greater => ("", " > ", "", false, false),
669 BinaryOpType::GreaterEqual => ("", " >= ", "", false, false),
670 BinaryOpType::And => ("", " AND ", "", false, false),
671 BinaryOpType::Or => ("", " OR ", "", false, false),
672 BinaryOpType::Alias => {
673 if context.fragment == Fragment::SqlSelectOrderBy {
674 return value.lhs.write_query(self.as_dyn(), context, out);
675 } else {
676 ("", " AS ", "", false, false)
677 }
678 }
679 };
680 let mut context = context.switch_fragment(if value.op == BinaryOpType::Cast {
681 Fragment::Casting
682 } else {
683 context.fragment
684 });
685 let precedence = self.expression_binary_op_precedence(&value.op);
686 out.push_str(prefix);
687 possibly_parenthesized!(
688 out,
689 !lhs_parenthesized && value.lhs.precedence(self.as_dyn()) < precedence,
690 value
691 .lhs
692 .write_query(self.as_dyn(), &mut context.current, out)
693 );
694 out.push_str(infix);
695 possibly_parenthesized!(
696 out,
697 !rhs_parenthesized && value.rhs.precedence(self.as_dyn()) <= precedence,
698 value
699 .rhs
700 .write_query(self.as_dyn(), &mut context.current, out)
701 );
702 out.push_str(suffix);
703 }
704
705 fn write_expression_ordered(
707 &self,
708 context: &mut Context,
709 out: &mut String,
710 value: &Ordered<&dyn Expression>,
711 ) {
712 value.expression.write_query(self.as_dyn(), context, out);
713 if context.fragment == Fragment::SqlSelectOrderBy {
714 let _ = write!(
715 out,
716 " {}",
717 match value.order {
718 Order::ASC => "ASC",
719 Order::DESC => "DESC",
720 }
721 );
722 }
723 }
724
725 fn write_join_type(&self, _context: &mut Context, out: &mut String, join_type: &JoinType) {
727 out.push_str(match &join_type {
728 JoinType::Default => "JOIN",
729 JoinType::Inner => "INNER JOIN",
730 JoinType::Outer => "OUTER JOIN",
731 JoinType::Left => "LEFT JOIN",
732 JoinType::Right => "RIGHT JOIN",
733 JoinType::Cross => "CROSS",
734 JoinType::Natural => "NATURAL JOIN",
735 });
736 }
737
738 fn write_join(
740 &self,
741 context: &mut Context,
742 out: &mut String,
743 join: &Join<&dyn DataSet, &dyn DataSet, &dyn Expression>,
744 ) {
745 let mut context = context.switch_fragment(Fragment::SqlJoin);
746 context.current.qualify_columns = true;
747 join.lhs
748 .write_query(self.as_dyn(), &mut context.current, out);
749 out.push(' ');
750 self.write_join_type(&mut context.current, out, &join.join);
751 out.push(' ');
752 join.rhs
753 .write_query(self.as_dyn(), &mut context.current, out);
754 if let Some(on) = &join.on {
755 out.push_str(" ON ");
756 on.write_query(self.as_dyn(), &mut context.current, out);
757 }
758 }
759
760 fn write_transaction_begin(&self, out: &mut String) {
762 out.push_str("BEGIN;");
763 }
764
765 fn write_transaction_commit(&self, out: &mut String) {
767 out.push_str("COMMIT;");
768 }
769
770 fn write_transaction_rollback(&self, out: &mut String) {
772 out.push_str("ROLLBACK;");
773 }
774
775 fn write_create_schema<E>(&self, out: &mut String, if_not_exists: bool)
777 where
778 Self: Sized,
779 E: Entity,
780 {
781 out.reserve(32 + E::table().schema.len());
782 if !out.is_empty() {
783 out.push('\n');
784 }
785 out.push_str("CREATE SCHEMA ");
786 let mut context = Context::new(Fragment::SqlCreateSchema, E::qualified_columns());
787 if if_not_exists {
788 out.push_str("IF NOT EXISTS ");
789 }
790 self.write_identifier_quoted(&mut context, out, E::table().schema);
791 out.push(';');
792 }
793
794 fn write_drop_schema<E>(&self, out: &mut String, if_exists: bool)
796 where
797 Self: Sized,
798 E: Entity,
799 {
800 out.reserve(24 + E::table().schema.len());
801 if !out.is_empty() {
802 out.push('\n');
803 }
804 out.push_str("DROP SCHEMA ");
805 let mut context = Context::new(Fragment::SqlDropSchema, E::qualified_columns());
806 if if_exists {
807 out.push_str("IF EXISTS ");
808 }
809 self.write_identifier_quoted(&mut context, out, E::table().schema);
810 out.push(';');
811 }
812
813 fn write_create_table<E>(&self, out: &mut String, if_not_exists: bool)
815 where
816 Self: Sized,
817 E: Entity,
818 {
819 let mut context = Context::new(Fragment::SqlCreateTable, E::qualified_columns());
820 let estimated = 128 + E::columns().len() * 64 + E::primary_key_def().len() * 24;
821 out.reserve(estimated);
822 if !out.is_empty() {
823 out.push('\n');
824 }
825 out.push_str("CREATE TABLE ");
826 if if_not_exists {
827 out.push_str("IF NOT EXISTS ");
828 }
829 self.write_table_ref(&mut context, out, E::table());
830 out.push_str(" (\n");
831 separated_by(
832 out,
833 E::columns(),
834 |out, v| {
835 self.write_create_table_column_fragment(&mut context, out, v);
836 },
837 ",\n",
838 );
839 let primary_key = E::primary_key_def();
840 if primary_key.len() > 1 {
841 out.push_str(",\nPRIMARY KEY (");
842 separated_by(
843 out,
844 primary_key,
845 |out, v| {
846 self.write_identifier_quoted(
847 &mut context
848 .switch_fragment(Fragment::SqlCreateTablePrimaryKey)
849 .current,
850 out,
851 v.name(),
852 );
853 },
854 ", ",
855 );
856 out.push(')');
857 }
858 for unique in E::unique_defs() {
859 if unique.len() > 1 {
860 out.push_str(",\nUNIQUE (");
861 separated_by(
862 out,
863 unique,
864 |out, v| {
865 self.write_identifier_quoted(
866 &mut context
867 .switch_fragment(Fragment::SqlCreateTableUnique)
868 .current,
869 out,
870 v.name(),
871 );
872 },
873 ", ",
874 );
875 out.push(')');
876 }
877 }
878 let foreign_keys = E::columns().iter().filter(|c| c.references.is_some());
879 separated_by(
880 out,
881 foreign_keys,
882 |out, column| {
883 let references = column.references.unwrap();
884 out.push_str(",\nFOREIGN KEY (");
885 self.write_identifier_quoted(&mut context, out, &column.name());
886 out.push_str(") REFERENCES ");
887 self.write_table_ref(&mut context, out, &references.table());
888 out.push('(');
889 self.write_column_ref(&mut context, out, &references);
890 out.push(')');
891 if let Some(on_delete) = &column.on_delete {
892 out.push_str(" ON DELETE ");
893 self.write_create_table_references_action(&mut context, out, on_delete);
894 }
895 if let Some(on_update) = &column.on_update {
896 out.push_str(" ON UPDATE ");
897 self.write_create_table_references_action(&mut context, out, on_update);
898 }
899 },
900 "",
901 );
902 out.push_str(");");
903 self.write_column_comments_statements::<E>(&mut context, out);
904 }
905
906 fn write_create_table_column_fragment(
908 &self,
909 context: &mut Context,
910 out: &mut String,
911 column: &ColumnDef,
912 ) where
913 Self: Sized,
914 {
915 self.write_identifier_quoted(context, out, &column.name());
916 out.push(' ');
917 let len = out.len();
918 self.write_column_overridden_type(context, out, column, &column.column_type);
919 let didnt_write_type = out.len() == len;
920 if didnt_write_type {
921 SqlWriter::write_column_type(self, context, out, &column.value);
922 }
923 if !column.nullable && column.primary_key == PrimaryKeyType::None {
924 out.push_str(" NOT NULL");
925 }
926 if let Some(default) = &column.default {
927 out.push_str(" DEFAULT ");
928 default.write_query(self.as_dyn(), context, out);
929 }
930 if column.primary_key == PrimaryKeyType::PrimaryKey {
931 out.push_str(" PRIMARY KEY");
933 }
934 if column.unique && column.primary_key != PrimaryKeyType::PrimaryKey {
935 out.push_str(" UNIQUE");
936 }
937 if !column.comment.is_empty() {
938 self.write_column_comment_inline(context, out, column);
939 }
940 }
941
942 fn write_create_table_references_action(
944 &self,
945 _context: &mut Context,
946 out: &mut String,
947 action: &Action,
948 ) {
949 out.push_str(match action {
950 Action::NoAction => "NO ACTION",
951 Action::Restrict => "RESTRICT",
952 Action::Cascade => "CASCADE",
953 Action::SetNull => "SET NULL",
954 Action::SetDefault => "SET DEFAULT",
955 });
956 }
957
958 fn write_column_comment_inline(
959 &self,
960 _context: &mut Context,
961 _out: &mut String,
962 _column: &ColumnDef,
963 ) where
964 Self: Sized,
965 {
966 }
967
968 fn write_column_comments_statements<E>(&self, context: &mut Context, out: &mut String)
970 where
971 Self: Sized,
972 E: Entity,
973 {
974 let mut context = context.switch_fragment(Fragment::SqlCommentOnColumn);
975 context.current.qualify_columns = true;
976 for c in E::columns().iter().filter(|c| !c.comment.is_empty()) {
977 out.push_str("\nCOMMENT ON COLUMN ");
978 self.write_column_ref(&mut context.current, out, c.into());
979 out.push_str(" IS ");
980 self.write_value_string(&mut context.current, out, c.comment);
981 out.push(';');
982 }
983 }
984
985 fn write_drop_table<E>(&self, out: &mut String, if_exists: bool)
987 where
988 Self: Sized,
989 E: Entity,
990 {
991 out.reserve(24 + E::table().schema.len() + E::table().name.len());
992 if !out.is_empty() {
993 out.push('\n');
994 }
995 out.push_str("DROP TABLE ");
996 let mut context = Context::new(Fragment::SqlDropTable, E::qualified_columns());
997 if if_exists {
998 out.push_str("IF EXISTS ");
999 }
1000 self.write_table_ref(&mut context, out, E::table());
1001 out.push(';');
1002 }
1003
1004 fn write_select<Item, Cols, Data, Cond>(
1006 &self,
1007 out: &mut String,
1008 columns: Cols,
1009 from: &Data,
1010 condition: &Cond,
1011 limit: Option<u32>,
1012 ) where
1013 Self: Sized,
1014 Item: Expression,
1015 Cols: IntoIterator<Item = Item> + Clone,
1016 Data: DataSet,
1017 Cond: Expression,
1018 {
1019 let cols = columns.clone().into_iter().count();
1020 out.reserve(128 + cols * 32);
1021 if !out.is_empty() {
1022 out.push('\n');
1023 }
1024 out.push_str("SELECT ");
1025 let mut has_order_by = false;
1026 let mut context = Context::new(Fragment::SqlSelect, Data::qualified_columns());
1027 separated_by(
1028 out,
1029 columns.clone(),
1030 |out, col| {
1031 col.write_query(self, &mut context, out);
1032 has_order_by = has_order_by || col.is_ordered();
1033 },
1034 ", ",
1035 );
1036 out.push_str("\nFROM ");
1037 from.write_query(
1038 self,
1039 &mut context.switch_fragment(Fragment::SqlSelectFrom).current,
1040 out,
1041 );
1042 out.push_str("\nWHERE ");
1043 condition.write_query(
1044 self,
1045 &mut context.switch_fragment(Fragment::SqlSelectWhere).current,
1046 out,
1047 );
1048 if has_order_by {
1049 out.push_str("\nORDER BY ");
1050 let mut order_context = context.switch_fragment(Fragment::SqlSelectOrderBy);
1051 separated_by(
1052 out,
1053 columns.into_iter().filter(Expression::is_ordered),
1054 |out, col| {
1055 col.write_query(self, &mut order_context.current, out);
1056 },
1057 ", ",
1058 );
1059 }
1060 if let Some(limit) = limit {
1061 let _ = write!(out, "\nLIMIT {}", limit);
1062 }
1063 out.push(';');
1064 }
1065
1066 fn write_insert<'b, E>(
1068 &self,
1069 out: &mut String,
1070 entities: impl IntoIterator<Item = &'b E>,
1071 update: bool,
1072 ) where
1073 Self: Sized,
1074 E: Entity + 'b,
1075 {
1076 let mut rows = entities.into_iter().map(Entity::row_filtered).peekable();
1077 let Some(mut row) = rows.next() else {
1078 return;
1079 };
1080 let cols = E::columns().len();
1081 out.reserve(128 + cols * 48);
1082 if !out.is_empty() {
1083 out.push('\n');
1084 }
1085 out.push_str("INSERT INTO ");
1086 let mut context = Context::new(Fragment::SqlInsertInto, E::qualified_columns());
1087 self.write_table_ref(&mut context, out, E::table());
1088 out.push_str(" (");
1089 let columns = E::columns().iter();
1090 let single = rows.peek().is_none();
1091 if single {
1092 separated_by(
1094 out,
1095 row.iter(),
1096 |out, v| {
1097 self.write_identifier_quoted(&mut context, out, v.0);
1098 },
1099 ", ",
1100 );
1101 } else {
1102 separated_by(
1103 out,
1104 columns.clone(),
1105 |out, v| {
1106 self.write_identifier_quoted(&mut context, out, v.name());
1107 },
1108 ", ",
1109 );
1110 };
1111 out.push_str(") VALUES\n");
1112 let mut context = context.switch_fragment(Fragment::SqlInsertIntoValues);
1113 let mut first_row = None;
1114 let mut separate = false;
1115 loop {
1116 if separate {
1117 out.push_str(",\n");
1118 }
1119 out.push('(');
1120 let mut fields = row.iter();
1121 let mut field = fields.next();
1122 separated_by(
1123 out,
1124 E::columns(),
1125 |out, col| {
1126 if Some(col.name()) == field.map(|v| v.0) {
1127 self.write_value(
1128 &mut context.current,
1129 out,
1130 field
1131 .map(|v| &v.1)
1132 .expect(&format!("Column {} does not have a value", col.name())),
1133 );
1134 field = fields.next();
1135 } else if !single {
1136 out.push_str("DEFAULT");
1137 }
1138 },
1139 ", ",
1140 );
1141 out.push(')');
1142 separate = true;
1143 if first_row.is_none() {
1144 first_row = row.into();
1145 }
1146 if let Some(next) = rows.next() {
1147 row = next;
1148 } else {
1149 break;
1150 };
1151 }
1152 let first_row = first_row
1153 .expect("Should have at least one row")
1154 .into_iter()
1155 .map(|(v, _)| v);
1156 if update {
1157 self.write_insert_update_fragment::<E>(
1158 &mut context.current,
1159 out,
1160 if single {
1161 EitherIterator::Left(
1162 columns.filter(|c| first_row.clone().find(|n| *n == c.name()).is_some()),
1164 )
1165 } else {
1166 EitherIterator::Right(columns)
1167 },
1168 );
1169 }
1170 out.push(';');
1171 }
1172
1173 fn write_insert_update_fragment<'a, E>(
1175 &self,
1176 context: &mut Context,
1177 out: &mut String,
1178 columns: impl Iterator<Item = &'a ColumnDef>,
1179 ) where
1180 Self: Sized,
1181 E: Entity,
1182 {
1183 let pk = E::primary_key_def();
1184 if pk.len() == 0 {
1185 return;
1186 }
1187 out.push_str("\nON CONFLICT");
1188 context.fragment = Fragment::SqlInsertIntoOnConflict;
1189 if pk.len() > 0 {
1190 out.push_str(" (");
1191 separated_by(
1192 out,
1193 pk,
1194 |out, v| {
1195 self.write_identifier_quoted(context, out, v.name());
1196 },
1197 ", ",
1198 );
1199 out.push(')');
1200 }
1201 out.push_str(" DO UPDATE SET\n");
1202 separated_by(
1203 out,
1204 columns.filter(|c| c.primary_key == PrimaryKeyType::None),
1205 |out, v| {
1206 self.write_identifier_quoted(context, out, v.name());
1207 out.push_str(" = EXCLUDED.");
1208 self.write_identifier_quoted(context, out, v.name());
1209 },
1210 ",\n",
1211 );
1212 }
1213
1214 fn write_delete<E>(&self, out: &mut String, condition: &impl Expression)
1216 where
1217 Self: Sized,
1218 E: Entity,
1219 {
1220 out.reserve(128 + E::table().schema.len() + E::table().name.len());
1221 if !out.is_empty() {
1222 out.push('\n');
1223 }
1224 out.push_str("DELETE FROM ");
1225 let mut context = Context::new(Fragment::SqlDeleteFrom, E::qualified_columns());
1226 self.write_table_ref(&mut context, out, E::table());
1227 out.push_str("\nWHERE ");
1228 condition.write_query(
1229 self,
1230 &mut context
1231 .switch_fragment(Fragment::SqlDeleteFromWhere)
1232 .current,
1233 out,
1234 );
1235 out.push(';');
1236 }
1237}
1238
1239pub struct GenericSqlWriter;
1241impl GenericSqlWriter {
1242 pub fn new() -> Self {
1244 Self {}
1245 }
1246}
1247impl SqlWriter for GenericSqlWriter {
1248 fn as_dyn(&self) -> &dyn SqlWriter {
1249 self
1250 }
1251}