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