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