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