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(
342 &self,
343 context: &mut Context,
344 out: &mut DynQuery,
345 value: &Date,
346 timestamp: bool,
347 ) {
348 let b = match context.fragment {
349 Fragment::Json if !timestamp => "\"",
350 _ if !timestamp => "'",
351 _ => "",
352 };
353 print_date(out, b, value);
354 }
355
356 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: &mut dyn Iterator<Item = &Value>,
494 _ty: &Value,
495 _elem_ty: &Value,
496 ) {
497 self.write_expression_list(context, out, &mut value.map(|v| v as &dyn Expression));
498 }
499
500 fn write_value_map(
502 &self,
503 context: &mut Context,
504 out: &mut DynQuery,
505 value: &HashMap<Value, Value>,
506 ) {
507 out.push('{');
508 separated_by(
509 out,
510 value,
511 |out, (k, v)| {
512 self.write_value(context, out, k);
513 out.push(':');
514 self.write_value(context, out, v);
515 },
516 ",",
517 );
518 out.push('}');
519 }
520
521 fn write_value_struct(
523 &self,
524 context: &mut Context,
525 out: &mut DynQuery,
526 value: &Vec<(String, Value)>,
527 ) {
528 out.push('{');
529 separated_by(
530 out,
531 value,
532 |out, (k, v)| {
533 self.write_value_string(context, out, k);
534 out.push(':');
535 self.write_value(context, out, v);
536 },
537 ",",
538 );
539 out.push('}');
540 }
541
542 fn expression_unary_op_precedence(&self, value: &UnaryOpType) -> i32 {
544 match value {
545 UnaryOpType::Negative => 1250,
546 UnaryOpType::Not => 250,
547 }
548 }
549
550 fn expression_binary_op_precedence(&self, value: &BinaryOpType) -> i32 {
552 match value {
553 BinaryOpType::Or => 100,
554 BinaryOpType::And => 200,
555 BinaryOpType::Equal => 300,
556 BinaryOpType::NotEqual => 300,
557 BinaryOpType::Less => 300,
558 BinaryOpType::Greater => 300,
559 BinaryOpType::LessEqual => 300,
560 BinaryOpType::GreaterEqual => 300,
561 BinaryOpType::In => 400,
562 BinaryOpType::NotIn => 400,
563 BinaryOpType::Is => 400,
564 BinaryOpType::IsNot => 400,
565 BinaryOpType::Like => 400,
566 BinaryOpType::NotLike => 400,
567 BinaryOpType::Regexp => 400,
568 BinaryOpType::NotRegexp => 400,
569 BinaryOpType::Glob => 400,
570 BinaryOpType::NotGlob => 400,
571 BinaryOpType::BitwiseOr => 500,
572 BinaryOpType::BitwiseAnd => 600,
573 BinaryOpType::ShiftLeft => 700,
574 BinaryOpType::ShiftRight => 700,
575 BinaryOpType::Subtraction => 800,
576 BinaryOpType::Addition => 800,
577 BinaryOpType::Multiplication => 900,
578 BinaryOpType::Division => 900,
579 BinaryOpType::Remainder => 900,
580 BinaryOpType::Indexing => 1000,
581 BinaryOpType::Cast => 1100,
582 BinaryOpType::Alias => 1200,
583 }
584 }
585
586 fn write_expression_operand(&self, context: &mut Context, out: &mut DynQuery, value: &Operand) {
588 match value {
589 Operand::Null => self.write_value_none(context, out),
590 Operand::LitBool(v) => self.write_value_bool(context, out, *v),
591 Operand::LitInt(v) => self.write_value_i128(context, out, *v),
592 Operand::LitFloat(v) => self.write_value_f64(context, out, *v),
593 Operand::LitStr(v) => self.write_value_string(context, out, v),
594 Operand::LitIdent(v) => {
595 self.write_identifier(context, out, v, context.fragment == Fragment::Aliasing)
596 }
597 Operand::LitField(v) => self.write_identifier(context, out, &v.join("."), false),
598 Operand::LitArray(v) => self.write_expression_list(
599 context,
600 out,
601 &mut v.iter().map(|v| v as &dyn Expression),
602 ),
603 Operand::LitTuple(v) => self.write_expression_tuple(
604 context,
605 out,
606 &mut v.iter().map(|v| v as &dyn Expression),
607 ),
608 Operand::Type(v) => self.write_column_type(context, out, v),
609 Operand::Variable(v) => self.write_value(context, out, v),
610 Operand::Value(v) => self.write_value(context, out, v),
611 Operand::Call(f, args) => self.write_expression_call(context, out, f, args),
612 Operand::Asterisk => drop(out.push('*')),
613 Operand::QuestionMark => self.write_expression_operand_question_mark(context, out),
614 Operand::CurrentTimestampMs => {
615 self.write_expression_operand_current_timestamp_ms(context, out)
616 }
617 };
618 }
619
620 fn write_expression_operand_question_mark(&self, context: &mut Context, out: &mut DynQuery) {
622 context.counter += 1;
623 out.push('?');
624 }
625
626 fn write_expression_operand_current_timestamp_ms(
627 &self,
628 _context: &mut Context,
629 out: &mut DynQuery,
630 ) {
631 out.push_str("NOW()");
632 }
633
634 fn write_expression_unary_op(
636 &self,
637 context: &mut Context,
638 out: &mut DynQuery,
639 value: &UnaryOp<&dyn Expression>,
640 ) {
641 match value.op {
642 UnaryOpType::Negative => out.push('-'),
643 UnaryOpType::Not => out.push_str("NOT "),
644 };
645 possibly_parenthesized!(
646 out,
647 value.arg.precedence(self.as_dyn()) <= self.expression_unary_op_precedence(&value.op),
648 value.arg.write_query(self.as_dyn(), context, out)
649 );
650 }
651
652 fn write_expression_binary_op(
654 &self,
655 context: &mut Context,
656 out: &mut DynQuery,
657 value: &BinaryOp<&dyn Expression, &dyn Expression>,
658 ) {
659 let (prefix, infix, suffix, lhs_parenthesized, rhs_parenthesized) = match value.op {
660 BinaryOpType::Indexing => ("", "[", "]", false, true),
661 BinaryOpType::Cast => {
662 return self.write_expression_cast(context, out, value.lhs, value.rhs);
663 }
664 BinaryOpType::Multiplication => ("", " * ", "", false, false),
665 BinaryOpType::Division => ("", " / ", "", false, false),
666 BinaryOpType::Remainder => ("", " % ", "", false, false),
667 BinaryOpType::Addition => ("", " + ", "", false, false),
668 BinaryOpType::Subtraction => ("", " - ", "", false, false),
669 BinaryOpType::ShiftLeft => ("", " << ", "", false, false),
670 BinaryOpType::ShiftRight => ("", " >> ", "", false, false),
671 BinaryOpType::BitwiseAnd => ("", " & ", "", false, false),
672 BinaryOpType::BitwiseOr => ("", " | ", "", false, false),
673 BinaryOpType::In => ("", " IN ", "", false, false),
674 BinaryOpType::NotIn => ("", " NOT IN ", "", false, false),
675 BinaryOpType::Is => ("", " IS ", "", false, false),
676 BinaryOpType::IsNot => ("", " IS NOT ", "", false, false),
677 BinaryOpType::Like => ("", " LIKE ", "", false, false),
678 BinaryOpType::NotLike => ("", " NOT LIKE ", "", false, false),
679 BinaryOpType::Regexp => ("", " REGEXP ", "", false, false),
680 BinaryOpType::NotRegexp => ("", " NOT REGEXP ", "", false, false),
681 BinaryOpType::Glob => ("", " GLOB ", "", false, false),
682 BinaryOpType::NotGlob => ("", " NOT GLOB ", "", false, false),
683 BinaryOpType::Equal => ("", " = ", "", false, false),
684 BinaryOpType::NotEqual => ("", " != ", "", false, false),
685 BinaryOpType::Less => ("", " < ", "", false, false),
686 BinaryOpType::LessEqual => ("", " <= ", "", false, false),
687 BinaryOpType::Greater => ("", " > ", "", false, false),
688 BinaryOpType::GreaterEqual => ("", " >= ", "", false, false),
689 BinaryOpType::And => ("", " AND ", "", false, false),
690 BinaryOpType::Or => ("", " OR ", "", false, false),
691 BinaryOpType::Alias => {
692 if context.fragment == Fragment::SqlSelectOrderBy {
693 return value.lhs.write_query(self.as_dyn(), context, out);
694 } else {
695 ("", " AS ", "", false, false)
696 }
697 }
698 };
699 let precedence = self.expression_binary_op_precedence(&value.op);
700 out.push_str(prefix);
701 possibly_parenthesized!(
702 out,
703 !lhs_parenthesized && value.lhs.precedence(self.as_dyn()) < precedence,
704 value.lhs.write_query(self.as_dyn(), context, out)
705 );
706 out.push_str(infix);
707 let mut context = context.switch_fragment(if value.op == BinaryOpType::Alias {
708 Fragment::Aliasing
709 } else {
710 context.fragment
711 });
712 possibly_parenthesized!(
713 out,
714 !rhs_parenthesized && value.rhs.precedence(self.as_dyn()) <= precedence,
715 value
716 .rhs
717 .write_query(self.as_dyn(), &mut context.current, out)
718 );
719 out.push_str(suffix);
720 }
721
722 fn write_expression_cast(
724 &self,
725 context: &mut Context,
726 out: &mut DynQuery,
727 expr: &dyn Expression,
728 ty: &dyn Expression,
729 ) {
730 let mut context = context.switch_fragment(Fragment::Casting);
731 out.push_str("CAST(");
732 expr.write_query(self.as_dyn(), &mut context.current, out);
733 out.push_str(" AS ");
734 ty.write_query(self.as_dyn(), &mut context.current, out);
735 out.push(')');
736 }
737
738 fn write_expression_ordered(
740 &self,
741 context: &mut Context,
742 out: &mut DynQuery,
743 value: &Ordered<&dyn Expression>,
744 ) {
745 value.expression.write_query(self.as_dyn(), context, out);
746 if context.fragment == Fragment::SqlSelectOrderBy {
747 let _ = write!(
748 out,
749 " {}",
750 match value.order {
751 Order::ASC => "ASC",
752 Order::DESC => "DESC",
753 }
754 );
755 }
756 }
757
758 fn write_expression_call(
759 &self,
760 context: &mut Context,
761 out: &mut DynQuery,
762 function: &str,
763 args: &[&dyn Expression],
764 ) {
765 out.push_str(function);
766 out.push('(');
767 separated_by(
768 out,
769 args,
770 |out, expr| {
771 expr.write_query(self.as_dyn(), context, out);
772 },
773 ",",
774 );
775 out.push(')');
776 }
777
778 fn write_expression_list(
779 &self,
780 context: &mut Context,
781 out: &mut DynQuery,
782 value: &mut dyn Iterator<Item = &dyn Expression>,
783 ) {
784 out.push('[');
785 separated_by(
786 out,
787 value,
788 |out, v| {
789 v.write_query(self.as_dyn(), context, out);
790 },
791 ",",
792 );
793 out.push(']');
794 }
795
796 fn write_expression_tuple(
797 &self,
798 context: &mut Context,
799 out: &mut DynQuery,
800 value: &mut dyn Iterator<Item = &dyn Expression>,
801 ) {
802 out.push('(');
803 separated_by(
804 out,
805 value,
806 |out, v| {
807 v.write_query(self.as_dyn(), context, out);
808 },
809 ",",
810 );
811 out.push(')');
812 }
813
814 fn write_join_type(&self, _context: &mut Context, out: &mut DynQuery, join_type: &JoinType) {
816 out.push_str(match &join_type {
817 JoinType::Default => "JOIN",
818 JoinType::Inner => "INNER JOIN",
819 JoinType::Outer => "OUTER JOIN",
820 JoinType::Left => "LEFT JOIN",
821 JoinType::Right => "RIGHT JOIN",
822 JoinType::Cross => "CROSS JOIN",
823 JoinType::Natural => "NATURAL JOIN",
824 });
825 }
826
827 fn write_join(
829 &self,
830 context: &mut Context,
831 out: &mut DynQuery,
832 join: &Join<&dyn Dataset, &dyn Dataset, &dyn Expression>,
833 ) {
834 let mut context = context.switch_fragment(Fragment::SqlJoin);
835 context.current.qualify_columns = true;
836 join.lhs
837 .write_query(self.as_dyn(), &mut context.current, out);
838 out.push(' ');
839 self.write_join_type(&mut context.current, out, &join.join);
840 out.push(' ');
841 join.rhs
842 .write_query(self.as_dyn(), &mut context.current, out);
843 if let Some(on) = &join.on {
844 out.push_str(" ON ");
845 on.write_query(self.as_dyn(), &mut context.current, out);
846 }
847 }
848
849 fn write_transaction_begin(&self, out: &mut DynQuery) {
851 out.push_str("BEGIN;");
852 }
853
854 fn write_transaction_commit(&self, out: &mut DynQuery) {
856 out.push_str("COMMIT;");
857 }
858
859 fn write_transaction_rollback(&self, out: &mut DynQuery) {
861 out.push_str("ROLLBACK;");
862 }
863
864 fn write_create_schema<E>(&self, out: &mut DynQuery, if_not_exists: bool)
866 where
867 Self: Sized,
868 E: Entity,
869 {
870 let table = E::table();
871 out.buffer().reserve(32 + table.schema.len());
872 if !out.is_empty() {
873 out.push('\n');
874 }
875 out.push_str("CREATE SCHEMA ");
876 let mut context = Context::new(Fragment::SqlCreateSchema, E::qualified_columns());
877 if if_not_exists {
878 out.push_str("IF NOT EXISTS ");
879 }
880 self.write_identifier(&mut context, out, &table.schema, true);
881 out.push(';');
882 }
883
884 fn write_drop_schema<E>(&self, out: &mut DynQuery, if_exists: bool)
886 where
887 Self: Sized,
888 E: Entity,
889 {
890 let mut context = Context::new(Fragment::SqlDropSchema, E::qualified_columns());
891 let table = E::table();
892 out.buffer().reserve(32 + table.schema.len());
893 if !out.is_empty() {
894 out.push('\n');
895 }
896 out.push_str("DROP SCHEMA ");
897 if if_exists {
898 out.push_str("IF EXISTS ");
899 }
900 self.write_identifier(&mut context, out, &table.schema, true);
901 out.push(';');
902 }
903
904 fn write_create_table<E>(&self, out: &mut DynQuery, if_not_exists: bool)
906 where
907 Self: Sized,
908 E: Entity,
909 {
910 let mut context = Context::new(Fragment::SqlCreateTable, E::qualified_columns());
911 let table = E::table();
912 let estimated = 128 + E::columns().len() * 64 + E::primary_key_def().len() * 24;
913 out.buffer().reserve(estimated);
914 if !out.is_empty() {
915 out.push('\n');
916 }
917 out.push_str("CREATE TABLE ");
918 if if_not_exists {
919 out.push_str("IF NOT EXISTS ");
920 }
921 self.write_table_ref(&mut context, out, table);
922 out.push_str(" (\n");
923 separated_by(
924 out,
925 E::columns(),
926 |out, col| {
927 self.write_create_table_column_fragment(&mut context, out, col);
928 },
929 ",\n",
930 );
931 let pk = E::primary_key_def();
932 if pk.len() > 1 {
933 self.write_create_table_primary_key_fragment(&mut context, out, pk.iter().map(|v| *v));
934 }
935 for unique in E::unique_defs() {
936 if unique.len() > 1 {
937 out.push_str(",\nUNIQUE (");
938 separated_by(
939 out,
940 unique,
941 |out, col| {
942 self.write_identifier(
943 &mut context
944 .switch_fragment(Fragment::SqlCreateTableUnique)
945 .current,
946 out,
947 col.name(),
948 true,
949 );
950 },
951 ", ",
952 );
953 out.push(')');
954 }
955 }
956 let foreign_keys = E::columns().iter().filter(|c| c.references.is_some());
957 separated_by(
958 out,
959 foreign_keys,
960 |out, column| {
961 let references = column.references.as_ref().unwrap();
962 out.push_str(",\nFOREIGN KEY (");
963 self.write_identifier(&mut context, out, &column.name(), true);
964 out.push_str(") REFERENCES ");
965 self.write_table_ref(&mut context, out, &references.table());
966 out.push('(');
967 self.write_column_ref(&mut context, out, references);
968 out.push(')');
969 if let Some(on_delete) = &column.on_delete {
970 out.push_str(" ON DELETE ");
971 self.write_create_table_references_action(&mut context, out, on_delete);
972 }
973 if let Some(on_update) = &column.on_update {
974 out.push_str(" ON UPDATE ");
975 self.write_create_table_references_action(&mut context, out, on_update);
976 }
977 },
978 "",
979 );
980 out.push_str(");");
981 self.write_column_comments_statements::<E>(&mut context, out);
982 }
983
984 fn write_create_table_column_fragment(
986 &self,
987 context: &mut Context,
988 out: &mut DynQuery,
989 column: &ColumnDef,
990 ) where
991 Self: Sized,
992 {
993 self.write_identifier(context, out, &column.name(), true);
994 out.push(' ');
995 let len = out.len();
996 self.write_column_overridden_type(context, out, column, &column.column_type);
997 let didnt_write_type = out.len() == len;
998 if didnt_write_type {
999 SqlWriter::write_column_type(self, context, out, &column.value);
1000 }
1001 if !column.nullable && column.primary_key == PrimaryKeyType::None {
1002 out.push_str(" NOT NULL");
1003 }
1004 if column.default.is_set() {
1005 out.push_str(" DEFAULT ");
1006 column.default.write_query(self.as_dyn(), context, out);
1007 }
1008 if column.primary_key == PrimaryKeyType::PrimaryKey {
1009 out.push_str(" PRIMARY KEY");
1011 }
1012 if column.unique && column.primary_key != PrimaryKeyType::PrimaryKey {
1013 out.push_str(" UNIQUE");
1014 }
1015 if !column.comment.is_empty() {
1016 self.write_column_comment_inline(context, out, column);
1017 }
1018 }
1019
1020 fn write_create_table_primary_key_fragment<'a, It>(
1022 &self,
1023 context: &mut Context,
1024 out: &mut DynQuery,
1025 primary_key: It,
1026 ) where
1027 Self: Sized,
1028 It: IntoIterator<Item = &'a ColumnDef>,
1029 It::IntoIter: Clone,
1030 {
1031 out.push_str(",\nPRIMARY KEY (");
1032 separated_by(
1033 out,
1034 primary_key,
1035 |out, col| {
1036 self.write_identifier(
1037 &mut context
1038 .switch_fragment(Fragment::SqlCreateTablePrimaryKey)
1039 .current,
1040 out,
1041 col.name(),
1042 true,
1043 );
1044 },
1045 ", ",
1046 );
1047 out.push(')');
1048 }
1049
1050 fn write_create_table_references_action(
1052 &self,
1053 _context: &mut Context,
1054 out: &mut DynQuery,
1055 action: &Action,
1056 ) {
1057 out.push_str(match action {
1058 Action::NoAction => "NO ACTION",
1059 Action::Restrict => "RESTRICT",
1060 Action::Cascade => "CASCADE",
1061 Action::SetNull => "SET NULL",
1062 Action::SetDefault => "SET DEFAULT",
1063 });
1064 }
1065
1066 fn write_column_comment_inline(
1067 &self,
1068 _context: &mut Context,
1069 _out: &mut DynQuery,
1070 _column: &ColumnDef,
1071 ) where
1072 Self: Sized,
1073 {
1074 }
1075
1076 fn write_column_comments_statements<E>(&self, context: &mut Context, out: &mut DynQuery)
1078 where
1079 Self: Sized,
1080 E: Entity,
1081 {
1082 let mut context = context.switch_fragment(Fragment::SqlCommentOnColumn);
1083 context.current.qualify_columns = true;
1084 for c in E::columns().iter().filter(|c| !c.comment.is_empty()) {
1085 out.push_str("\nCOMMENT ON COLUMN ");
1086 self.write_column_ref(&mut context.current, out, c.into());
1087 out.push_str(" IS ");
1088 self.write_value_string(&mut context.current, out, c.comment);
1089 out.push(';');
1090 }
1091 }
1092
1093 fn write_drop_table<E>(&self, out: &mut DynQuery, if_exists: bool)
1095 where
1096 Self: Sized,
1097 E: Entity,
1098 {
1099 let table = E::table();
1100 out.buffer()
1101 .reserve(24 + table.schema.len() + table.name.len());
1102 if !out.is_empty() {
1103 out.push('\n');
1104 }
1105 out.push_str("DROP TABLE ");
1106 let mut context = Context::new(Fragment::SqlDropTable, E::qualified_columns());
1107 if if_exists {
1108 out.push_str("IF EXISTS ");
1109 }
1110 self.write_table_ref(&mut context, out, table);
1111 out.push(';');
1112 }
1113
1114 fn write_select<'a, Data>(&self, out: &mut DynQuery, query: &impl SelectQuery<Data>)
1116 where
1117 Self: Sized,
1118 Data: Dataset + 'a,
1119 {
1120 let columns = query.get_select();
1121 let Some(from) = query.get_from() else {
1122 log::error!("The query does not have the FROM clause");
1123 return;
1124 };
1125 let limit = query.get_limit();
1126 let cols = columns.clone().into_iter().count();
1127 out.buffer().reserve(128 + cols * 32);
1128 if !out.is_empty() {
1129 out.push('\n');
1130 }
1131 out.push_str("SELECT ");
1132 let mut context = Context::new(Fragment::SqlSelect, Data::qualified_columns());
1133 separated_by(
1134 out,
1135 columns.clone(),
1136 |out, col| {
1137 col.write_query(self, &mut context, out);
1138 },
1139 ", ",
1140 );
1141 out.push_str("\nFROM ");
1142 from.write_query(
1143 self,
1144 &mut context.switch_fragment(Fragment::SqlSelectFrom).current,
1145 out,
1146 );
1147 if let Some(condition) = query.get_where()
1148 && !condition.accept_visitor(&mut IsTrue, self, &mut context, out)
1149 {
1150 out.push_str("\nWHERE ");
1151 condition.write_query(
1152 self,
1153 &mut context.switch_fragment(Fragment::SqlSelectWhere).current,
1154 out,
1155 );
1156 }
1157 let mut group_by = query.get_group_by().peekable();
1158 if group_by.peek().is_some() {
1159 out.push_str("\nGROUP BY ");
1160 let mut context = context.switch_fragment(Fragment::SqlSelectGroupBy);
1161 separated_by(
1162 out,
1163 group_by,
1164 |out, col| {
1165 col.write_query(self, &mut context.current, out);
1166 },
1167 ", ",
1168 );
1169 }
1170 if let Some(having) = query.get_having() {
1171 out.push_str("\nHAVING ");
1172 having.write_query(
1173 self,
1174 &mut context.switch_fragment(Fragment::SqlSelectWhere).current,
1175 out,
1176 );
1177 }
1178 let mut order_by = query.get_order_by().peekable();
1179 if order_by.peek().is_some() {
1180 out.push_str("\nORDER BY ");
1181 let mut context = context.switch_fragment(Fragment::SqlSelectOrderBy);
1182 separated_by(
1183 out,
1184 order_by,
1185 |out, col| {
1186 col.write_query(self, &mut 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 let mut rows = entities.into_iter().map(Entity::row_filtered).peekable();
1209 let Some(mut row) = rows.next() else {
1210 return;
1211 };
1212 let single = rows.peek().is_none();
1213 let cols = E::columns().len();
1214 out.buffer().reserve(128 + cols * 32);
1215 if !out.is_empty() {
1216 out.push('\n');
1217 }
1218 out.push_str("INSERT INTO ");
1219 let mut context = Context::new(Fragment::SqlInsertInto, E::qualified_columns());
1220 self.write_table_ref(&mut context, out, table);
1221 out.push_str(" (");
1222 let columns = E::columns().iter();
1223 if single {
1224 separated_by(
1226 out,
1227 row.iter(),
1228 |out, (name, ..)| {
1229 self.write_identifier(&mut context, out, name, true);
1230 },
1231 ", ",
1232 );
1233 } else {
1234 separated_by(
1235 out,
1236 columns.clone(),
1237 |out, col| {
1238 self.write_identifier(&mut context, out, col.name(), true);
1239 },
1240 ", ",
1241 );
1242 };
1243 out.push_str(") VALUES\n");
1244 let mut context = context.switch_fragment(Fragment::SqlInsertIntoValues);
1245 let mut first_row = None;
1246 let mut separate = false;
1247 loop {
1248 if separate {
1249 out.push_str(",\n");
1250 }
1251 out.push('(');
1252 let mut fields = row.iter();
1253 let mut field = fields.next();
1254 separated_by(
1255 out,
1256 E::columns(),
1257 |out, col| {
1258 if Some(col.name()) == field.map(|v| v.0) {
1259 self.write_value(
1260 &mut context.current,
1261 out,
1262 field
1263 .map(|v| &v.1)
1264 .expect(&format!("Column {} does not have a value", col.name())),
1265 );
1266 field = fields.next();
1267 } else if !single {
1268 out.push_str("DEFAULT");
1269 }
1270 },
1271 ", ",
1272 );
1273 out.push(')');
1274 separate = true;
1275 if first_row.is_none() {
1276 first_row = row.into();
1277 }
1278 if let Some(next) = rows.next() {
1279 row = next;
1280 } else {
1281 break;
1282 };
1283 }
1284 let first_row = first_row
1285 .expect("Should have at least one row")
1286 .into_iter()
1287 .map(|(v, _)| v);
1288 if update {
1289 self.write_insert_update_fragment::<E>(
1290 &mut context.current,
1291 out,
1292 if single {
1293 EitherIterator::Left(
1294 columns.filter(|c| first_row.clone().find(|n| *n == c.name()).is_some()),
1296 )
1297 } else {
1298 EitherIterator::Right(columns)
1299 },
1300 );
1301 }
1302 out.push(';');
1303 }
1304
1305 fn write_insert_update_fragment<'a, E>(
1307 &self,
1308 context: &mut Context,
1309 out: &mut DynQuery,
1310 columns: impl Iterator<Item = &'a ColumnDef> + Clone,
1311 ) where
1312 Self: Sized,
1313 E: Entity,
1314 {
1315 let pk = E::primary_key_def();
1316 if pk.len() == 0 {
1317 return;
1318 }
1319 out.push_str("\nON CONFLICT");
1320 context.fragment = Fragment::SqlInsertIntoOnConflict;
1321 if pk.len() > 0 {
1322 out.push_str(" (");
1323 separated_by(
1324 out,
1325 pk,
1326 |out, col| {
1327 self.write_identifier(context, out, col.name(), true);
1328 },
1329 ", ",
1330 );
1331 out.push(')');
1332 }
1333 let mut update_cols = columns
1334 .filter(|c| c.primary_key == PrimaryKeyType::None)
1335 .peekable();
1336 if update_cols.peek().is_some() {
1337 out.push_str(" DO UPDATE SET\n");
1338 separated_by(
1339 out,
1340 update_cols,
1341 |out, col| {
1342 self.write_identifier(context, out, col.name(), true);
1343 out.push_str(" = EXCLUDED.");
1344 self.write_identifier(context, out, col.name(), true);
1345 },
1346 ",\n",
1347 );
1348 } else {
1349 out.push_str(" DO NOTHING");
1350 }
1351 }
1352
1353 fn write_delete<E>(&self, out: &mut DynQuery, condition: impl Expression)
1355 where
1356 Self: Sized,
1357 E: Entity,
1358 {
1359 let table = E::table();
1360 out.buffer().reserve(128);
1361 if !out.is_empty() {
1362 out.push('\n');
1363 }
1364 out.push_str("DELETE FROM ");
1365 let mut context = Context::new(Fragment::SqlDeleteFrom, E::qualified_columns());
1366 self.write_table_ref(&mut context, out, table);
1367 out.push_str("\nWHERE ");
1368 condition.write_query(
1369 self,
1370 &mut context
1371 .switch_fragment(Fragment::SqlDeleteFromWhere)
1372 .current,
1373 out,
1374 );
1375 out.push(';');
1376 }
1377}
1378
1379pub struct GenericSqlWriter;
1381impl GenericSqlWriter {
1382 pub fn new() -> Self {
1384 Self {}
1385 }
1386}
1387impl SqlWriter for GenericSqlWriter {
1388 fn as_dyn(&self) -> &dyn SqlWriter {
1389 self
1390 }
1391}