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