1pub(crate) mod engine;
59pub mod plan;
60
61use crate::expressions::*;
62use crate::generator::{Generator, GeneratorConfig, NotInStyle};
63use crate::parser::Parser;
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub struct ClauseOptions {
69 pub append: bool,
70}
71
72impl Default for ClauseOptions {
73 fn default() -> Self {
74 Self { append: true }
75 }
76}
77
78#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
80pub struct LateralViewOptions {
81 pub outer: bool,
82}
83
84#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
86pub struct CtasOptions {
87 pub replace: bool,
88 pub temporary: bool,
89}
90
91fn generate_builder_sql(expression: &Expression) -> String {
92 let mut generator = Generator::with_config(GeneratorConfig {
93 not_in_style: NotInStyle::Infix,
94 ..Default::default()
95 });
96 generator.generate(expression).unwrap_or_default()
97}
98
99fn is_safe_identifier_name(name: &str) -> bool {
100 if name.is_empty() {
101 return false;
102 }
103
104 let mut chars = name.chars();
105 let Some(first) = chars.next() else {
106 return false;
107 };
108
109 if !(first == '_' || first.is_ascii_alphabetic()) {
110 return false;
111 }
112
113 chars.all(|c| c == '_' || c.is_ascii_alphanumeric())
114}
115
116fn builder_identifier(name: &str) -> Identifier {
117 if name == "*" || is_safe_identifier_name(name) {
118 Identifier::new(name)
119 } else {
120 Identifier::quoted(name)
121 }
122}
123
124fn builder_table_ref(name: &str) -> TableRef {
125 let parts: Vec<&str> = name.split('.').collect();
126
127 match parts.len() {
128 3 => {
129 let mut t = TableRef::new(parts[2]);
130 t.name = builder_identifier(parts[2]);
131 t.schema = Some(builder_identifier(parts[1]));
132 t.catalog = Some(builder_identifier(parts[0]));
133 t
134 }
135 2 => {
136 let mut t = TableRef::new(parts[1]);
137 t.name = builder_identifier(parts[1]);
138 t.schema = Some(builder_identifier(parts[0]));
139 t
140 }
141 _ => {
142 let first = parts.first().copied().unwrap_or("");
143 let mut t = TableRef::new(first);
144 t.name = builder_identifier(first);
145 t
146 }
147 }
148}
149
150pub fn col(name: &str) -> Expr {
174 let parts: Vec<&str> = name.split('.').collect();
175 if parts.len() >= 3 && parts.iter().all(|part| !part.is_empty()) {
176 let mut expr = Expression::boxed_column(Column {
177 name: builder_identifier(parts[1]),
178 table: Some(builder_identifier(parts[0])),
179 join_mark: false,
180 trailing_comments: Vec::new(),
181 span: None,
182 inferred_type: None,
183 });
184
185 for field in &parts[2..] {
186 expr = Expression::Dot(Box::new(DotAccess {
187 this: expr,
188 field: builder_identifier(field),
189 inferred_type: None,
190 }));
191 }
192
193 return Expr(expr);
194 }
195
196 if let Some((table, column)) = name.rsplit_once('.') {
197 Expr(Expression::boxed_column(Column {
198 name: builder_identifier(column),
199 table: Some(builder_identifier(table)),
200 join_mark: false,
201 trailing_comments: Vec::new(),
202 span: None,
203 inferred_type: None,
204 }))
205 } else {
206 Expr(Expression::boxed_column(Column {
207 name: builder_identifier(name),
208 table: None,
209 join_mark: false,
210 trailing_comments: Vec::new(),
211 span: None,
212 inferred_type: None,
213 }))
214 }
215}
216
217pub fn lit<V: IntoLiteral>(value: V) -> Expr {
233 value.into_literal()
234}
235
236pub fn star() -> Expr {
238 Expr(Expression::star())
239}
240
241pub fn null() -> Expr {
243 Expr(Expression::Null(Null))
244}
245
246pub fn boolean(value: bool) -> Expr {
248 Expr(Expression::Boolean(BooleanLiteral { value }))
249}
250
251pub fn table(name: &str) -> Expr {
268 Expr(Expression::Table(Box::new(builder_table_ref(name))))
269}
270
271pub fn func(name: &str, args: impl IntoIterator<Item = Expr>) -> Expr {
288 Expr(Expression::Function(Box::new(Function {
289 name: name.to_string(),
290 args: args.into_iter().map(|a| a.0).collect(),
291 ..Function::default()
292 })))
293}
294
295pub fn cast(expr: Expr, to: &str) -> Expr {
311 let data_type = parse_simple_data_type(to);
312 Expr(Expression::Cast(Box::new(Cast {
313 this: expr.0,
314 to: data_type,
315 trailing_comments: Vec::new(),
316 double_colon_syntax: false,
317 format: None,
318 default: None,
319 inferred_type: None,
320 })))
321}
322
323pub fn not(expr: Expr) -> Expr {
328 Expr(Expression::Not(Box::new(UnaryOp::new(expr.0))))
329}
330
331pub fn and(left: Expr, right: Expr) -> Expr {
336 left.and(right)
337}
338
339pub fn or(left: Expr, right: Expr) -> Expr {
344 left.or(right)
345}
346
347pub fn alias(expr: Expr, name: &str) -> Expr {
352 Expr(Expression::Alias(Box::new(Alias {
353 this: expr.0,
354 alias: builder_identifier(name),
355 column_aliases: Vec::new(),
356 alias_explicit_as: false,
357 alias_keyword: None,
358 pre_alias_comments: Vec::new(),
359 trailing_comments: Vec::new(),
360 inferred_type: None,
361 })))
362}
363
364pub fn sql_expr(sql: &str) -> Expr {
388 let wrapped = format!("SELECT {}", sql);
389 let ast = Parser::parse_sql(&wrapped).expect("sql_expr: failed to parse SQL expression");
390 if let Expression::Select(s) = &ast[0] {
391 if let Some(first) = s.expressions.first() {
392 return Expr(first.clone());
393 }
394 }
395 panic!("sql_expr: failed to extract expression from parsed SQL");
396}
397
398pub fn condition(sql: &str) -> Expr {
407 sql_expr(sql)
408}
409
410pub fn count(expr: Expr) -> Expr {
418 Expr(Expression::Count(Box::new(CountFunc {
419 this: Some(expr.0),
420 star: false,
421 distinct: false,
422 filter: None,
423 ignore_nulls: None,
424 original_name: None,
425 inferred_type: None,
426 })))
427}
428
429pub fn count_star() -> Expr {
431 Expr(Expression::Count(Box::new(CountFunc {
432 this: None,
433 star: true,
434 distinct: false,
435 filter: None,
436 ignore_nulls: None,
437 original_name: None,
438 inferred_type: None,
439 })))
440}
441
442pub fn count_distinct(expr: Expr) -> Expr {
444 Expr(Expression::Count(Box::new(CountFunc {
445 this: Some(expr.0),
446 star: false,
447 distinct: true,
448 filter: None,
449 ignore_nulls: None,
450 original_name: None,
451 inferred_type: None,
452 })))
453}
454
455pub fn sum(expr: Expr) -> Expr {
457 Expr(Expression::Sum(Box::new(AggFunc {
458 this: expr.0,
459 distinct: false,
460 filter: None,
461 order_by: vec![],
462 name: None,
463 ignore_nulls: None,
464 having_max: None,
465 limit: None,
466 inferred_type: None,
467 })))
468}
469
470pub fn avg(expr: Expr) -> Expr {
472 Expr(Expression::Avg(Box::new(AggFunc {
473 this: expr.0,
474 distinct: false,
475 filter: None,
476 order_by: vec![],
477 name: None,
478 ignore_nulls: None,
479 having_max: None,
480 limit: None,
481 inferred_type: None,
482 })))
483}
484
485pub fn min_(expr: Expr) -> Expr {
487 Expr(Expression::Min(Box::new(AggFunc {
488 this: expr.0,
489 distinct: false,
490 filter: None,
491 order_by: vec![],
492 name: None,
493 ignore_nulls: None,
494 having_max: None,
495 limit: None,
496 inferred_type: None,
497 })))
498}
499
500pub fn max_(expr: Expr) -> Expr {
502 Expr(Expression::Max(Box::new(AggFunc {
503 this: expr.0,
504 distinct: false,
505 filter: None,
506 order_by: vec![],
507 name: None,
508 ignore_nulls: None,
509 having_max: None,
510 limit: None,
511 inferred_type: None,
512 })))
513}
514
515pub fn approx_distinct(expr: Expr) -> Expr {
517 Expr(Expression::ApproxDistinct(Box::new(AggFunc {
518 this: expr.0,
519 distinct: false,
520 filter: None,
521 order_by: vec![],
522 name: None,
523 ignore_nulls: None,
524 having_max: None,
525 limit: None,
526 inferred_type: None,
527 })))
528}
529
530pub fn upper(expr: Expr) -> Expr {
534 Expr(Expression::Upper(Box::new(UnaryFunc::new(expr.0))))
535}
536
537pub fn lower(expr: Expr) -> Expr {
539 Expr(Expression::Lower(Box::new(UnaryFunc::new(expr.0))))
540}
541
542pub fn length(expr: Expr) -> Expr {
544 Expr(Expression::Length(Box::new(UnaryFunc::new(expr.0))))
545}
546
547pub fn trim(expr: Expr) -> Expr {
549 Expr(Expression::Trim(Box::new(TrimFunc {
550 this: expr.0,
551 characters: None,
552 position: TrimPosition::Both,
553 sql_standard_syntax: false,
554 position_explicit: false,
555 })))
556}
557
558pub fn ltrim(expr: Expr) -> Expr {
560 Expr(Expression::LTrim(Box::new(UnaryFunc::new(expr.0))))
561}
562
563pub fn rtrim(expr: Expr) -> Expr {
565 Expr(Expression::RTrim(Box::new(UnaryFunc::new(expr.0))))
566}
567
568pub fn reverse(expr: Expr) -> Expr {
570 Expr(Expression::Reverse(Box::new(UnaryFunc::new(expr.0))))
571}
572
573pub fn initcap(expr: Expr) -> Expr {
575 Expr(Expression::Initcap(Box::new(UnaryFunc::new(expr.0))))
576}
577
578pub fn substring(expr: Expr, start: Expr, len: Option<Expr>) -> Expr {
580 Expr(Expression::Substring(Box::new(SubstringFunc {
581 this: expr.0,
582 start: start.0,
583 length: len.map(|l| l.0),
584 from_for_syntax: false,
585 })))
586}
587
588pub fn replace_(expr: Expr, old: Expr, new: Expr) -> Expr {
591 Expr(Expression::Replace(Box::new(ReplaceFunc {
592 this: expr.0,
593 old: old.0,
594 new: new.0,
595 })))
596}
597
598pub fn concat_ws(separator: Expr, exprs: impl IntoIterator<Item = Expr>) -> Expr {
600 Expr(Expression::ConcatWs(Box::new(ConcatWs {
601 separator: separator.0,
602 expressions: exprs.into_iter().map(|e| e.0).collect(),
603 })))
604}
605
606pub fn coalesce(exprs: impl IntoIterator<Item = Expr>) -> Expr {
610 Expr(Expression::Coalesce(Box::new(VarArgFunc {
611 expressions: exprs.into_iter().map(|e| e.0).collect(),
612 original_name: None,
613 inferred_type: None,
614 })))
615}
616
617pub fn null_if(expr1: Expr, expr2: Expr) -> Expr {
619 Expr(Expression::NullIf(Box::new(BinaryFunc {
620 this: expr1.0,
621 expression: expr2.0,
622 original_name: None,
623 inferred_type: None,
624 })))
625}
626
627pub fn if_null(expr: Expr, fallback: Expr) -> Expr {
629 Expr(Expression::IfNull(Box::new(BinaryFunc {
630 this: expr.0,
631 expression: fallback.0,
632 original_name: None,
633 inferred_type: None,
634 })))
635}
636
637pub fn abs(expr: Expr) -> Expr {
641 Expr(Expression::Abs(Box::new(UnaryFunc::new(expr.0))))
642}
643
644pub fn round(expr: Expr, decimals: Option<Expr>) -> Expr {
646 Expr(Expression::Round(Box::new(RoundFunc {
647 this: expr.0,
648 decimals: decimals.map(|d| d.0),
649 })))
650}
651
652pub fn floor(expr: Expr) -> Expr {
654 Expr(Expression::Floor(Box::new(FloorFunc {
655 this: expr.0,
656 scale: None,
657 to: None,
658 })))
659}
660
661pub fn ceil(expr: Expr) -> Expr {
663 Expr(Expression::Ceil(Box::new(CeilFunc {
664 this: expr.0,
665 decimals: None,
666 to: None,
667 })))
668}
669
670pub fn power(base: Expr, exponent: Expr) -> Expr {
672 Expr(Expression::Power(Box::new(BinaryFunc {
673 this: base.0,
674 expression: exponent.0,
675 original_name: None,
676 inferred_type: None,
677 })))
678}
679
680pub fn sqrt(expr: Expr) -> Expr {
682 Expr(Expression::Sqrt(Box::new(UnaryFunc::new(expr.0))))
683}
684
685pub fn ln(expr: Expr) -> Expr {
687 Expr(Expression::Ln(Box::new(UnaryFunc::new(expr.0))))
688}
689
690pub fn exp_(expr: Expr) -> Expr {
692 Expr(Expression::Exp(Box::new(UnaryFunc::new(expr.0))))
693}
694
695pub fn sign(expr: Expr) -> Expr {
697 Expr(Expression::Sign(Box::new(UnaryFunc::new(expr.0))))
698}
699
700pub fn greatest(exprs: impl IntoIterator<Item = Expr>) -> Expr {
702 Expr(Expression::Greatest(Box::new(VarArgFunc {
703 expressions: exprs.into_iter().map(|e| e.0).collect(),
704 original_name: None,
705 inferred_type: None,
706 })))
707}
708
709pub fn least(exprs: impl IntoIterator<Item = Expr>) -> Expr {
711 Expr(Expression::Least(Box::new(VarArgFunc {
712 expressions: exprs.into_iter().map(|e| e.0).collect(),
713 original_name: None,
714 inferred_type: None,
715 })))
716}
717
718pub fn current_date_() -> Expr {
722 Expr(Expression::CurrentDate(CurrentDate))
723}
724
725pub fn current_time_() -> Expr {
727 Expr(Expression::CurrentTime(CurrentTime { precision: None }))
728}
729
730pub fn current_timestamp_() -> Expr {
732 Expr(Expression::CurrentTimestamp(CurrentTimestamp {
733 precision: None,
734 sysdate: false,
735 }))
736}
737
738pub fn extract_(field: &str, expr: Expr) -> Expr {
740 Expr(Expression::Extract(Box::new(ExtractFunc {
741 this: expr.0,
742 field: parse_datetime_field(field),
743 })))
744}
745
746fn parse_datetime_field(field: &str) -> DateTimeField {
748 match field.to_uppercase().as_str() {
749 "YEAR" => DateTimeField::Year,
750 "MONTH" => DateTimeField::Month,
751 "DAY" => DateTimeField::Day,
752 "HOUR" => DateTimeField::Hour,
753 "MINUTE" => DateTimeField::Minute,
754 "SECOND" => DateTimeField::Second,
755 "MILLISECOND" => DateTimeField::Millisecond,
756 "MICROSECOND" => DateTimeField::Microsecond,
757 "DOW" | "DAYOFWEEK" => DateTimeField::DayOfWeek,
758 "DOY" | "DAYOFYEAR" => DateTimeField::DayOfYear,
759 "WEEK" => DateTimeField::Week,
760 "QUARTER" => DateTimeField::Quarter,
761 "EPOCH" => DateTimeField::Epoch,
762 "TIMEZONE" => DateTimeField::Timezone,
763 "TIMEZONE_HOUR" => DateTimeField::TimezoneHour,
764 "TIMEZONE_MINUTE" => DateTimeField::TimezoneMinute,
765 "DATE" => DateTimeField::Date,
766 "TIME" => DateTimeField::Time,
767 other => DateTimeField::Custom(other.to_string()),
768 }
769}
770
771pub fn row_number() -> Expr {
775 Expr(Expression::RowNumber(RowNumber))
776}
777
778pub fn rank_() -> Expr {
780 Expr(Expression::Rank(Rank {
781 order_by: None,
782 args: vec![],
783 }))
784}
785
786pub fn dense_rank() -> Expr {
788 Expr(Expression::DenseRank(DenseRank { args: vec![] }))
789}
790
791pub fn select<I, E>(expressions: I) -> SelectBuilder
818where
819 I: IntoIterator<Item = E>,
820 E: IntoExpr,
821{
822 SelectBuilder::new().select_cols(expressions)
823}
824
825pub fn from(table_name: &str) -> SelectBuilder {
840 SelectBuilder::new().from(table_name)
841}
842
843pub fn delete(table_name: &str) -> DeleteBuilder {
856 DeleteBuilder {
857 delete: Delete {
858 table: builder_table_ref(table_name),
859 hint: None,
860 on_cluster: None,
861 alias: None,
862 alias_explicit_as: false,
863 using: Vec::new(),
864 where_clause: None,
865 output: None,
866 leading_comments: Vec::new(),
867 with: None,
868 limit: None,
869 order_by: None,
870 returning: Vec::new(),
871 tables: Vec::new(),
872 tables_from_using: false,
873 joins: Vec::new(),
874 force_index: None,
875 no_from: false,
876 },
877 }
878}
879
880pub fn insert_into(table_name: &str) -> InsertBuilder {
897 InsertBuilder {
898 insert: Insert {
899 table: builder_table_ref(table_name),
900 columns: Vec::new(),
901 values: Vec::new(),
902 query: None,
903 overwrite: false,
904 partition: Vec::new(),
905 directory: None,
906 returning: Vec::new(),
907 output: None,
908 on_conflict: None,
909 leading_comments: Vec::new(),
910 if_exists: false,
911 with: None,
912 ignore: false,
913 source_alias: None,
914 alias: None,
915 alias_explicit_as: false,
916 default_values: false,
917 by_name: false,
918 conflict_action: None,
919 is_replace: false,
920 hint: None,
921 replace_where: None,
922 source: None,
923 function_target: None,
924 partition_by: None,
925 settings: Vec::new(),
926 },
927 }
928}
929
930pub fn update(table_name: &str) -> UpdateBuilder {
948 UpdateBuilder {
949 update: Update {
950 table: builder_table_ref(table_name),
951 hint: None,
952 extra_tables: Vec::new(),
953 table_joins: Vec::new(),
954 set: Vec::new(),
955 from_clause: None,
956 from_joins: Vec::new(),
957 where_clause: None,
958 returning: Vec::new(),
959 output: None,
960 with: None,
961 leading_comments: Vec::new(),
962 limit: None,
963 order_by: None,
964 from_before_set: false,
965 },
966 }
967}
968
969#[derive(Debug, Clone)]
994pub struct Expr(pub Expression);
995
996impl Expr {
997 pub fn into_inner(self) -> Expression {
999 self.0
1000 }
1001
1002 pub fn to_sql(&self) -> String {
1006 generate_builder_sql(&self.0)
1007 }
1008
1009 pub fn eq(self, other: Expr) -> Expr {
1013 Expr(engine::binary(engine::BinaryKind::Eq, self.0, other.0))
1014 }
1015
1016 pub fn neq(self, other: Expr) -> Expr {
1018 Expr(engine::binary(engine::BinaryKind::Neq, self.0, other.0))
1019 }
1020
1021 pub fn lt(self, other: Expr) -> Expr {
1023 Expr(engine::binary(engine::BinaryKind::Lt, self.0, other.0))
1024 }
1025
1026 pub fn lte(self, other: Expr) -> Expr {
1028 Expr(engine::binary(engine::BinaryKind::Lte, self.0, other.0))
1029 }
1030
1031 pub fn gt(self, other: Expr) -> Expr {
1033 Expr(engine::binary(engine::BinaryKind::Gt, self.0, other.0))
1034 }
1035
1036 pub fn gte(self, other: Expr) -> Expr {
1038 Expr(engine::binary(engine::BinaryKind::Gte, self.0, other.0))
1039 }
1040
1041 pub fn and(self, other: Expr) -> Expr {
1045 Expr(engine::binary(engine::BinaryKind::And, self.0, other.0))
1046 }
1047
1048 pub fn or(self, other: Expr) -> Expr {
1050 Expr(engine::binary(engine::BinaryKind::Or, self.0, other.0))
1051 }
1052
1053 pub fn not(self) -> Expr {
1055 Expr(engine::unary(engine::UnaryKind::Not, self.0))
1056 }
1057
1058 pub fn xor(self, other: Expr) -> Expr {
1060 Expr(engine::binary(engine::BinaryKind::Xor, self.0, other.0))
1061 }
1062
1063 pub fn add(self, other: Expr) -> Expr {
1067 Expr(engine::binary(engine::BinaryKind::Add, self.0, other.0))
1068 }
1069
1070 pub fn sub(self, other: Expr) -> Expr {
1072 Expr(engine::binary(engine::BinaryKind::Sub, self.0, other.0))
1073 }
1074
1075 pub fn mul(self, other: Expr) -> Expr {
1077 Expr(engine::binary(engine::BinaryKind::Mul, self.0, other.0))
1078 }
1079
1080 pub fn div(self, other: Expr) -> Expr {
1082 Expr(engine::binary(engine::BinaryKind::Div, self.0, other.0))
1083 }
1084
1085 pub fn modulo(self, other: Expr) -> Expr {
1087 Expr(engine::binary(engine::BinaryKind::Mod, self.0, other.0))
1088 }
1089
1090 pub fn neg(self) -> Expr {
1092 Expr(engine::unary(engine::UnaryKind::Neg, self.0))
1093 }
1094
1095 pub fn is(self, other: Expr) -> Expr {
1097 Expr(engine::binary(engine::BinaryKind::Is, self.0, other.0))
1098 }
1099
1100 pub fn is_null(self) -> Expr {
1104 Expr(engine::unary(engine::UnaryKind::IsNull, self.0))
1105 }
1106
1107 pub fn is_not_null(self) -> Expr {
1109 Expr(engine::unary(engine::UnaryKind::IsNotNull, self.0))
1110 }
1111
1112 pub fn in_list(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1116 Expr(Expression::In(Box::new(In {
1117 this: self.0,
1118 expressions: values.into_iter().map(|v| v.0).collect(),
1119 query: None,
1120 not: false,
1121 global: false,
1122 unnest: None,
1123 is_field: false,
1124 })))
1125 }
1126
1127 pub fn between(self, low: Expr, high: Expr) -> Expr {
1129 Expr(Expression::Between(Box::new(Between {
1130 this: self.0,
1131 low: low.0,
1132 high: high.0,
1133 not: false,
1134 symmetric: None,
1135 })))
1136 }
1137
1138 pub fn like(self, pattern: Expr) -> Expr {
1140 Expr(engine::binary(engine::BinaryKind::Like, self.0, pattern.0))
1141 }
1142
1143 pub fn alias(self, name: &str) -> Expr {
1145 alias(self, name)
1146 }
1147
1148 pub fn cast(self, to: &str) -> Expr {
1152 cast(self, to)
1153 }
1154
1155 pub fn asc(self) -> Expr {
1160 Expr(Expression::Ordered(Box::new(Ordered {
1161 this: self.0,
1162 desc: false,
1163 nulls_first: None,
1164 explicit_asc: true,
1165 with_fill: None,
1166 })))
1167 }
1168
1169 pub fn desc(self) -> Expr {
1173 Expr(Expression::Ordered(Box::new(Ordered {
1174 this: self.0,
1175 desc: true,
1176 nulls_first: None,
1177 explicit_asc: false,
1178 with_fill: None,
1179 })))
1180 }
1181
1182 pub fn ilike(self, pattern: Expr) -> Expr {
1187 Expr(engine::binary(engine::BinaryKind::ILike, self.0, pattern.0))
1188 }
1189
1190 pub fn rlike(self, pattern: Expr) -> Expr {
1195 Expr(engine::binary(engine::BinaryKind::RLike, self.0, pattern.0))
1196 }
1197
1198 pub fn not_in(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1202 Expr(Expression::In(Box::new(In {
1203 this: self.0,
1204 expressions: values.into_iter().map(|v| v.0).collect(),
1205 query: None,
1206 not: true,
1207 global: false,
1208 unnest: None,
1209 is_field: false,
1210 })))
1211 }
1212}
1213
1214pub struct SelectBuilder {
1240 select: Select,
1241}
1242
1243impl SelectBuilder {
1244 fn new() -> Self {
1245 SelectBuilder {
1246 select: Select::new(),
1247 }
1248 }
1249
1250 fn edit(mut self, edit: impl FnOnce(&mut Expression)) -> Self {
1251 let mut expression = Expression::Select(Box::new(self.select));
1252 edit(&mut expression);
1253 self.select = match expression {
1254 Expression::Select(select) => *select,
1255 _ => unreachable!("select builder engine changed the expression kind"),
1256 };
1257 self
1258 }
1259
1260 fn join_with_kind(self, table_name: &str, on: Option<Expr>, kind: JoinKind) -> Self {
1261 let join = Join {
1262 kind,
1263 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1264 on: on.map(|expression| expression.0),
1265 using: Vec::new(),
1266 use_inner_keyword: false,
1267 use_outer_keyword: false,
1268 deferred_condition: false,
1269 join_hint: None,
1270 match_condition: None,
1271 pivots: Vec::new(),
1272 comments: Vec::new(),
1273 nesting_group: 0,
1274 directed: false,
1275 };
1276 self.edit(|expression| {
1277 engine::append_join(expression, join).expect("select builder accepts JOIN clauses")
1278 })
1279 }
1280
1281 pub fn select_cols<I, E>(self, expressions: I) -> Self
1286 where
1287 I: IntoIterator<Item = E>,
1288 E: IntoExpr,
1289 {
1290 self.select_cols_with_options(expressions, ClauseOptions::default())
1291 }
1292
1293 pub fn select_cols_with_options<I, E>(self, expressions: I, options: ClauseOptions) -> Self
1295 where
1296 I: IntoIterator<Item = E>,
1297 E: IntoExpr,
1298 {
1299 let values = expressions
1300 .into_iter()
1301 .map(|expression| expression.into_expr().0)
1302 .collect();
1303 self.edit(|expression| {
1304 engine::append_select(expression, values, options.append)
1305 .expect("select builder accepts SELECT clauses")
1306 })
1307 }
1308
1309 pub fn from(self, table_name: &str) -> Self {
1311 self.edit(|expression| {
1312 engine::set_from(
1313 expression,
1314 vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1315 )
1316 .expect("select builder accepts FROM clauses")
1317 })
1318 }
1319
1320 pub fn from_expr(self, expr: Expr) -> Self {
1325 self.edit(|expression| {
1326 engine::set_from(expression, vec![expr.0]).expect("select builder accepts FROM clauses")
1327 })
1328 }
1329
1330 pub fn join(self, table_name: &str, on: Expr) -> Self {
1332 self.join_with_kind(table_name, Some(on), JoinKind::Inner)
1333 }
1334
1335 pub fn left_join(self, table_name: &str, on: Expr) -> Self {
1337 self.join_with_kind(table_name, Some(on), JoinKind::Left)
1338 }
1339
1340 pub fn where_(self, condition: Expr) -> Self {
1342 self.where_with_options(condition, ClauseOptions::default())
1343 }
1344
1345 pub fn where_with_options(self, condition: Expr, options: ClauseOptions) -> Self {
1347 self.edit(|expression| {
1348 engine::apply_where(expression, condition.0, options.append)
1349 .expect("select builder accepts WHERE clauses")
1350 })
1351 }
1352
1353 pub fn group_by<I, E>(self, expressions: I) -> Self
1355 where
1356 I: IntoIterator<Item = E>,
1357 E: IntoExpr,
1358 {
1359 self.group_by_with_options(expressions, ClauseOptions::default())
1360 }
1361
1362 pub fn group_by_with_options<I, E>(self, expressions: I, options: ClauseOptions) -> Self
1364 where
1365 I: IntoIterator<Item = E>,
1366 E: IntoExpr,
1367 {
1368 let values = expressions
1369 .into_iter()
1370 .map(|expression| expression.into_expr().0)
1371 .collect();
1372 self.edit(|expression| {
1373 engine::apply_group_by(expression, values, options.append)
1374 .expect("select builder accepts GROUP BY clauses")
1375 })
1376 }
1377
1378 pub fn having(self, condition: Expr) -> Self {
1380 self.having_with_options(condition, ClauseOptions::default())
1381 }
1382
1383 pub fn having_with_options(self, condition: Expr, options: ClauseOptions) -> Self {
1385 self.edit(|expression| {
1386 engine::apply_having(expression, condition.0, options.append)
1387 .expect("select builder accepts HAVING clauses")
1388 })
1389 }
1390
1391 pub fn order_by<I, E>(self, expressions: I) -> Self
1397 where
1398 I: IntoIterator<Item = E>,
1399 E: IntoExpr,
1400 {
1401 self.order_by_with_options(expressions, ClauseOptions::default())
1402 }
1403
1404 pub fn order_by_with_options<I, E>(self, expressions: I, options: ClauseOptions) -> Self
1406 where
1407 I: IntoIterator<Item = E>,
1408 E: IntoExpr,
1409 {
1410 let values = expressions
1411 .into_iter()
1412 .map(|expression| engine::ordered(expression.into_expr().0))
1413 .collect();
1414 self.edit(|expression| {
1415 engine::apply_order_by(expression, values, options.append)
1416 .expect("select builder accepts ORDER BY clauses")
1417 })
1418 }
1419
1420 pub fn sort_by<I, E>(self, expressions: I) -> Self
1427 where
1428 I: IntoIterator<Item = E>,
1429 E: IntoExpr,
1430 {
1431 self.sort_by_with_options(expressions, ClauseOptions::default())
1432 }
1433
1434 pub fn sort_by_with_options<I, E>(self, expressions: I, options: ClauseOptions) -> Self
1436 where
1437 I: IntoIterator<Item = E>,
1438 E: IntoExpr,
1439 {
1440 let values = expressions
1441 .into_iter()
1442 .map(|expression| engine::ordered(expression.into_expr().0))
1443 .collect();
1444 self.edit(|expression| {
1445 engine::apply_sort_by(expression, values, options.append)
1446 .expect("select builder accepts SORT BY clauses")
1447 })
1448 }
1449
1450 pub fn limit(self, count: usize) -> Self {
1452 self.edit(|expression| {
1453 engine::apply_limit(
1454 expression,
1455 Expression::Literal(Box::new(Literal::Number(count.to_string()))),
1456 )
1457 .expect("select builder accepts LIMIT clauses")
1458 })
1459 }
1460
1461 pub fn offset(self, count: usize) -> Self {
1463 self.edit(|expression| {
1464 engine::apply_offset(
1465 expression,
1466 Expression::Literal(Box::new(Literal::Number(count.to_string()))),
1467 )
1468 .expect("select builder accepts OFFSET clauses")
1469 })
1470 }
1471
1472 pub fn distinct(self) -> Self {
1474 self.edit(|expression| {
1475 engine::apply_distinct(expression, true)
1476 .expect("select builder accepts DISTINCT clauses")
1477 })
1478 }
1479
1480 pub fn qualify(self, condition: Expr) -> Self {
1485 self.qualify_with_options(condition, ClauseOptions::default())
1486 }
1487
1488 pub fn qualify_with_options(self, condition: Expr, options: ClauseOptions) -> Self {
1490 self.edit(|expression| {
1491 engine::apply_qualify(expression, condition.0, options.append)
1492 .expect("select builder accepts QUALIFY clauses")
1493 })
1494 }
1495
1496 pub fn right_join(self, table_name: &str, on: Expr) -> Self {
1498 self.join_with_kind(table_name, Some(on), JoinKind::Right)
1499 }
1500
1501 pub fn full_join(self, table_name: &str, on: Expr) -> Self {
1503 self.join_with_kind(table_name, Some(on), JoinKind::Full)
1504 }
1505
1506 pub fn cross_join(self, table_name: &str) -> Self {
1508 self.join_with_kind(table_name, None, JoinKind::Cross)
1509 }
1510
1511 pub fn lateral_view<S: AsRef<str>>(
1518 self,
1519 table_function: Expr,
1520 table_alias: &str,
1521 column_aliases: impl IntoIterator<Item = S>,
1522 ) -> Self {
1523 self.lateral_view_with_options(
1524 table_function,
1525 table_alias,
1526 column_aliases,
1527 LateralViewOptions::default(),
1528 )
1529 }
1530
1531 pub fn lateral_view_with_options<S: AsRef<str>>(
1533 self,
1534 table_function: Expr,
1535 table_alias: &str,
1536 column_aliases: impl IntoIterator<Item = S>,
1537 options: LateralViewOptions,
1538 ) -> Self {
1539 let aliases = column_aliases
1540 .into_iter()
1541 .map(|c| builder_identifier(c.as_ref()))
1542 .collect();
1543 self.edit(|expression| {
1544 engine::append_lateral_view(
1545 expression,
1546 table_function.0,
1547 Some(builder_identifier(table_alias)),
1548 aliases,
1549 options.outer,
1550 )
1551 .expect("select builder accepts LATERAL VIEW clauses")
1552 })
1553 }
1554
1555 pub fn window(self, name: &str, def: WindowDefBuilder) -> Self {
1561 let order_by = def.order_by;
1562 self.edit(|expression| {
1563 engine::append_window(
1564 expression,
1565 builder_identifier(name),
1566 def.partition_by,
1567 order_by,
1568 )
1569 .expect("select builder accepts WINDOW clauses")
1570 })
1571 }
1572
1573 pub fn for_update(self) -> Self {
1578 self.edit(|expression| {
1579 engine::append_lock(expression, engine::LockKind::Update)
1580 .expect("select builder accepts locking clauses")
1581 })
1582 }
1583
1584 pub fn for_share(self) -> Self {
1589 self.edit(|expression| {
1590 engine::append_lock(expression, engine::LockKind::Share)
1591 .expect("select builder accepts locking clauses")
1592 })
1593 }
1594
1595 pub fn hint(self, hint_text: &str) -> Self {
1600 self.edit(|expression| {
1601 engine::append_hint(expression, hint_text.to_string())
1602 .expect("select builder accepts query hints")
1603 })
1604 }
1605
1606 pub fn ctas(self, table_name: &str) -> Expression {
1622 self.ctas_with_options(table_name, CtasOptions::default())
1623 }
1624
1625 pub fn ctas_with_options(self, table_name: &str, options: CtasOptions) -> Expression {
1627 engine::create_table_as(
1628 self.build(),
1629 builder_table_ref(table_name),
1630 options.replace,
1631 options.temporary,
1632 )
1633 .expect("select builder CTAS source is a query")
1634 }
1635
1636 pub fn union(self, other: SelectBuilder) -> SetOpBuilder {
1640 SetOpBuilder::new(SetOpKind::Union, self, other, false)
1641 }
1642
1643 pub fn union_all(self, other: SelectBuilder) -> SetOpBuilder {
1647 SetOpBuilder::new(SetOpKind::Union, self, other, true)
1648 }
1649
1650 pub fn intersect(self, other: SelectBuilder) -> SetOpBuilder {
1654 SetOpBuilder::new(SetOpKind::Intersect, self, other, false)
1655 }
1656
1657 pub fn except_(self, other: SelectBuilder) -> SetOpBuilder {
1661 SetOpBuilder::new(SetOpKind::Except, self, other, false)
1662 }
1663
1664 pub fn build(self) -> Expression {
1666 Expression::Select(Box::new(self.select))
1667 }
1668
1669 pub fn to_sql(self) -> String {
1674 generate_builder_sql(&self.build())
1675 }
1676}
1677
1678pub struct DeleteBuilder {
1687 delete: Delete,
1688}
1689
1690impl DeleteBuilder {
1691 pub fn where_(self, condition: Expr) -> Self {
1693 self.where_with_options(condition, ClauseOptions::default())
1694 }
1695
1696 pub fn where_with_options(mut self, condition: Expr, options: ClauseOptions) -> Self {
1698 let mut expression = Expression::Delete(Box::new(self.delete));
1699 engine::apply_where(&mut expression, condition.0, options.append)
1700 .expect("delete builder accepts WHERE clauses");
1701 self.delete = match expression {
1702 Expression::Delete(delete) => *delete,
1703 _ => unreachable!("delete builder engine changed the expression kind"),
1704 };
1705 self
1706 }
1707
1708 pub fn build(self) -> Expression {
1710 Expression::Delete(Box::new(self.delete))
1711 }
1712
1713 pub fn to_sql(self) -> String {
1715 generate_builder_sql(&self.build())
1716 }
1717}
1718
1719pub struct InsertBuilder {
1730 insert: Insert,
1731}
1732
1733impl InsertBuilder {
1734 fn edit(mut self, edit: impl FnOnce(&mut Expression)) -> Self {
1735 let mut expression = Expression::Insert(Box::new(self.insert));
1736 edit(&mut expression);
1737 self.insert = match expression {
1738 Expression::Insert(insert) => *insert,
1739 _ => unreachable!("insert builder engine changed the expression kind"),
1740 };
1741 self
1742 }
1743
1744 pub fn columns<I, S>(self, columns: I) -> Self
1746 where
1747 I: IntoIterator<Item = S>,
1748 S: AsRef<str>,
1749 {
1750 let columns = columns
1751 .into_iter()
1752 .map(|c| builder_identifier(c.as_ref()))
1753 .collect();
1754 self.edit(|expression| {
1755 engine::set_insert_columns(expression, columns)
1756 .expect("insert builder accepts target columns")
1757 })
1758 }
1759
1760 pub fn values<I>(self, values: I) -> Self
1764 where
1765 I: IntoIterator<Item = Expr>,
1766 {
1767 let row = values.into_iter().map(|v| v.0).collect();
1768 self.edit(|expression| {
1769 engine::apply_insert_values(expression, vec![row], true)
1770 .expect("insert builder accepts VALUES clauses")
1771 })
1772 }
1773
1774 pub fn query(self, query: SelectBuilder) -> Self {
1778 self.edit(|expression| {
1779 engine::set_insert_query(expression, query.build())
1780 .expect("insert builder accepts query sources")
1781 })
1782 }
1783
1784 pub fn build(self) -> Expression {
1786 Expression::Insert(Box::new(self.insert))
1787 }
1788
1789 pub fn to_sql(self) -> String {
1791 generate_builder_sql(&self.build())
1792 }
1793}
1794
1795pub struct UpdateBuilder {
1805 update: Update,
1806}
1807
1808impl UpdateBuilder {
1809 fn edit(mut self, edit: impl FnOnce(&mut Expression)) -> Self {
1810 let mut expression = Expression::Update(Box::new(self.update));
1811 edit(&mut expression);
1812 self.update = match expression {
1813 Expression::Update(update) => *update,
1814 _ => unreachable!("update builder engine changed the expression kind"),
1815 };
1816 self
1817 }
1818
1819 pub fn set(self, column: &str, value: Expr) -> Self {
1823 self.edit(|expression| {
1824 engine::append_update_assignments(
1825 expression,
1826 vec![(builder_identifier(column), value.0)],
1827 )
1828 .expect("update builder accepts SET assignments")
1829 })
1830 }
1831
1832 pub fn where_(self, condition: Expr) -> Self {
1834 self.where_with_options(condition, ClauseOptions::default())
1835 }
1836
1837 pub fn where_with_options(mut self, condition: Expr, options: ClauseOptions) -> Self {
1839 let mut expression = Expression::Update(Box::new(self.update));
1840 engine::apply_where(&mut expression, condition.0, options.append)
1841 .expect("update builder accepts WHERE clauses");
1842 self.update = match expression {
1843 Expression::Update(update) => *update,
1844 _ => unreachable!("update builder engine changed the expression kind"),
1845 };
1846 self
1847 }
1848
1849 pub fn from(self, table_name: &str) -> Self {
1853 self.edit(|expression| {
1854 engine::set_from(
1855 expression,
1856 vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1857 )
1858 .expect("update builder accepts FROM clauses")
1859 })
1860 }
1861
1862 pub fn build(self) -> Expression {
1864 Expression::Update(Box::new(self.update))
1865 }
1866
1867 pub fn to_sql(self) -> String {
1869 generate_builder_sql(&self.build())
1870 }
1871}
1872
1873pub fn case() -> CaseBuilder {
1898 CaseBuilder {
1899 operand: None,
1900 whens: Vec::new(),
1901 else_: None,
1902 }
1903}
1904
1905pub fn case_of(operand: Expr) -> CaseBuilder {
1926 CaseBuilder {
1927 operand: Some(operand.0),
1928 whens: Vec::new(),
1929 else_: None,
1930 }
1931}
1932
1933pub struct CaseBuilder {
1941 operand: Option<Expression>,
1942 whens: Vec<(Expression, Expression)>,
1943 else_: Option<Expression>,
1944}
1945
1946impl CaseBuilder {
1947 pub fn when(mut self, condition: Expr, result: Expr) -> Self {
1952 self.whens.push((condition.0, result.0));
1953 self
1954 }
1955
1956 pub fn else_(mut self, result: Expr) -> Self {
1961 self.else_ = Some(result.0);
1962 self
1963 }
1964
1965 pub fn build(self) -> Expr {
1967 Expr(self.build_expr())
1968 }
1969
1970 pub fn build_expr(self) -> Expression {
1975 let mut expression = engine::case(self.operand);
1976 for (condition, result) in self.whens {
1977 engine::append_case_when(&mut expression, condition, result)
1978 .expect("case builder accepts WHEN branches");
1979 }
1980 if let Some(result) = self.else_ {
1981 engine::set_case_else(&mut expression, result)
1982 .expect("case builder accepts ELSE branches");
1983 }
1984 expression
1985 }
1986}
1987
1988pub fn subquery(query: SelectBuilder, alias_name: &str) -> Expr {
2012 subquery_expr(query.build(), alias_name)
2013}
2014
2015pub fn subquery_expr(expr: Expression, alias_name: &str) -> Expr {
2020 Expr(
2021 engine::subquery(expr, Some(builder_identifier(alias_name)), true)
2022 .expect("subquery builder source is a query"),
2023 )
2024}
2025
2026#[derive(Debug, Clone, Copy)]
2032enum SetOpKind {
2033 Union,
2034 Intersect,
2035 Except,
2036}
2037
2038pub struct SetOpBuilder {
2059 kind: SetOpKind,
2060 left: Expression,
2061 right: Expression,
2062 all: bool,
2063 order_by: Option<OrderBy>,
2064 limit: Option<Box<Expression>>,
2065 offset: Option<Box<Expression>>,
2066}
2067
2068impl SetOpBuilder {
2069 fn new(kind: SetOpKind, left: SelectBuilder, right: SelectBuilder, all: bool) -> Self {
2070 SetOpBuilder {
2071 kind,
2072 left: left.build(),
2073 right: right.build(),
2074 all,
2075 order_by: None,
2076 limit: None,
2077 offset: None,
2078 }
2079 }
2080
2081 pub fn order_by<I, E>(self, expressions: I) -> Self
2086 where
2087 I: IntoIterator<Item = E>,
2088 E: IntoExpr,
2089 {
2090 self.order_by_with_options(expressions, ClauseOptions::default())
2091 }
2092
2093 pub fn order_by_with_options<I, E>(mut self, expressions: I, options: ClauseOptions) -> Self
2095 where
2096 I: IntoIterator<Item = E>,
2097 E: IntoExpr,
2098 {
2099 let values: Vec<_> = expressions
2100 .into_iter()
2101 .map(|expression| engine::ordered(expression.into_expr().0))
2102 .collect();
2103 if options.append {
2104 self.order_by
2105 .get_or_insert_with(|| OrderBy {
2106 siblings: false,
2107 comments: Vec::new(),
2108 expressions: Vec::new(),
2109 })
2110 .expressions
2111 .extend(values);
2112 } else {
2113 self.order_by = Some(OrderBy {
2114 siblings: false,
2115 comments: Vec::new(),
2116 expressions: values,
2117 });
2118 }
2119 self
2120 }
2121
2122 pub fn limit(mut self, count: usize) -> Self {
2124 self.limit = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2125 count.to_string(),
2126 )))));
2127 self
2128 }
2129
2130 pub fn offset(mut self, count: usize) -> Self {
2132 self.offset = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2133 count.to_string(),
2134 )))));
2135 self
2136 }
2137
2138 pub fn build(self) -> Expression {
2143 let kind = match self.kind {
2144 SetOpKind::Union => engine::SetKind::Union,
2145 SetOpKind::Intersect => engine::SetKind::Intersect,
2146 SetOpKind::Except => engine::SetKind::Except,
2147 };
2148 let mut expression = engine::set_operation(kind, self.left, self.right, !self.all)
2149 .expect("set builder operands are queries");
2150 if let Some(order_by) = self.order_by {
2151 engine::apply_order_by(&mut expression, order_by.expressions, false)
2152 .expect("set operations accept ORDER BY clauses");
2153 }
2154 if let Some(limit) = self.limit {
2155 engine::apply_limit(&mut expression, *limit)
2156 .expect("set operations accept LIMIT clauses");
2157 }
2158 if let Some(offset) = self.offset {
2159 engine::apply_offset(&mut expression, *offset)
2160 .expect("set operations accept OFFSET clauses");
2161 }
2162 expression
2163 }
2164
2165 pub fn to_sql(self) -> String {
2167 generate_builder_sql(&self.build())
2168 }
2169}
2170
2171pub fn union(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2175 SetOpBuilder::new(SetOpKind::Union, left, right, false)
2176}
2177
2178pub fn union_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2182 SetOpBuilder::new(SetOpKind::Union, left, right, true)
2183}
2184
2185pub fn intersect(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2189 SetOpBuilder::new(SetOpKind::Intersect, left, right, false)
2190}
2191
2192pub fn intersect_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2196 SetOpBuilder::new(SetOpKind::Intersect, left, right, true)
2197}
2198
2199pub fn except_(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2203 SetOpBuilder::new(SetOpKind::Except, left, right, false)
2204}
2205
2206pub fn except_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2210 SetOpBuilder::new(SetOpKind::Except, left, right, true)
2211}
2212
2213pub struct WindowDefBuilder {
2238 partition_by: Vec<Expression>,
2239 order_by: Vec<Ordered>,
2240}
2241
2242impl WindowDefBuilder {
2243 pub fn new() -> Self {
2245 WindowDefBuilder {
2246 partition_by: Vec::new(),
2247 order_by: Vec::new(),
2248 }
2249 }
2250
2251 pub fn partition_by<I, E>(mut self, expressions: I) -> Self
2253 where
2254 I: IntoIterator<Item = E>,
2255 E: IntoExpr,
2256 {
2257 self.partition_by = expressions.into_iter().map(|e| e.into_expr().0).collect();
2258 self
2259 }
2260
2261 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2266 where
2267 I: IntoIterator<Item = E>,
2268 E: IntoExpr,
2269 {
2270 self.order_by = expressions
2271 .into_iter()
2272 .map(|e| {
2273 let expr = e.into_expr().0;
2274 match expr {
2275 Expression::Ordered(o) => *o,
2276 other => Ordered {
2277 this: other,
2278 desc: false,
2279 nulls_first: None,
2280 explicit_asc: false,
2281 with_fill: None,
2282 },
2283 }
2284 })
2285 .collect();
2286 self
2287 }
2288}
2289
2290pub trait IntoExpr {
2309 fn into_expr(self) -> Expr;
2311}
2312
2313impl IntoExpr for Expr {
2314 fn into_expr(self) -> Expr {
2315 self
2316 }
2317}
2318
2319impl IntoExpr for &str {
2320 fn into_expr(self) -> Expr {
2322 col(self)
2323 }
2324}
2325
2326impl IntoExpr for String {
2327 fn into_expr(self) -> Expr {
2329 col(&self)
2330 }
2331}
2332
2333impl IntoExpr for Expression {
2334 fn into_expr(self) -> Expr {
2336 Expr(self)
2337 }
2338}
2339
2340pub trait IntoLiteral {
2355 fn into_literal(self) -> Expr;
2357}
2358
2359impl IntoLiteral for &str {
2360 fn into_literal(self) -> Expr {
2362 Expr(Expression::Literal(Box::new(Literal::String(
2363 self.to_string(),
2364 ))))
2365 }
2366}
2367
2368impl IntoLiteral for String {
2369 fn into_literal(self) -> Expr {
2371 Expr(Expression::Literal(Box::new(Literal::String(self))))
2372 }
2373}
2374
2375impl IntoLiteral for i64 {
2376 fn into_literal(self) -> Expr {
2378 Expr(Expression::Literal(Box::new(Literal::Number(
2379 self.to_string(),
2380 ))))
2381 }
2382}
2383
2384impl IntoLiteral for i32 {
2385 fn into_literal(self) -> Expr {
2387 Expr(Expression::Literal(Box::new(Literal::Number(
2388 self.to_string(),
2389 ))))
2390 }
2391}
2392
2393impl IntoLiteral for usize {
2394 fn into_literal(self) -> Expr {
2396 Expr(Expression::Literal(Box::new(Literal::Number(
2397 self.to_string(),
2398 ))))
2399 }
2400}
2401
2402impl IntoLiteral for f64 {
2403 fn into_literal(self) -> Expr {
2405 Expr(Expression::Literal(Box::new(Literal::Number(
2406 self.to_string(),
2407 ))))
2408 }
2409}
2410
2411impl IntoLiteral for bool {
2412 fn into_literal(self) -> Expr {
2414 Expr(Expression::Boolean(BooleanLiteral { value: self }))
2415 }
2416}
2417
2418pub fn merge_into(target: &str) -> MergeBuilder {
2440 MergeBuilder {
2441 expression: engine::merge(Expression::Table(Box::new(builder_table_ref(target)))),
2442 }
2443}
2444
2445pub struct MergeBuilder {
2449 expression: Expression,
2450}
2451
2452impl MergeBuilder {
2453 pub fn using(mut self, source: &str, on: Expr) -> Self {
2455 engine::set_merge_using(
2456 &mut self.expression,
2457 Expression::Table(Box::new(builder_table_ref(source))),
2458 on.0,
2459 )
2460 .expect("merge builder accepts a USING clause");
2461 self
2462 }
2463
2464 pub fn when_matched_update(mut self, assignments: Vec<(&str, Expr)>) -> Self {
2466 let assignments = assignments
2467 .into_iter()
2468 .map(|(column, value)| (builder_identifier(column), value.0))
2469 .collect();
2470 engine::append_merge_update(&mut self.expression, assignments, None)
2471 .expect("merge builder accepts matched update actions");
2472 self
2473 }
2474
2475 pub fn when_matched_update_where(
2477 mut self,
2478 condition: Expr,
2479 assignments: Vec<(&str, Expr)>,
2480 ) -> Self {
2481 let assignments = assignments
2482 .into_iter()
2483 .map(|(column, value)| (builder_identifier(column), value.0))
2484 .collect();
2485 engine::append_merge_update(&mut self.expression, assignments, Some(condition.0))
2486 .expect("merge builder accepts conditional matched update actions");
2487 self
2488 }
2489
2490 pub fn when_matched_delete(mut self) -> Self {
2492 engine::append_merge_delete(&mut self.expression, None)
2493 .expect("merge builder accepts matched delete actions");
2494 self
2495 }
2496
2497 pub fn when_matched_delete_where(mut self, condition: Expr) -> Self {
2499 engine::append_merge_delete(&mut self.expression, Some(condition.0))
2500 .expect("merge builder accepts conditional matched delete actions");
2501 self
2502 }
2503
2504 pub fn when_not_matched_insert(mut self, columns: &[&str], values: Vec<Expr>) -> Self {
2506 engine::append_merge_insert(
2507 &mut self.expression,
2508 columns
2509 .iter()
2510 .map(|column| builder_identifier(column))
2511 .collect(),
2512 values.into_iter().map(|value| value.0).collect(),
2513 None,
2514 )
2515 .expect("merge builder accepts not-matched insert actions");
2516 self
2517 }
2518
2519 pub fn when_not_matched_insert_where(
2521 mut self,
2522 condition: Expr,
2523 columns: &[&str],
2524 values: Vec<Expr>,
2525 ) -> Self {
2526 engine::append_merge_insert(
2527 &mut self.expression,
2528 columns
2529 .iter()
2530 .map(|column| builder_identifier(column))
2531 .collect(),
2532 values.into_iter().map(|value| value.0).collect(),
2533 Some(condition.0),
2534 )
2535 .expect("merge builder accepts conditional not-matched insert actions");
2536 self
2537 }
2538
2539 pub fn build(self) -> Expression {
2541 self.expression
2542 }
2543
2544 pub fn to_sql(self) -> String {
2546 generate_builder_sql(&self.build())
2547 }
2548}
2549
2550fn parse_simple_data_type(name: &str) -> DataType {
2551 let upper = name.trim().to_uppercase();
2552 match upper.as_str() {
2553 "INT" | "INTEGER" => DataType::Int {
2554 length: None,
2555 integer_spelling: upper == "INTEGER",
2556 },
2557 "BIGINT" => DataType::BigInt { length: None },
2558 "SMALLINT" => DataType::SmallInt { length: None },
2559 "TINYINT" => DataType::TinyInt { length: None },
2560 "FLOAT" => DataType::Float {
2561 precision: None,
2562 scale: None,
2563 real_spelling: false,
2564 },
2565 "DOUBLE" => DataType::Double {
2566 precision: None,
2567 scale: None,
2568 },
2569 "BOOLEAN" | "BOOL" => DataType::Boolean,
2570 "TEXT" => DataType::Text,
2571 "DATE" => DataType::Date,
2572 "TIMESTAMP" => DataType::Timestamp {
2573 precision: None,
2574 timezone: false,
2575 },
2576 "VARCHAR" => DataType::VarChar {
2577 length: None,
2578 parenthesized_length: false,
2579 },
2580 "CHAR" => DataType::Char { length: None },
2581 _ => {
2582 if let Ok(ast) =
2584 crate::parser::Parser::parse_sql(&format!("SELECT CAST(x AS {})", name))
2585 {
2586 if let Expression::Select(s) = &ast[0] {
2587 if let Some(Expression::Cast(c)) = s.expressions.first() {
2588 return c.to.clone();
2589 }
2590 }
2591 }
2592 DataType::Custom {
2594 name: name.to_string(),
2595 }
2596 }
2597 }
2598}
2599
2600#[cfg(test)]
2601mod tests {
2602 use super::*;
2603
2604 #[test]
2605 fn test_simple_select() {
2606 let sql = select(["id", "name"]).from("users").to_sql();
2607 assert_eq!(sql, "SELECT id, name FROM users");
2608 }
2609
2610 #[test]
2611 fn test_builder_quotes_unsafe_identifier_tokens() {
2612 let sql = select(["Name; DROP TABLE titanic"]).to_sql();
2613 assert_eq!(sql, r#"SELECT "Name; DROP TABLE titanic""#);
2614 }
2615
2616 #[test]
2617 fn test_builder_string_literal_requires_lit() {
2618 let sql = select([lit("Name; DROP TABLE titanic")]).to_sql();
2619 assert_eq!(sql, "SELECT 'Name; DROP TABLE titanic'");
2620 }
2621
2622 #[test]
2623 fn test_builder_quotes_unsafe_table_name_tokens() {
2624 let sql = select(["id"]).from("users; DROP TABLE x").to_sql();
2625 assert_eq!(sql, r#"SELECT id FROM "users; DROP TABLE x""#);
2626 }
2627
2628 #[test]
2629 fn test_select_star() {
2630 let sql = select([star()]).from("users").to_sql();
2631 assert_eq!(sql, "SELECT * FROM users");
2632 }
2633
2634 #[test]
2635 fn test_select_with_where() {
2636 let sql = select(["id", "name"])
2637 .from("users")
2638 .where_(col("age").gt(lit(18)))
2639 .to_sql();
2640 assert_eq!(sql, "SELECT id, name FROM users WHERE age > 18");
2641 }
2642
2643 #[test]
2644 fn test_select_with_join() {
2645 let sql = select(["u.id", "o.amount"])
2646 .from("users")
2647 .join("orders", col("u.id").eq(col("o.user_id")))
2648 .to_sql();
2649 assert_eq!(
2650 sql,
2651 "SELECT u.id, o.amount FROM users JOIN orders ON u.id = o.user_id"
2652 );
2653 }
2654
2655 #[test]
2656 fn test_select_with_group_by_having() {
2657 let sql = select([col("dept"), func("COUNT", [star()]).alias("cnt")])
2658 .from("employees")
2659 .group_by(["dept"])
2660 .having(func("COUNT", [star()]).gt(lit(5)))
2661 .to_sql();
2662 assert_eq!(
2663 sql,
2664 "SELECT dept, COUNT(*) AS cnt FROM employees GROUP BY dept HAVING COUNT(*) > 5"
2665 );
2666 }
2667
2668 #[test]
2669 fn test_select_with_order_limit_offset() {
2670 let sql = select(["id", "name"])
2671 .from("users")
2672 .order_by(["name"])
2673 .limit(10)
2674 .offset(20)
2675 .to_sql();
2676 assert_eq!(
2677 sql,
2678 "SELECT id, name FROM users ORDER BY name LIMIT 10 OFFSET 20"
2679 );
2680 }
2681
2682 #[test]
2683 fn test_select_distinct() {
2684 let sql = select(["name"]).from("users").distinct().to_sql();
2685 assert_eq!(sql, "SELECT DISTINCT name FROM users");
2686 }
2687
2688 #[test]
2689 fn test_insert_values() {
2690 let sql = insert_into("users")
2691 .columns(["id", "name"])
2692 .values([lit(1), lit("Alice")])
2693 .values([lit(2), lit("Bob")])
2694 .to_sql();
2695 assert_eq!(
2696 sql,
2697 "INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob')"
2698 );
2699 }
2700
2701 #[test]
2702 fn test_insert_select() {
2703 let sql = insert_into("archive")
2704 .columns(["id", "name"])
2705 .query(select(["id", "name"]).from("users"))
2706 .to_sql();
2707 assert_eq!(
2708 sql,
2709 "INSERT INTO archive (id, name) SELECT id, name FROM users"
2710 );
2711 }
2712
2713 #[test]
2714 fn test_update() {
2715 let sql = update("users")
2716 .set("name", lit("Bob"))
2717 .set("age", lit(30))
2718 .where_(col("id").eq(lit(1)))
2719 .to_sql();
2720 assert_eq!(sql, "UPDATE users SET name = 'Bob', age = 30 WHERE id = 1");
2721 }
2722
2723 #[test]
2724 fn test_delete() {
2725 let sql = delete("users").where_(col("id").eq(lit(1))).to_sql();
2726 assert_eq!(sql, "DELETE FROM users WHERE id = 1");
2727 }
2728
2729 #[test]
2730 fn test_complex_where() {
2731 let sql = select(["id"])
2732 .from("users")
2733 .where_(
2734 col("age")
2735 .gte(lit(18))
2736 .and(col("active").eq(boolean(true)))
2737 .and(col("name").like(lit("%test%"))),
2738 )
2739 .to_sql();
2740 assert_eq!(
2741 sql,
2742 "SELECT id FROM users WHERE age >= 18 AND active = TRUE AND name LIKE '%test%'"
2743 );
2744 }
2745
2746 #[test]
2747 fn test_in_list() {
2748 let sql = select(["id"])
2749 .from("users")
2750 .where_(col("status").in_list([lit("active"), lit("pending")]))
2751 .to_sql();
2752 assert_eq!(
2753 sql,
2754 "SELECT id FROM users WHERE status IN ('active', 'pending')"
2755 );
2756 }
2757
2758 #[test]
2759 fn test_between() {
2760 let sql = select(["id"])
2761 .from("orders")
2762 .where_(col("amount").between(lit(100), lit(500)))
2763 .to_sql();
2764 assert_eq!(
2765 sql,
2766 "SELECT id FROM orders WHERE amount BETWEEN 100 AND 500"
2767 );
2768 }
2769
2770 #[test]
2771 fn test_is_null() {
2772 let sql = select(["id"])
2773 .from("users")
2774 .where_(col("email").is_null())
2775 .to_sql();
2776 assert_eq!(sql, "SELECT id FROM users WHERE email IS NULL");
2777 }
2778
2779 #[test]
2780 fn test_arithmetic() {
2781 let sql = select([col("price").mul(col("quantity")).alias("total")])
2782 .from("items")
2783 .to_sql();
2784 assert_eq!(sql, "SELECT price * quantity AS total FROM items");
2785 }
2786
2787 #[test]
2788 fn test_nested_operator_grouping() {
2789 assert_eq!(
2790 or(col("a").eq(lit(1)), col("b").eq(lit(2)))
2791 .and(col("c").eq(lit(3)))
2792 .to_sql(),
2793 "(a = 1 OR b = 2) AND c = 3"
2794 );
2795 assert_eq!(
2796 col("a")
2797 .eq(lit(1))
2798 .and(or(col("b").eq(lit(2)), col("c").eq(lit(3))))
2799 .to_sql(),
2800 "a = 1 AND (b = 2 OR c = 3)"
2801 );
2802 assert_eq!(col("a").add(col("b")).mul(col("c")).to_sql(), "(a + b) * c");
2803 assert_eq!(col("a").mul(col("b").add(col("c"))).to_sql(), "a * (b + c)");
2804 assert_eq!(col("a").sub(col("b").sub(col("c"))).to_sql(), "a - (b - c)");
2805 assert_eq!(col("a").div(col("b").div(col("c"))).to_sql(), "a / (b / c)");
2806 }
2807
2808 #[test]
2809 fn test_cast() {
2810 let sql = select([col("id").cast("VARCHAR")]).from("users").to_sql();
2811 assert_eq!(sql, "SELECT CAST(id AS VARCHAR) FROM users");
2812 }
2813
2814 #[test]
2815 fn test_from_starter() {
2816 let sql = from("users").select_cols(["id", "name"]).to_sql();
2817 assert_eq!(sql, "SELECT id, name FROM users");
2818 }
2819
2820 #[test]
2821 fn test_qualified_column() {
2822 let sql = select([col("u.id"), col("u.name")]).from("users").to_sql();
2823 assert_eq!(sql, "SELECT u.id, u.name FROM users");
2824 }
2825
2826 #[test]
2827 fn test_nested_dot_column() {
2828 let sql = select([col("t.s.f")]).from("users").to_sql();
2829 assert_eq!(sql, "SELECT t.s.f FROM users");
2830 }
2831
2832 #[test]
2833 fn test_not_condition() {
2834 let sql = select(["id"])
2835 .from("users")
2836 .where_(not(col("active").eq(boolean(true))))
2837 .to_sql();
2838 assert_eq!(sql, "SELECT id FROM users WHERE NOT active = TRUE");
2839 }
2840
2841 #[test]
2842 fn test_order_by_desc() {
2843 let sql = select(["id", "name"])
2844 .from("users")
2845 .order_by([col("name").desc()])
2846 .to_sql();
2847 assert_eq!(sql, "SELECT id, name FROM users ORDER BY name DESC");
2848 }
2849
2850 #[test]
2851 fn test_left_join() {
2852 let sql = select(["u.id", "o.amount"])
2853 .from("users")
2854 .left_join("orders", col("u.id").eq(col("o.user_id")))
2855 .to_sql();
2856 assert_eq!(
2857 sql,
2858 "SELECT u.id, o.amount FROM users LEFT JOIN orders ON u.id = o.user_id"
2859 );
2860 }
2861
2862 #[test]
2863 fn test_build_returns_expression() {
2864 let expr = select(["id"]).from("users").build();
2865 assert!(matches!(expr, Expression::Select(_)));
2866 }
2867
2868 #[test]
2869 fn test_expr_interop() {
2870 let age_check = col("age").gt(lit(18));
2872 let sql = select([col("id"), age_check.alias("is_adult")])
2873 .from("users")
2874 .to_sql();
2875 assert_eq!(sql, "SELECT id, age > 18 AS is_adult FROM users");
2876 }
2877
2878 #[test]
2881 fn test_sql_expr_simple() {
2882 let expr = sql_expr("age > 18");
2883 let sql = select(["id"]).from("users").where_(expr).to_sql();
2884 assert_eq!(sql, "SELECT id FROM users WHERE age > 18");
2885 }
2886
2887 #[test]
2888 fn test_sql_expr_compound() {
2889 let expr = sql_expr("a > 1 AND b < 10");
2890 let sql = select(["*"]).from("t").where_(expr).to_sql();
2891 assert_eq!(sql, "SELECT * FROM t WHERE a > 1 AND b < 10");
2892 }
2893
2894 #[test]
2895 fn test_sql_expr_function() {
2896 let expr = sql_expr("COALESCE(a, b, 0)");
2897 let sql = select([expr.alias("val")]).from("t").to_sql();
2898 assert_eq!(sql, "SELECT COALESCE(a, b, 0) AS val FROM t");
2899 }
2900
2901 #[test]
2902 fn test_condition_alias() {
2903 let cond = condition("x > 0");
2904 let sql = select(["*"]).from("t").where_(cond).to_sql();
2905 assert_eq!(sql, "SELECT * FROM t WHERE x > 0");
2906 }
2907
2908 #[test]
2911 fn test_ilike() {
2912 let sql = select(["id"])
2913 .from("users")
2914 .where_(col("name").ilike(lit("%test%")))
2915 .to_sql();
2916 assert_eq!(sql, "SELECT id FROM users WHERE name ILIKE '%test%'");
2917 }
2918
2919 #[test]
2920 fn test_rlike() {
2921 let sql = select(["id"])
2922 .from("users")
2923 .where_(col("name").rlike(lit("^[A-Z]")))
2924 .to_sql();
2925 assert_eq!(
2926 sql,
2927 "SELECT id FROM users WHERE REGEXP_LIKE(name, '^[A-Z]')"
2928 );
2929 }
2930
2931 #[test]
2932 fn test_not_in() {
2933 let sql = select(["id"])
2934 .from("users")
2935 .where_(col("status").not_in([lit("deleted"), lit("banned")]))
2936 .to_sql();
2937 assert_eq!(
2938 sql,
2939 "SELECT id FROM users WHERE status NOT IN ('deleted', 'banned')"
2940 );
2941 }
2942
2943 #[test]
2944 fn repeated_clauses_append_unless_replacement_is_requested() {
2945 let appended = select(["x"])
2946 .where_(col("x").gt(lit(0)))
2947 .where_(col("x").lt(lit(10)))
2948 .group_by(["x"])
2949 .group_by(["y"])
2950 .to_sql();
2951 assert_eq!(appended, "SELECT x WHERE x > 0 AND x < 10 GROUP BY x, y");
2952
2953 let replaced = select(["x"])
2954 .where_(col("x").gt(lit(0)))
2955 .where_with_options(col("x").eq(lit(5)), ClauseOptions { append: false })
2956 .group_by(["x"])
2957 .group_by_with_options(["y"], ClauseOptions { append: false })
2958 .to_sql();
2959 assert_eq!(replaced, "SELECT x WHERE x = 5 GROUP BY y");
2960 }
2961
2962 #[test]
2965 fn test_case_searched() {
2966 let expr = case()
2967 .when(col("x").gt(lit(0)), lit("positive"))
2968 .when(col("x").eq(lit(0)), lit("zero"))
2969 .else_(lit("negative"))
2970 .build();
2971 let sql = select([expr.alias("label")]).from("t").to_sql();
2972 assert_eq!(
2973 sql,
2974 "SELECT CASE WHEN x > 0 THEN 'positive' WHEN x = 0 THEN 'zero' ELSE 'negative' END AS label FROM t"
2975 );
2976 }
2977
2978 #[test]
2979 fn test_case_simple() {
2980 let expr = case_of(col("status"))
2981 .when(lit(1), lit("active"))
2982 .when(lit(0), lit("inactive"))
2983 .build();
2984 let sql = select([expr.alias("status_label")]).from("t").to_sql();
2985 assert_eq!(
2986 sql,
2987 "SELECT CASE status WHEN 1 THEN 'active' WHEN 0 THEN 'inactive' END AS status_label FROM t"
2988 );
2989 }
2990
2991 #[test]
2992 fn test_case_no_else() {
2993 let expr = case().when(col("x").gt(lit(0)), lit("yes")).build();
2994 let sql = select([expr]).from("t").to_sql();
2995 assert_eq!(sql, "SELECT CASE WHEN x > 0 THEN 'yes' END FROM t");
2996 }
2997
2998 #[test]
3001 fn test_subquery_in_from() {
3002 let inner = select(["id", "name"])
3003 .from("users")
3004 .where_(col("active").eq(boolean(true)));
3005 let outer = select(["sub.id"])
3006 .from_expr(subquery(inner, "sub"))
3007 .to_sql();
3008 assert_eq!(
3009 outer,
3010 "SELECT sub.id FROM (SELECT id, name FROM users WHERE active = TRUE) AS sub"
3011 );
3012 }
3013
3014 #[test]
3015 fn test_subquery_in_join() {
3016 let inner = select([col("user_id"), func("SUM", [col("amount")]).alias("total")])
3017 .from("orders")
3018 .group_by(["user_id"]);
3019 let sql = select(["u.name", "o.total"])
3020 .from("users")
3021 .join("orders", col("u.id").eq(col("o.user_id")))
3022 .to_sql();
3023 assert!(sql.contains("JOIN"));
3024 let _sub = subquery(inner, "o");
3026 }
3027
3028 #[test]
3031 fn test_union() {
3032 let sql = union(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3033 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3034 }
3035
3036 #[test]
3037 fn test_union_all() {
3038 let sql = union_all(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3039 assert_eq!(sql, "SELECT id FROM a UNION ALL SELECT id FROM b");
3040 }
3041
3042 #[test]
3043 fn test_intersect_builder() {
3044 let sql = intersect(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3045 assert_eq!(sql, "SELECT id FROM a INTERSECT SELECT id FROM b");
3046 }
3047
3048 #[test]
3049 fn test_except_builder() {
3050 let sql = except_(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3051 assert_eq!(sql, "SELECT id FROM a EXCEPT SELECT id FROM b");
3052 }
3053
3054 #[test]
3055 fn test_union_with_order_limit() {
3056 let sql = union(select(["id"]).from("a"), select(["id"]).from("b"))
3057 .order_by(["id"])
3058 .limit(10)
3059 .to_sql();
3060 assert!(sql.contains("UNION"));
3061 assert!(sql.contains("ORDER BY"));
3062 assert!(sql.contains("LIMIT"));
3063 }
3064
3065 #[test]
3066 fn test_select_builder_union() {
3067 let sql = select(["id"])
3068 .from("a")
3069 .union(select(["id"]).from("b"))
3070 .to_sql();
3071 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3072 }
3073
3074 #[test]
3077 fn test_qualify() {
3078 let sql = select(["id", "name"])
3079 .from("users")
3080 .qualify(col("rn").eq(lit(1)))
3081 .to_sql();
3082 assert_eq!(sql, "SELECT id, name FROM users QUALIFY rn = 1");
3083 }
3084
3085 #[test]
3086 fn test_right_join() {
3087 let sql = select(["u.id", "o.amount"])
3088 .from("users")
3089 .right_join("orders", col("u.id").eq(col("o.user_id")))
3090 .to_sql();
3091 assert_eq!(
3092 sql,
3093 "SELECT u.id, o.amount FROM users RIGHT JOIN orders ON u.id = o.user_id"
3094 );
3095 }
3096
3097 #[test]
3098 fn test_cross_join() {
3099 let sql = select(["a.x", "b.y"]).from("a").cross_join("b").to_sql();
3100 assert_eq!(sql, "SELECT a.x, b.y FROM a CROSS JOIN b");
3101 }
3102
3103 #[test]
3104 fn test_lateral_view() {
3105 let sql = select(["id", "col_val"])
3106 .from("t")
3107 .lateral_view(func("EXPLODE", [col("arr")]), "lv", ["col_val"])
3108 .to_sql();
3109 assert!(sql.contains("LATERAL VIEW"));
3110 assert!(sql.contains("EXPLODE"));
3111
3112 let expression = select(["id"])
3113 .from("t")
3114 .lateral_view_with_options(
3115 func("EXPLODE", [col("arr")]),
3116 "lv",
3117 ["value"],
3118 LateralViewOptions { outer: true },
3119 )
3120 .build();
3121 let Expression::Select(select) = expression else {
3122 panic!("expected SELECT")
3123 };
3124 assert!(select.lateral_views[0].outer);
3125 }
3126
3127 #[test]
3128 fn test_window_clause() {
3129 let sql = select(["id"])
3130 .from("t")
3131 .window(
3132 "w",
3133 WindowDefBuilder::new()
3134 .partition_by(["dept"])
3135 .order_by(["salary"]),
3136 )
3137 .to_sql();
3138 assert!(sql.contains("WINDOW"));
3139 assert!(sql.contains("PARTITION BY"));
3140 }
3141
3142 #[test]
3145 fn test_xor() {
3146 let sql = select(["*"])
3147 .from("t")
3148 .where_(col("a").xor(col("b")))
3149 .to_sql();
3150 assert_eq!(sql, "SELECT * FROM t WHERE a XOR b");
3151 }
3152
3153 #[test]
3156 fn test_for_update() {
3157 let sql = select(["id"]).from("t").for_update().to_sql();
3158 assert_eq!(sql, "SELECT id FROM t FOR UPDATE");
3159 }
3160
3161 #[test]
3162 fn test_for_share() {
3163 let sql = select(["id"]).from("t").for_share().to_sql();
3164 assert_eq!(sql, "SELECT id FROM t FOR SHARE");
3165 }
3166
3167 #[test]
3170 fn test_hint() {
3171 let sql = select(["*"]).from("t").hint("FULL(t)").to_sql();
3172 assert!(sql.contains("FULL(t)"), "Expected hint in: {}", sql);
3173 }
3174
3175 #[test]
3178 fn test_ctas() {
3179 let expr = select(["*"]).from("t").ctas("new_table");
3180 let sql = Generator::sql(&expr).unwrap();
3181 assert_eq!(sql, "CREATE TABLE new_table AS SELECT * FROM t");
3182
3183 let expr = select(["*"]).from("t").ctas_with_options(
3184 "new_table",
3185 CtasOptions {
3186 replace: true,
3187 temporary: true,
3188 },
3189 );
3190 let Expression::CreateTable(create) = expr else {
3191 panic!("expected CREATE TABLE")
3192 };
3193 assert!(create.or_replace);
3194 assert!(create.temporary);
3195 }
3196
3197 #[test]
3200 fn test_merge_update_insert() {
3201 let sql = merge_into("target")
3202 .using("source", col("target.id").eq(col("source.id")))
3203 .when_matched_update(vec![("name", col("source.name"))])
3204 .when_not_matched_insert(&["id", "name"], vec![col("source.id"), col("source.name")])
3205 .to_sql();
3206 assert!(
3207 sql.contains("MERGE INTO"),
3208 "Expected MERGE INTO in: {}",
3209 sql
3210 );
3211 assert!(sql.contains("USING"), "Expected USING in: {}", sql);
3212 assert!(
3213 sql.contains("WHEN MATCHED"),
3214 "Expected WHEN MATCHED in: {}",
3215 sql
3216 );
3217 assert!(
3218 sql.contains("UPDATE SET"),
3219 "Expected UPDATE SET in: {}",
3220 sql
3221 );
3222 assert!(
3223 sql.contains("WHEN NOT MATCHED"),
3224 "Expected WHEN NOT MATCHED in: {}",
3225 sql
3226 );
3227 assert!(sql.contains("INSERT"), "Expected INSERT in: {}", sql);
3228 }
3229
3230 #[test]
3231 fn test_merge_delete() {
3232 let sql = merge_into("target")
3233 .using("source", col("target.id").eq(col("source.id")))
3234 .when_matched_delete()
3235 .to_sql();
3236 assert!(
3237 sql.contains("MERGE INTO"),
3238 "Expected MERGE INTO in: {}",
3239 sql
3240 );
3241 assert!(
3242 sql.contains("WHEN MATCHED THEN DELETE"),
3243 "Expected WHEN MATCHED THEN DELETE in: {}",
3244 sql
3245 );
3246 }
3247
3248 #[test]
3249 fn test_merge_with_condition() {
3250 let sql = merge_into("target")
3251 .using("source", col("target.id").eq(col("source.id")))
3252 .when_matched_update_where(
3253 col("source.active").eq(boolean(true)),
3254 vec![("name", col("source.name"))],
3255 )
3256 .to_sql();
3257 assert!(
3258 sql.contains("MERGE INTO"),
3259 "Expected MERGE INTO in: {}",
3260 sql
3261 );
3262 assert!(
3263 sql.contains("AND source.active = TRUE"),
3264 "Expected condition in: {}",
3265 sql
3266 );
3267 }
3268}