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