1use crate::{
2 Action, BinaryOp, BinaryOpType, ColumnDef, ColumnRef, DataSet, EitherIterator, Entity,
3 Expression, Fragment, Interval, Join, JoinType, Operand, Order, Ordered, PrimaryKeyType,
4 TableRef, UnaryOp, UnaryOpType, Value, possibly_parenthesized, separated_by, writer::Context,
5};
6use futures::future::Either;
7use std::{collections::HashMap, fmt::Write};
8use time::{Date, Time};
9
10macro_rules! write_integer {
11 ($buff:ident, $value:expr) => {{
12 let mut buffer = itoa::Buffer::new();
13 $buff.push_str(buffer.format($value));
14 }};
15}
16macro_rules! write_float {
17 ($this:ident, $context:ident,$buff:ident, $value:expr) => {{
18 if $value.is_infinite() {
19 $this.write_value_infinity($context, $buff, $value.is_sign_negative());
20 } else {
21 let mut buffer = ryu::Buffer::new();
22 $buff.push_str(buffer.format($value));
23 }
24 }};
25}
26
27pub trait SqlWriter {
28 fn as_dyn(&self) -> &dyn SqlWriter;
29
30 fn alias_declaration(&self, context: &mut Context) -> bool {
31 match context.fragment {
32 Fragment::SqlSelectFrom | Fragment::SqlJoin => true,
33 _ => false,
34 }
35 }
36
37 fn write_escaped(
38 &self,
39 _context: &mut Context,
40 buff: &mut String,
41 value: &str,
42 search: char,
43 replace: &str,
44 ) {
45 let mut position = 0;
46 for (i, c) in value.char_indices() {
47 if c == search {
48 buff.push_str(&value[position..i]);
49 buff.push_str(replace);
50 position = i + 1;
51 }
52 }
53 buff.push_str(&value[position..]);
54 }
55
56 fn write_identifier_quoted(&self, context: &mut Context, buff: &mut String, value: &str) {
57 buff.push('"');
58 self.write_escaped(context, buff, value, '"', r#""""#);
59 buff.push('"');
60 }
61
62 fn write_table_ref(&self, context: &mut Context, buff: &mut String, value: &TableRef) {
63 if self.alias_declaration(context) || value.alias.is_empty() {
64 if !value.schema.is_empty() {
65 self.write_identifier_quoted(context, buff, &value.schema);
66 buff.push('.');
67 }
68 self.write_identifier_quoted(context, buff, &value.name);
69 }
70 if !value.alias.is_empty() {
71 let _ = write!(buff, " {}", value.alias);
72 }
73 }
74
75 fn write_column_ref(&self, context: &mut Context, buff: &mut String, value: &ColumnRef) {
76 if context.qualify_columns && !value.table.is_empty() {
77 if !value.schema.is_empty() {
78 self.write_identifier_quoted(context, buff, &value.schema);
79 buff.push('.');
80 }
81 self.write_identifier_quoted(context, buff, &value.table);
82 buff.push('.');
83 }
84 self.write_identifier_quoted(context, buff, &value.name);
85 }
86
87 fn write_column_type(&self, context: &mut Context, buff: &mut String, value: &Value) {
88 match value {
89 Value::Boolean(..) => buff.push_str("BOOLEAN"),
90 Value::Int8(..) => buff.push_str("TINYINT"),
91 Value::Int16(..) => buff.push_str("SMALLINT"),
92 Value::Int32(..) => buff.push_str("INTEGER"),
93 Value::Int64(..) => buff.push_str("BIGINT"),
94 Value::Int128(..) => buff.push_str("HUGEINT"),
95 Value::UInt8(..) => buff.push_str("UTINYINT"),
96 Value::UInt16(..) => buff.push_str("USMALLINT"),
97 Value::UInt32(..) => buff.push_str("UINTEGER"),
98 Value::UInt64(..) => buff.push_str("UBIGINT"),
99 Value::UInt128(..) => buff.push_str("UHUGEINT"),
100 Value::Float32(..) => buff.push_str("FLOAT"),
101 Value::Float64(..) => buff.push_str("DOUBLE"),
102 Value::Decimal(.., precision, scale) => {
103 buff.push_str("DECIMAL");
104 if (precision, scale) != (&0, &0) {
105 let _ = write!(buff, "({},{})", precision, scale);
106 }
107 }
108 Value::Char(..) => buff.push_str("CHAR(1)"),
109 Value::Varchar(..) => buff.push_str("VARCHAR"),
110 Value::Blob(..) => buff.push_str("BLOB"),
111 Value::Date(..) => buff.push_str("DATE"),
112 Value::Time(..) => buff.push_str("TIME"),
113 Value::Timestamp(..) => buff.push_str("TIMESTAMP"),
114 Value::TimestampWithTimezone(..) => buff.push_str("TIMESTAMP WITH TIME ZONE"),
115 Value::Interval(..) => buff.push_str("INTERVAL"),
116 Value::Uuid(..) => buff.push_str("UUID"),
117 Value::Array(.., inner, size) => {
118 self.write_column_type(context, buff, inner);
119 let _ = write!(buff, "[{}]", size);
120 }
121 Value::List(.., inner) => {
122 self.write_column_type(context, buff, inner);
123 buff.push_str("[]");
124 }
125 Value::Map(.., key, value) => {
126 buff.push_str("MAP(");
127 self.write_column_type(context, buff, key);
128 buff.push(',');
129 self.write_column_type(context, buff, value);
130 buff.push(')');
131 }
132 _ => log::error!(
133 "Unexpected tank::Value, variant {:?} is not supported",
134 value
135 ),
136 };
137 }
138
139 fn write_value(&self, context: &mut Context, buff: &mut String, value: &Value) {
140 match value {
141 v if v.is_null() => self.write_value_none(context, buff),
142 Value::Boolean(Some(v), ..) => self.write_value_bool(context, buff, *v),
143 Value::Int8(Some(v), ..) => write_integer!(buff, *v),
144 Value::Int16(Some(v), ..) => write_integer!(buff, *v),
145 Value::Int32(Some(v), ..) => write_integer!(buff, *v),
146 Value::Int64(Some(v), ..) => write_integer!(buff, *v),
147 Value::Int128(Some(v), ..) => write_integer!(buff, *v),
148 Value::UInt8(Some(v), ..) => write_integer!(buff, *v),
149 Value::UInt16(Some(v), ..) => write_integer!(buff, *v),
150 Value::UInt32(Some(v), ..) => write_integer!(buff, *v),
151 Value::UInt64(Some(v), ..) => write_integer!(buff, *v),
152 Value::UInt128(Some(v), ..) => write_integer!(buff, *v),
153 Value::Float32(Some(v), ..) => write_float!(self, context, buff, *v),
154 Value::Float64(Some(v), ..) => write_float!(self, context, buff, *v),
155 Value::Decimal(Some(v), ..) => drop(write!(buff, "{}", v)),
156 Value::Char(Some(v), ..) => {
157 buff.push('\'');
158 buff.push(*v);
159 buff.push('\'');
160 }
161 Value::Varchar(Some(v), ..) => self.write_value_string(context, buff, v),
162 Value::Blob(Some(v), ..) => self.write_value_blob(context, buff, v.as_ref()),
163 Value::Date(Some(v), ..) => {
164 buff.push('\'');
165 self.write_value_date(context, buff, v);
166 buff.push('\'');
167 }
168 Value::Time(Some(v), ..) => {
169 buff.push('\'');
170 self.write_value_time(context, buff, v);
171 buff.push('\'');
172 }
173 Value::Timestamp(Some(v), ..) => {
174 buff.push('\'');
175 self.write_value_date(context, buff, &v.date());
176 buff.push('T');
177 self.write_value_time(context, buff, &v.time());
178 buff.push('\'');
179 }
180 Value::TimestampWithTimezone(Some(v), ..) => {
181 buff.push('\'');
182 self.write_value_date(context, buff, &v.date());
183 buff.push('T');
184 self.write_value_time(context, buff, &v.time());
185 let _ = write!(
186 buff,
187 "{:+02}:{:02}",
188 v.offset().whole_hours(),
189 v.offset().whole_minutes()
190 );
191 buff.push('\'');
192 }
193 Value::Interval(Some(v), ..) => self.write_value_interval(context, buff, v),
194 Value::Uuid(Some(v), ..) => drop(write!(buff, "'{}'", v)),
195 Value::Array(Some(..), ..) | Value::List(Some(..), ..) => match value {
196 Value::Array(Some(v), ..) => {
197 self.write_value_list(context, buff, Either::Left(v), value)
198 }
199 Value::List(Some(v), ..) => {
200 self.write_value_list(context, buff, Either::Right(v), value)
201 }
202 _ => unreachable!(),
203 },
204 Value::Map(Some(v), ..) => self.write_value_map(context, buff, v),
205 Value::Struct(Some(_v), ..) => {
206 todo!()
207 }
208 _ => {
209 log::error!("Cannot write {:?}", value);
210 }
211 };
212 }
213
214 fn write_value_none(&self, _context: &mut Context, buff: &mut String) {
215 buff.push_str("NULL");
216 }
217
218 fn write_value_bool(&self, _context: &mut Context, buff: &mut String, value: bool) {
219 buff.push_str(["false", "true"][value as usize]);
220 }
221
222 fn write_value_infinity(&self, context: &mut Context, buff: &mut String, negative: bool) {
223 let mut buffer = ryu::Buffer::new();
224 self.write_expression_binary_op(
225 context,
226 buff,
227 &BinaryOp {
228 op: BinaryOpType::Cast,
229 lhs: &Operand::LitStr(buffer.format(if negative {
230 f64::NEG_INFINITY
231 } else {
232 f64::INFINITY
233 })),
234 rhs: &Operand::Type(Value::Float64(None)),
235 },
236 );
237 }
238
239 fn write_value_string(&self, _context: &mut Context, buff: &mut String, value: &str) {
240 buff.push('\'');
241 let mut position = 0;
242 for (i, c) in value.char_indices() {
243 if c == '\'' {
244 buff.push_str(&value[position..i]);
245 buff.push_str("''");
246 position = i + 1;
247 } else if c == '\n' {
248 buff.push_str(&value[position..i]);
249 buff.push_str("\\n");
250 position = i + 1;
251 }
252 }
253 buff.push_str(&value[position..]);
254 buff.push('\'');
255 }
256
257 fn write_value_blob(&self, _context: &mut Context, buff: &mut String, value: &[u8]) {
258 buff.push('\'');
259 for b in value {
260 let _ = write!(buff, "\\x{:X}", b);
261 }
262 buff.push('\'');
263 }
264
265 fn write_value_date(&self, _context: &mut Context, buff: &mut String, value: &Date) {
266 let _ = write!(
267 buff,
268 "{:04}-{:02}-{:02}",
269 value.year(),
270 value.month() as u8,
271 value.day()
272 );
273 }
274
275 fn write_value_time(&self, _context: &mut Context, buff: &mut String, value: &Time) {
276 let mut subsecond = value.nanosecond();
277 let mut width = 9;
278 while width > 1 && subsecond % 10 == 0 {
279 subsecond /= 10;
280 width -= 1;
281 }
282 let _ = write!(
283 buff,
284 "{:02}:{:02}:{:02}.{:0width$}",
285 value.hour(),
286 value.minute(),
287 value.second(),
288 subsecond
289 );
290 }
291
292 fn value_interval_units(&self) -> &[(&str, i128)] {
293 static UNITS: &[(&str, i128)] = &[
294 ("DAY", Interval::NANOS_IN_DAY),
295 ("HOUR", Interval::NANOS_IN_SEC * 3600),
296 ("MINUTE", Interval::NANOS_IN_SEC * 60),
297 ("SECOND", Interval::NANOS_IN_SEC),
298 ("MICROSECOND", 1_000),
299 ("NANOSECOND", 1),
300 ];
301 UNITS
302 }
303
304 fn write_value_interval(&self, _context: &mut Context, buff: &mut String, value: &Interval) {
305 buff.push_str("INTERVAL ");
306 if value.is_zero() {
307 buff.push_str("0 SECONDS");
308 return;
309 }
310 macro_rules! write_unit {
311 ($buff:ident, $val:expr, $unit:expr) => {
312 let _ = write!(
313 $buff,
314 "{} {}{}",
315 $val,
316 $unit,
317 if $val != 1 { "S" } else { "" }
318 );
319 };
320 }
321 let months = value.months;
322 let nanos = value.nanos + value.days as i128 * Interval::NANOS_IN_DAY;
323 let multiple_units = nanos != 0 && value.months != 0;
324 if multiple_units {
325 buff.push('\'');
326 }
327 if months != 0 {
328 if months % 12 == 0 {
329 write_unit!(buff, months / 12, "YEAR");
330 } else {
331 write_unit!(buff, months, "MONTH");
332 }
333 }
334 for &(name, factor) in self.value_interval_units() {
335 if nanos % factor == 0 {
336 let value = nanos / factor;
337 if value != 0 {
338 if months != 0 {
339 buff.push(' ');
340 }
341 write_unit!(buff, value, name);
342 break;
343 }
344 }
345 }
346 if multiple_units {
347 buff.push('\'');
348 }
349 }
350
351 fn write_value_list<'a>(
352 &self,
353 context: &mut Context,
354 buff: &mut String,
355 value: Either<&Box<[Value]>, &Vec<Value>>,
356 _ty: &Value,
357 ) {
358 buff.push('[');
359 separated_by(
360 buff,
361 match value {
362 Either::Left(v) => v.iter(),
363 Either::Right(v) => v.iter(),
364 },
365 |buff, v| {
366 self.write_value(context, buff, v);
367 },
368 ",",
369 );
370 buff.push(']');
371 }
372
373 fn write_value_map(
374 &self,
375 context: &mut Context,
376 buff: &mut String,
377 value: &HashMap<Value, Value>,
378 ) {
379 buff.push('{');
380 separated_by(
381 buff,
382 value,
383 |buff, (k, v)| {
384 self.write_value(context, buff, k);
385 buff.push(':');
386 self.write_value(context, buff, v);
387 },
388 ",",
389 );
390 buff.push('}');
391 }
392
393 fn expression_unary_op_precedence<'a>(&self, value: &UnaryOpType) -> i32 {
394 match value {
395 UnaryOpType::Negative => 1250,
396 UnaryOpType::Not => 250,
397 }
398 }
399
400 fn expression_binary_op_precedence<'a>(&self, value: &BinaryOpType) -> i32 {
401 match value {
402 BinaryOpType::Or => 100,
403 BinaryOpType::And => 200,
404 BinaryOpType::Equal => 300,
405 BinaryOpType::NotEqual => 300,
406 BinaryOpType::Less => 300,
407 BinaryOpType::Greater => 300,
408 BinaryOpType::LessEqual => 300,
409 BinaryOpType::GreaterEqual => 300,
410 BinaryOpType::Is => 400,
411 BinaryOpType::IsNot => 400,
412 BinaryOpType::Like => 400,
413 BinaryOpType::NotLike => 400,
414 BinaryOpType::Regexp => 400,
415 BinaryOpType::NotRegexp => 400,
416 BinaryOpType::Glob => 400,
417 BinaryOpType::NotGlob => 400,
418 BinaryOpType::BitwiseOr => 500,
419 BinaryOpType::BitwiseAnd => 600,
420 BinaryOpType::ShiftLeft => 700,
421 BinaryOpType::ShiftRight => 700,
422 BinaryOpType::Subtraction => 800,
423 BinaryOpType::Addition => 800,
424 BinaryOpType::Multiplication => 900,
425 BinaryOpType::Division => 900,
426 BinaryOpType::Remainder => 900,
427 BinaryOpType::Indexing => 1000,
428 BinaryOpType::Cast => 1100,
429 BinaryOpType::Alias => 1200,
430 }
431 }
432
433 fn write_expression_operand(&self, context: &mut Context, buff: &mut String, value: &Operand) {
434 match value {
435 Operand::LitBool(v) => self.write_value_bool(context, buff, *v),
436 Operand::LitFloat(v) => write_float!(self, context, buff, *v),
437 Operand::LitIdent(v) => drop(buff.push_str(v)),
438 Operand::LitField(v) => separated_by(buff, *v, |buff, v| buff.push_str(v), "."),
439 Operand::LitInt(v) => write_integer!(buff, *v),
440 Operand::LitStr(v) => self.write_value_string(context, buff, v),
441 Operand::LitArray(v) => {
442 buff.push('[');
443 separated_by(
444 buff,
445 *v,
446 |buff, v| {
447 v.write_query(self.as_dyn(), context, buff);
448 },
449 ", ",
450 );
451 buff.push(']');
452 }
453 Operand::Null => drop(buff.push_str("NULL")),
454 Operand::Type(v) => self.write_column_type(context, buff, v),
455 Operand::Variable(v) => self.write_value(context, buff, v),
456 Operand::Call(f, args) => {
457 buff.push_str(f);
458 buff.push('(');
459 separated_by(
460 buff,
461 *args,
462 |buff, v| {
463 v.write_query(self.as_dyn(), context, buff);
464 },
465 ",",
466 );
467 buff.push(')');
468 }
469 Operand::Asterisk => drop(buff.push('*')),
470 Operand::QuestionMark => self.write_expression_operand_question_mark(context, buff),
471 };
472 }
473
474 fn write_expression_operand_question_mark(&self, _context: &mut Context, buff: &mut String) {
475 buff.push('?');
476 }
477
478 fn write_expression_unary_op(
479 &self,
480 context: &mut Context,
481 buff: &mut String,
482 value: &UnaryOp<&dyn Expression>,
483 ) {
484 match value.op {
485 UnaryOpType::Negative => buff.push('-'),
486 UnaryOpType::Not => buff.push_str("NOT "),
487 };
488 possibly_parenthesized!(
489 buff,
490 value.arg.precedence(self.as_dyn()) <= self.expression_unary_op_precedence(&value.op),
491 value.arg.write_query(self.as_dyn(), context, buff)
492 );
493 }
494
495 fn write_expression_binary_op(
496 &self,
497 context: &mut Context,
498 buff: &mut String,
499 value: &BinaryOp<&dyn Expression, &dyn Expression>,
500 ) {
501 let (prefix, infix, suffix, lhs_parenthesized, rhs_parenthesized) = match value.op {
502 BinaryOpType::Indexing => ("", "[", "]", false, true),
503 BinaryOpType::Cast => ("CAST(", " AS ", ")", true, true),
504 BinaryOpType::Multiplication => ("", " * ", "", false, false),
505 BinaryOpType::Division => ("", " / ", "", false, false),
506 BinaryOpType::Remainder => ("", " % ", "", false, false),
507 BinaryOpType::Addition => ("", " + ", "", false, false),
508 BinaryOpType::Subtraction => ("", " - ", "", false, false),
509 BinaryOpType::ShiftLeft => ("", " << ", "", false, false),
510 BinaryOpType::ShiftRight => ("", " >> ", "", false, false),
511 BinaryOpType::BitwiseAnd => ("", " & ", "", false, false),
512 BinaryOpType::BitwiseOr => ("", " | ", "", false, false),
513 BinaryOpType::Is => ("", " Is ", "", false, false),
514 BinaryOpType::IsNot => ("", " IS NOT ", "", false, false),
515 BinaryOpType::Like => ("", " LIKE ", "", false, false),
516 BinaryOpType::NotLike => ("", " NOT LIKE ", "", false, false),
517 BinaryOpType::Regexp => ("", " REGEXP ", "", false, false),
518 BinaryOpType::NotRegexp => ("", " NOT REGEXP ", "", false, false),
519 BinaryOpType::Glob => ("", " GLOB ", "", false, false),
520 BinaryOpType::NotGlob => ("", " NOT GLOB ", "", false, false),
521 BinaryOpType::Equal => ("", " = ", "", false, false),
522 BinaryOpType::NotEqual => ("", " != ", "", false, false),
523 BinaryOpType::Less => ("", " < ", "", false, false),
524 BinaryOpType::LessEqual => ("", " <= ", "", false, false),
525 BinaryOpType::Greater => ("", " > ", "", false, false),
526 BinaryOpType::GreaterEqual => ("", " >= ", "", false, false),
527 BinaryOpType::And => ("", " AND ", "", false, false),
528 BinaryOpType::Or => ("", " OR ", "", false, false),
529 BinaryOpType::Alias => ("", " AS ", "", false, false),
530 };
531 let precedence = self.expression_binary_op_precedence(&value.op);
532 buff.push_str(prefix);
533 possibly_parenthesized!(
534 buff,
535 !lhs_parenthesized && value.lhs.precedence(self.as_dyn()) < precedence,
536 value.lhs.write_query(self.as_dyn(), context, buff)
537 );
538 buff.push_str(infix);
539 possibly_parenthesized!(
540 buff,
541 !rhs_parenthesized && value.rhs.precedence(self.as_dyn()) <= precedence,
542 value.rhs.write_query(self.as_dyn(), context, buff)
543 );
544 buff.push_str(suffix);
545 }
546
547 fn write_expression_ordered(
548 &self,
549 context: &mut Context,
550 buff: &mut String,
551 value: &Ordered<&dyn Expression>,
552 ) {
553 value.expression.write_query(self.as_dyn(), context, buff);
554 if context.fragment == Fragment::SqlSelectOrderBy {
555 let _ = write!(
556 buff,
557 " {}",
558 match value.order {
559 Order::ASC => "ASC",
560 Order::DESC => "DESC",
561 }
562 );
563 }
564 }
565
566 fn write_join_type(&self, _context: &mut Context, buff: &mut String, join_type: &JoinType) {
567 buff.push_str(match &join_type {
568 JoinType::Default => "JOIN",
569 JoinType::Inner => "INNER JOIN",
570 JoinType::Outer => "OUTER JOIN",
571 JoinType::Left => "LEFT JOIN",
572 JoinType::Right => "RIGHT JOIN",
573 JoinType::Cross => "CROSS",
574 JoinType::Natural => "NATURAL JOIN",
575 });
576 }
577
578 fn write_join(
579 &self,
580 context: &mut Context,
581 buff: &mut String,
582 join: &Join<&dyn DataSet, &dyn DataSet, &dyn Expression>,
583 ) {
584 let mut context = context.switch_fragment(Fragment::SqlJoin);
585 context.current.qualify_columns = true;
586 join.lhs
587 .write_query(self.as_dyn(), &mut context.current, buff);
588 buff.push(' ');
589 self.write_join_type(&mut context.current, buff, &join.join);
590 buff.push(' ');
591 join.rhs
592 .write_query(self.as_dyn(), &mut context.current, buff);
593 if let Some(on) = &join.on {
594 buff.push_str(" ON ");
595 on.write_query(self.as_dyn(), &mut context.current, buff);
596 }
597 }
598
599 fn write_transaction_begin(&self, buff: &mut String) {
600 buff.push_str("BEGIN;");
601 }
602
603 fn write_transaction_commit(&self, buff: &mut String) {
604 buff.push_str("COMMIT;");
605 }
606
607 fn write_transaction_rollback(&self, buff: &mut String) {
608 buff.push_str("ROLLBACK;");
609 }
610
611 fn write_create_schema<E>(&self, buff: &mut String, if_not_exists: bool)
612 where
613 Self: Sized,
614 E: Entity,
615 {
616 buff.push_str("CREATE SCHEMA ");
617 let mut context = Context::new(Fragment::SqlCreateSchema, E::qualified_columns());
618 if if_not_exists {
619 buff.push_str("IF NOT EXISTS ");
620 }
621 self.write_identifier_quoted(&mut context, buff, E::table_ref().schema);
622 buff.push(';');
623 }
624
625 fn write_drop_schema<E>(&self, buff: &mut String, if_exists: bool)
626 where
627 Self: Sized,
628 E: Entity,
629 {
630 buff.push_str("DROP SCHEMA ");
631 let mut context = Context::new(Fragment::SqlDropSchema, E::qualified_columns());
632 if if_exists {
633 buff.push_str("IF EXISTS ");
634 }
635 self.write_identifier_quoted(&mut context, buff, E::table_ref().schema);
636 buff.push(';');
637 }
638
639 fn write_create_table<E>(&self, buff: &mut String, if_not_exists: bool)
640 where
641 Self: Sized,
642 E: Entity,
643 {
644 let mut context = Context::new(Fragment::SqlCreateTable, E::qualified_columns());
645 buff.push_str("CREATE TABLE ");
646 if if_not_exists {
647 buff.push_str("IF NOT EXISTS ");
648 }
649 self.write_table_ref(&mut context, buff, E::table_ref());
650 buff.push_str(" (\n");
651 separated_by(
652 buff,
653 E::columns(),
654 |buff, v| {
655 self.write_create_table_column_fragment(&mut context, buff, v);
656 },
657 ",\n",
658 );
659 let primary_key = E::primary_key_def();
660 if primary_key.len() > 1 {
661 buff.push_str(",\nPRIMARY KEY (");
662 separated_by(
663 buff,
664 primary_key,
665 |buff, v| {
666 self.write_identifier_quoted(
667 &mut context
668 .switch_fragment(Fragment::SqlCreateTablePrimaryKey)
669 .current,
670 buff,
671 v.name(),
672 );
673 },
674 ", ",
675 );
676 buff.push(')');
677 }
678 for unique in E::unique_defs() {
679 if unique.len() > 1 {
680 buff.push_str(",\nUNIQUE (");
681 separated_by(
682 buff,
683 unique,
684 |buff, v| {
685 self.write_identifier_quoted(
686 &mut context
687 .switch_fragment(Fragment::SqlCreateTableUnique)
688 .current,
689 buff,
690 v.name(),
691 );
692 },
693 ", ",
694 );
695 buff.push(')');
696 }
697 }
698 buff.push_str(");");
699 self.write_column_comments::<E>(&mut context, buff);
700 }
701
702 fn write_column_comments<E>(&self, context: &mut Context, buff: &mut String)
703 where
704 Self: Sized,
705 E: Entity,
706 {
707 let mut context = context.switch_fragment(Fragment::SqlCommentOnColumn);
708 context.current.qualify_columns = true;
709 for c in E::columns().iter().filter(|c| !c.comment.is_empty()) {
710 buff.push_str("\nCOMMENT ON COLUMN ");
711 self.write_column_ref(&mut context.current, buff, c.into());
712 buff.push_str(" IS ");
713 self.write_value_string(&mut context.current, buff, c.comment);
714 buff.push(';');
715 }
716 }
717
718 fn write_create_table_column_fragment(
719 &self,
720 context: &mut Context,
721 buff: &mut String,
722 column: &ColumnDef,
723 ) where
724 Self: Sized,
725 {
726 self.write_identifier_quoted(context, buff, &column.name());
727 buff.push(' ');
728 if !column.column_type.is_empty() {
729 buff.push_str(&column.column_type);
730 } else {
731 SqlWriter::write_column_type(self, context, buff, &column.value);
732 }
733 if !column.nullable && column.primary_key == PrimaryKeyType::None {
734 buff.push_str(" NOT NULL");
735 }
736 if let Some(default) = &column.default {
737 buff.push_str(" DEFAULT ");
738 default.write_query(self.as_dyn(), context, buff);
739 }
740 if column.primary_key == PrimaryKeyType::PrimaryKey {
741 buff.push_str(" PRIMARY KEY");
743 }
744 if column.unique && column.primary_key != PrimaryKeyType::PrimaryKey {
745 buff.push_str(" UNIQUE");
746 }
747 if let Some(references) = column.references {
748 buff.push_str(" REFERENCES ");
749 self.write_table_ref(context, buff, &references.table_ref());
750 buff.push('(');
751 self.write_column_ref(context, buff, &references);
752 buff.push(')');
753 if let Some(on_delete) = &column.on_delete {
754 buff.push_str(" ON DELETE ");
755 self.write_create_table_references_action(context, buff, on_delete);
756 }
757 if let Some(on_update) = &column.on_update {
758 buff.push_str(" ON UPDATE ");
759 self.write_create_table_references_action(context, buff, on_update);
760 }
761 }
762 }
763
764 fn write_create_table_references_action(
765 &self,
766 _context: &mut Context,
767 buff: &mut String,
768 action: &Action,
769 ) {
770 buff.push_str(match action {
771 Action::NoAction => "NO ACTION",
772 Action::Restrict => "RESTRICT",
773 Action::Cascade => "CASCADE",
774 Action::SetNull => "SET NULL",
775 Action::SetDefault => "SET DEFAULT",
776 });
777 }
778
779 fn write_drop_table<E>(&self, buff: &mut String, if_exists: bool)
780 where
781 Self: Sized,
782 E: Entity,
783 {
784 buff.push_str("DROP TABLE ");
785 let mut context = Context::new(Fragment::SqlDropTable, E::qualified_columns());
786 if if_exists {
787 buff.push_str("IF EXISTS ");
788 }
789 self.write_table_ref(&mut context, buff, E::table_ref());
790 buff.push(';');
791 }
792
793 fn write_select<Item, Cols, Data, Cond>(
794 &self,
795 buff: &mut String,
796 columns: Cols,
797 from: &Data,
798 condition: &Cond,
799 limit: Option<u32>,
800 ) where
801 Self: Sized,
802 Item: Expression,
803 Cols: IntoIterator<Item = Item> + Clone,
804 Data: DataSet,
805 Cond: Expression,
806 {
807 buff.push_str("SELECT ");
808 let mut has_order_by = false;
809 let mut context = Context::new(Fragment::SqlSelect, Data::qualified_columns());
810 separated_by(
811 buff,
812 columns.clone(),
813 |buff, col| {
814 col.write_query(self, &mut context, buff);
815 has_order_by = has_order_by || col.is_ordered();
816 },
817 ", ",
818 );
819 buff.push_str("\nFROM ");
820 from.write_query(
821 self,
822 &mut context.switch_fragment(Fragment::SqlSelectFrom).current,
823 buff,
824 );
825 buff.push_str("\nWHERE ");
826 condition.write_query(
827 self,
828 &mut context.switch_fragment(Fragment::SqlSelectWhere).current,
829 buff,
830 );
831 if has_order_by {
832 buff.push_str("\nORDER BY ");
833 for col in columns.into_iter().filter(Expression::is_ordered) {
834 col.write_query(
835 self,
836 &mut context.switch_fragment(Fragment::SqlSelectOrderBy).current,
837 buff,
838 );
839 }
840 }
841 if let Some(limit) = limit {
842 let _ = write!(buff, "\nLIMIT {}", limit);
843 }
844 buff.push(';');
845 }
846
847 fn write_insert<'b, E, It>(&self, buff: &mut String, entities: It, update: bool)
848 where
849 Self: Sized,
850 E: Entity + 'b,
851 It: IntoIterator<Item = &'b E>,
852 {
853 let mut rows = entities.into_iter().map(Entity::row_filtered).peekable();
854 let Some(mut row) = rows.next() else {
855 return;
856 };
857 buff.push_str("INSERT INTO ");
858 let mut context = Context::new(Fragment::SqlInsertInto, E::qualified_columns());
859 self.write_table_ref(&mut context, buff, E::table_ref());
860 buff.push_str(" (");
861 let columns = E::columns().iter();
862 let single = rows.peek().is_none();
863 if single {
864 separated_by(
866 buff,
867 row.iter(),
868 |buff, v| {
869 self.write_identifier_quoted(&mut context, buff, v.0);
870 },
871 ", ",
872 );
873 } else {
874 separated_by(
876 buff,
877 columns.clone(),
878 |buff, v| {
879 self.write_identifier_quoted(&mut context, buff, v.name());
880 },
881 ", ",
882 );
883 };
884 buff.push_str(") VALUES\n");
885 let mut context = context.switch_fragment(Fragment::SqlInsertIntoValues);
886 let mut first_row = None;
887 let mut separate = false;
888 loop {
889 if separate {
890 buff.push_str(",\n");
891 }
892 buff.push('(');
893 let mut fields = row.iter();
894 let mut field = fields.next();
895 separated_by(
896 buff,
897 E::columns(),
898 |buff, col| {
899 if Some(col.name()) == field.map(|v| v.0) {
900 self.write_value(
901 &mut context.current,
902 buff,
903 field
904 .map(|v| &v.1)
905 .expect(&format!("Column {} does not have a value", col.name())),
906 );
907 field = fields.next();
908 } else if !single {
909 buff.push_str("DEFAULT");
910 }
911 },
912 ", ",
913 );
914 buff.push(')');
915 separate = true;
916 if first_row.is_none() {
917 first_row = row.into();
918 }
919 if let Some(next) = rows.next() {
920 row = next;
921 } else {
922 break;
923 };
924 }
925 let first_row = first_row
926 .expect("Should have at least one row")
927 .into_iter()
928 .map(|(v, _)| v);
929 if update {
930 self.write_insert_update_fragment::<E, _>(
931 &mut context.current,
932 buff,
933 if single {
934 EitherIterator::Left(
935 columns.filter(|c| first_row.clone().find(|n| *n == c.name()).is_some()),
937 )
938 } else {
939 EitherIterator::Right(columns)
940 },
941 );
942 }
943 buff.push(';');
944 }
945
946 fn write_insert_update_fragment<'a, E, It>(
947 &self,
948 context: &mut Context,
949 buff: &mut String,
950 columns: It,
951 ) where
952 Self: Sized,
953 E: Entity,
954 It: Iterator<Item = &'a ColumnDef>,
955 {
956 let pk = E::primary_key_def();
957 if pk.len() == 0 {
958 return;
959 }
960 buff.push_str("\nON CONFLICT");
961 context.fragment = Fragment::SqlInsertIntoOnConflict;
962 if pk.len() > 0 {
963 buff.push_str(" (");
964 separated_by(
965 buff,
966 pk,
967 |buff, v| {
968 self.write_identifier_quoted(context, buff, v.name());
969 },
970 ", ",
971 );
972 buff.push(')');
973 }
974 buff.push_str(" DO UPDATE SET\n");
975 separated_by(
976 buff,
977 columns.filter(|c| c.primary_key == PrimaryKeyType::None),
978 |buff, v| {
979 self.write_identifier_quoted(context, buff, v.name());
980 buff.push_str(" = EXCLUDED.");
981 self.write_identifier_quoted(context, buff, v.name());
982 },
983 ",\n",
984 );
985 }
986
987 fn write_delete<E, Expr>(&self, buff: &mut String, condition: &Expr)
988 where
989 Self: Sized,
990 E: Entity,
991 Expr: Expression,
992 {
993 buff.push_str("DELETE FROM ");
994 let mut context = Context::new(Fragment::SqlDeleteFrom, E::qualified_columns());
995 self.write_table_ref(&mut context, buff, E::table_ref());
996 buff.push_str("\nWHERE ");
997 condition.write_query(
998 self,
999 &mut context
1000 .switch_fragment(Fragment::SqlDeleteFromWhere)
1001 .current,
1002 buff,
1003 );
1004 buff.push(';');
1005 }
1006}
1007
1008pub struct GenericSqlWriter;
1009impl GenericSqlWriter {
1010 pub fn new() -> Self {
1011 Self {}
1012 }
1013}
1014impl SqlWriter for GenericSqlWriter {
1015 fn as_dyn(&self) -> &dyn SqlWriter {
1016 self
1017 }
1018}