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