1pub mod plan;
59
60use crate::ast_mutation as engine;
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 inferred_type: None,
556 })))
557}
558
559pub fn ltrim(expr: Expr) -> Expr {
561 Expr(Expression::LTrim(Box::new(UnaryFunc::new(expr.0))))
562}
563
564pub fn rtrim(expr: Expr) -> Expr {
566 Expr(Expression::RTrim(Box::new(UnaryFunc::new(expr.0))))
567}
568
569pub fn reverse(expr: Expr) -> Expr {
571 Expr(Expression::Reverse(Box::new(UnaryFunc::new(expr.0))))
572}
573
574pub fn initcap(expr: Expr) -> Expr {
576 Expr(Expression::Initcap(Box::new(UnaryFunc::new(expr.0))))
577}
578
579pub fn substring(expr: Expr, start: Expr, len: Option<Expr>) -> Expr {
581 Expr(Expression::Substring(Box::new(SubstringFunc {
582 this: expr.0,
583 start: start.0,
584 length: len.map(|l| l.0),
585 from_for_syntax: false,
586 })))
587}
588
589pub fn replace_(expr: Expr, old: Expr, new: Expr) -> Expr {
592 Expr(Expression::Replace(Box::new(ReplaceFunc {
593 this: expr.0,
594 old: old.0,
595 new: new.0,
596 })))
597}
598
599pub fn concat_ws(separator: Expr, exprs: impl IntoIterator<Item = Expr>) -> Expr {
601 Expr(Expression::ConcatWs(Box::new(ConcatWs {
602 separator: separator.0,
603 expressions: exprs.into_iter().map(|e| e.0).collect(),
604 })))
605}
606
607pub fn coalesce(exprs: impl IntoIterator<Item = Expr>) -> Expr {
611 Expr(Expression::Coalesce(Box::new(VarArgFunc {
612 expressions: exprs.into_iter().map(|e| e.0).collect(),
613 original_name: None,
614 inferred_type: None,
615 })))
616}
617
618pub fn null_if(expr1: Expr, expr2: Expr) -> Expr {
620 Expr(Expression::NullIf(Box::new(BinaryFunc {
621 this: expr1.0,
622 expression: expr2.0,
623 original_name: None,
624 inferred_type: None,
625 })))
626}
627
628pub fn if_null(expr: Expr, fallback: Expr) -> Expr {
630 Expr(Expression::IfNull(Box::new(BinaryFunc {
631 this: expr.0,
632 expression: fallback.0,
633 original_name: None,
634 inferred_type: None,
635 })))
636}
637
638pub fn abs(expr: Expr) -> Expr {
642 Expr(Expression::Abs(Box::new(UnaryFunc::new(expr.0))))
643}
644
645pub fn round(expr: Expr, decimals: Option<Expr>) -> Expr {
647 Expr(Expression::Round(Box::new(RoundFunc {
648 this: expr.0,
649 decimals: decimals.map(|d| d.0),
650 })))
651}
652
653pub fn floor(expr: Expr) -> Expr {
655 Expr(Expression::Floor(Box::new(FloorFunc {
656 this: expr.0,
657 scale: None,
658 to: None,
659 })))
660}
661
662pub fn ceil(expr: Expr) -> Expr {
664 Expr(Expression::Ceil(Box::new(CeilFunc {
665 this: expr.0,
666 decimals: None,
667 to: None,
668 })))
669}
670
671pub fn power(base: Expr, exponent: Expr) -> Expr {
673 Expr(Expression::Power(Box::new(BinaryFunc {
674 this: base.0,
675 expression: exponent.0,
676 original_name: None,
677 inferred_type: None,
678 })))
679}
680
681pub fn sqrt(expr: Expr) -> Expr {
683 Expr(Expression::Sqrt(Box::new(UnaryFunc::new(expr.0))))
684}
685
686pub fn ln(expr: Expr) -> Expr {
688 Expr(Expression::Ln(Box::new(UnaryFunc::new(expr.0))))
689}
690
691pub fn exp_(expr: Expr) -> Expr {
693 Expr(Expression::Exp(Box::new(UnaryFunc::new(expr.0))))
694}
695
696pub fn sign(expr: Expr) -> Expr {
698 Expr(Expression::Sign(Box::new(UnaryFunc::new(expr.0))))
699}
700
701pub fn greatest(exprs: impl IntoIterator<Item = Expr>) -> Expr {
703 Expr(Expression::Greatest(Box::new(VarArgFunc {
704 expressions: exprs.into_iter().map(|e| e.0).collect(),
705 original_name: None,
706 inferred_type: None,
707 })))
708}
709
710pub fn least(exprs: impl IntoIterator<Item = Expr>) -> Expr {
712 Expr(Expression::Least(Box::new(VarArgFunc {
713 expressions: exprs.into_iter().map(|e| e.0).collect(),
714 original_name: None,
715 inferred_type: None,
716 })))
717}
718
719pub fn current_date_() -> Expr {
723 Expr(Expression::CurrentDate(CurrentDate))
724}
725
726pub fn current_time_() -> Expr {
728 Expr(Expression::CurrentTime(CurrentTime { precision: None }))
729}
730
731pub fn current_timestamp_() -> Expr {
733 Expr(Expression::CurrentTimestamp(CurrentTimestamp {
734 precision: None,
735 sysdate: false,
736 }))
737}
738
739pub fn extract_(field: &str, expr: Expr) -> Expr {
741 Expr(Expression::Extract(Box::new(ExtractFunc {
742 this: expr.0,
743 field: parse_datetime_field(field),
744 })))
745}
746
747fn parse_datetime_field(field: &str) -> DateTimeField {
749 match field.to_uppercase().as_str() {
750 "YEAR" => DateTimeField::Year,
751 "MONTH" => DateTimeField::Month,
752 "DAY" => DateTimeField::Day,
753 "HOUR" => DateTimeField::Hour,
754 "MINUTE" => DateTimeField::Minute,
755 "SECOND" => DateTimeField::Second,
756 "MILLISECOND" => DateTimeField::Millisecond,
757 "MICROSECOND" => DateTimeField::Microsecond,
758 "DOW" | "DAYOFWEEK" => DateTimeField::DayOfWeek,
759 "DOY" | "DAYOFYEAR" => DateTimeField::DayOfYear,
760 "WEEK" => DateTimeField::Week,
761 "QUARTER" => DateTimeField::Quarter,
762 "EPOCH" => DateTimeField::Epoch,
763 "TIMEZONE" => DateTimeField::Timezone,
764 "TIMEZONE_HOUR" => DateTimeField::TimezoneHour,
765 "TIMEZONE_MINUTE" => DateTimeField::TimezoneMinute,
766 "DATE" => DateTimeField::Date,
767 "TIME" => DateTimeField::Time,
768 other => DateTimeField::Custom(other.to_string()),
769 }
770}
771
772pub fn row_number() -> Expr {
776 Expr(Expression::RowNumber(RowNumber))
777}
778
779pub fn rank_() -> Expr {
781 Expr(Expression::Rank(Rank {
782 order_by: None,
783 args: vec![],
784 }))
785}
786
787pub fn dense_rank() -> Expr {
789 Expr(Expression::DenseRank(DenseRank { args: vec![] }))
790}
791
792pub fn select<I, E>(expressions: I) -> SelectBuilder
819where
820 I: IntoIterator<Item = E>,
821 E: IntoExpr,
822{
823 SelectBuilder::new().select_cols(expressions)
824}
825
826pub fn from(table_name: &str) -> SelectBuilder {
841 SelectBuilder::new().from(table_name)
842}
843
844pub fn delete(table_name: &str) -> DeleteBuilder {
857 DeleteBuilder {
858 delete: Delete {
859 table: builder_table_ref(table_name),
860 hint: None,
861 on_cluster: None,
862 alias: None,
863 alias_explicit_as: false,
864 using: Vec::new(),
865 where_clause: None,
866 output: None,
867 leading_comments: Vec::new(),
868 with: None,
869 limit: None,
870 order_by: None,
871 returning: Vec::new(),
872 tables: Vec::new(),
873 tables_from_using: false,
874 joins: Vec::new(),
875 force_index: None,
876 no_from: false,
877 },
878 }
879}
880
881pub fn insert_into(table_name: &str) -> InsertBuilder {
898 InsertBuilder {
899 insert: Insert {
900 table: builder_table_ref(table_name),
901 columns: Vec::new(),
902 values: Vec::new(),
903 query: None,
904 overwrite: false,
905 partition: Vec::new(),
906 directory: None,
907 returning: Vec::new(),
908 output: None,
909 on_conflict: None,
910 leading_comments: Vec::new(),
911 if_exists: false,
912 with: None,
913 ignore: false,
914 source_alias: None,
915 alias: None,
916 alias_explicit_as: false,
917 default_values: false,
918 by_name: false,
919 conflict_action: None,
920 is_replace: false,
921 hint: None,
922 replace_where: None,
923 source: None,
924 function_target: None,
925 partition_by: None,
926 settings: Vec::new(),
927 },
928 }
929}
930
931pub fn update(table_name: &str) -> UpdateBuilder {
949 UpdateBuilder {
950 update: Update {
951 table: builder_table_ref(table_name),
952 hint: None,
953 extra_tables: Vec::new(),
954 table_joins: Vec::new(),
955 set: Vec::new(),
956 from_clause: None,
957 from_joins: Vec::new(),
958 where_clause: None,
959 returning: Vec::new(),
960 output: None,
961 with: None,
962 leading_comments: Vec::new(),
963 limit: None,
964 order_by: None,
965 from_before_set: false,
966 },
967 }
968}
969
970#[derive(Debug, Clone)]
995pub struct Expr(pub Expression);
996
997impl Expr {
998 pub fn into_inner(self) -> Expression {
1000 self.0
1001 }
1002
1003 pub fn to_sql(&self) -> String {
1007 generate_builder_sql(&self.0)
1008 }
1009
1010 pub fn eq(self, other: Expr) -> Expr {
1014 Expr(engine::binary(engine::BinaryKind::Eq, self.0, other.0))
1015 }
1016
1017 pub fn neq(self, other: Expr) -> Expr {
1019 Expr(engine::binary(engine::BinaryKind::Neq, self.0, other.0))
1020 }
1021
1022 pub fn lt(self, other: Expr) -> Expr {
1024 Expr(engine::binary(engine::BinaryKind::Lt, self.0, other.0))
1025 }
1026
1027 pub fn lte(self, other: Expr) -> Expr {
1029 Expr(engine::binary(engine::BinaryKind::Lte, self.0, other.0))
1030 }
1031
1032 pub fn gt(self, other: Expr) -> Expr {
1034 Expr(engine::binary(engine::BinaryKind::Gt, self.0, other.0))
1035 }
1036
1037 pub fn gte(self, other: Expr) -> Expr {
1039 Expr(engine::binary(engine::BinaryKind::Gte, self.0, other.0))
1040 }
1041
1042 pub fn and(self, other: Expr) -> Expr {
1046 Expr(engine::binary(engine::BinaryKind::And, self.0, other.0))
1047 }
1048
1049 pub fn or(self, other: Expr) -> Expr {
1051 Expr(engine::binary(engine::BinaryKind::Or, self.0, other.0))
1052 }
1053
1054 pub fn not(self) -> Expr {
1056 Expr(engine::unary(engine::UnaryKind::Not, self.0))
1057 }
1058
1059 pub fn xor(self, other: Expr) -> Expr {
1061 Expr(engine::binary(engine::BinaryKind::Xor, self.0, other.0))
1062 }
1063
1064 pub fn add(self, other: Expr) -> Expr {
1068 Expr(engine::binary(engine::BinaryKind::Add, self.0, other.0))
1069 }
1070
1071 pub fn sub(self, other: Expr) -> Expr {
1073 Expr(engine::binary(engine::BinaryKind::Sub, self.0, other.0))
1074 }
1075
1076 pub fn mul(self, other: Expr) -> Expr {
1078 Expr(engine::binary(engine::BinaryKind::Mul, self.0, other.0))
1079 }
1080
1081 pub fn div(self, other: Expr) -> Expr {
1083 Expr(engine::binary(engine::BinaryKind::Div, self.0, other.0))
1084 }
1085
1086 pub fn modulo(self, other: Expr) -> Expr {
1088 Expr(engine::binary(engine::BinaryKind::Mod, self.0, other.0))
1089 }
1090
1091 pub fn neg(self) -> Expr {
1093 Expr(engine::unary(engine::UnaryKind::Neg, self.0))
1094 }
1095
1096 pub fn is(self, other: Expr) -> Expr {
1098 Expr(engine::binary(engine::BinaryKind::Is, self.0, other.0))
1099 }
1100
1101 pub fn is_null(self) -> Expr {
1105 Expr(engine::unary(engine::UnaryKind::IsNull, self.0))
1106 }
1107
1108 pub fn is_not_null(self) -> Expr {
1110 Expr(engine::unary(engine::UnaryKind::IsNotNull, self.0))
1111 }
1112
1113 pub fn in_list(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1117 Expr(Expression::In(Box::new(In {
1118 this: self.0,
1119 expressions: values.into_iter().map(|v| v.0).collect(),
1120 query: None,
1121 not: false,
1122 global: false,
1123 unnest: None,
1124 is_field: false,
1125 })))
1126 }
1127
1128 pub fn between(self, low: Expr, high: Expr) -> Expr {
1130 Expr(Expression::Between(Box::new(Between {
1131 this: self.0,
1132 low: low.0,
1133 high: high.0,
1134 not: false,
1135 symmetric: None,
1136 })))
1137 }
1138
1139 pub fn like(self, pattern: Expr) -> Expr {
1141 Expr(engine::binary(engine::BinaryKind::Like, self.0, pattern.0))
1142 }
1143
1144 pub fn alias(self, name: &str) -> Expr {
1146 alias(self, name)
1147 }
1148
1149 pub fn cast(self, to: &str) -> Expr {
1153 cast(self, to)
1154 }
1155
1156 pub fn asc(self) -> Expr {
1161 Expr(Expression::Ordered(Box::new(Ordered {
1162 nulls_auto: false,
1163 this: self.0,
1164 desc: false,
1165 nulls_first: None,
1166 explicit_asc: true,
1167 with_fill: None,
1168 })))
1169 }
1170
1171 pub fn desc(self) -> Expr {
1175 Expr(Expression::Ordered(Box::new(Ordered {
1176 nulls_auto: false,
1177 this: self.0,
1178 desc: true,
1179 nulls_first: None,
1180 explicit_asc: false,
1181 with_fill: None,
1182 })))
1183 }
1184
1185 pub fn ilike(self, pattern: Expr) -> Expr {
1190 Expr(engine::binary(engine::BinaryKind::ILike, self.0, pattern.0))
1191 }
1192
1193 pub fn rlike(self, pattern: Expr) -> Expr {
1198 Expr(engine::binary(engine::BinaryKind::RLike, self.0, pattern.0))
1199 }
1200
1201 pub fn not_in(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1205 Expr(Expression::In(Box::new(In {
1206 this: self.0,
1207 expressions: values.into_iter().map(|v| v.0).collect(),
1208 query: None,
1209 not: true,
1210 global: false,
1211 unnest: None,
1212 is_field: false,
1213 })))
1214 }
1215}
1216
1217pub struct SelectBuilder {
1243 select: Select,
1244}
1245
1246impl SelectBuilder {
1247 fn new() -> Self {
1248 SelectBuilder {
1249 select: Select::new(),
1250 }
1251 }
1252
1253 fn edit(mut self, edit: impl FnOnce(&mut Expression)) -> Self {
1254 let mut expression = Expression::Select(Box::new(self.select));
1255 edit(&mut expression);
1256 self.select = match expression {
1257 Expression::Select(select) => *select,
1258 _ => unreachable!("select builder engine changed the expression kind"),
1259 };
1260 self
1261 }
1262
1263 fn join_with_kind(self, table_name: &str, on: Option<Expr>, kind: JoinKind) -> Self {
1264 let join = Join {
1265 kind,
1266 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1267 on: on.map(|expression| expression.0),
1268 using: Vec::new(),
1269 use_inner_keyword: false,
1270 use_outer_keyword: false,
1271 deferred_condition: false,
1272 join_hint: None,
1273 match_condition: None,
1274 pivots: Vec::new(),
1275 comments: Vec::new(),
1276 nesting_group: 0,
1277 directed: false,
1278 };
1279 self.edit(|expression| {
1280 engine::append_join(expression, join).expect("select builder accepts JOIN clauses")
1281 })
1282 }
1283
1284 pub fn select_cols<I, E>(self, expressions: I) -> Self
1289 where
1290 I: IntoIterator<Item = E>,
1291 E: IntoExpr,
1292 {
1293 self.select_cols_with_options(expressions, ClauseOptions::default())
1294 }
1295
1296 pub fn select_cols_with_options<I, E>(self, expressions: I, options: ClauseOptions) -> Self
1298 where
1299 I: IntoIterator<Item = E>,
1300 E: IntoExpr,
1301 {
1302 let values = expressions
1303 .into_iter()
1304 .map(|expression| expression.into_expr().0)
1305 .collect();
1306 self.edit(|expression| {
1307 engine::append_select(expression, values, options.append)
1308 .expect("select builder accepts SELECT clauses")
1309 })
1310 }
1311
1312 pub fn from(self, table_name: &str) -> Self {
1314 self.edit(|expression| {
1315 engine::set_from(
1316 expression,
1317 vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1318 )
1319 .expect("select builder accepts FROM clauses")
1320 })
1321 }
1322
1323 pub fn from_expr(self, expr: Expr) -> Self {
1328 self.edit(|expression| {
1329 engine::set_from(expression, vec![expr.0]).expect("select builder accepts FROM clauses")
1330 })
1331 }
1332
1333 pub fn join(self, table_name: &str, on: Expr) -> Self {
1335 self.join_with_kind(table_name, Some(on), JoinKind::Inner)
1336 }
1337
1338 pub fn left_join(self, table_name: &str, on: Expr) -> Self {
1340 self.join_with_kind(table_name, Some(on), JoinKind::Left)
1341 }
1342
1343 pub fn where_(self, condition: Expr) -> Self {
1345 self.where_with_options(condition, ClauseOptions::default())
1346 }
1347
1348 pub fn where_with_options(self, condition: Expr, options: ClauseOptions) -> Self {
1350 self.edit(|expression| {
1351 engine::apply_where(expression, condition.0, options.append)
1352 .expect("select builder accepts WHERE clauses")
1353 })
1354 }
1355
1356 pub fn group_by<I, E>(self, expressions: I) -> Self
1358 where
1359 I: IntoIterator<Item = E>,
1360 E: IntoExpr,
1361 {
1362 self.group_by_with_options(expressions, ClauseOptions::default())
1363 }
1364
1365 pub fn group_by_with_options<I, E>(self, expressions: I, options: ClauseOptions) -> Self
1367 where
1368 I: IntoIterator<Item = E>,
1369 E: IntoExpr,
1370 {
1371 let values = expressions
1372 .into_iter()
1373 .map(|expression| expression.into_expr().0)
1374 .collect();
1375 self.edit(|expression| {
1376 engine::apply_group_by(expression, values, options.append)
1377 .expect("select builder accepts GROUP BY clauses")
1378 })
1379 }
1380
1381 pub fn having(self, condition: Expr) -> Self {
1383 self.having_with_options(condition, ClauseOptions::default())
1384 }
1385
1386 pub fn having_with_options(self, condition: Expr, options: ClauseOptions) -> Self {
1388 self.edit(|expression| {
1389 engine::apply_having(expression, condition.0, options.append)
1390 .expect("select builder accepts HAVING clauses")
1391 })
1392 }
1393
1394 pub fn order_by<I, E>(self, expressions: I) -> Self
1400 where
1401 I: IntoIterator<Item = E>,
1402 E: IntoExpr,
1403 {
1404 self.order_by_with_options(expressions, ClauseOptions::default())
1405 }
1406
1407 pub fn order_by_with_options<I, E>(self, expressions: I, options: ClauseOptions) -> Self
1409 where
1410 I: IntoIterator<Item = E>,
1411 E: IntoExpr,
1412 {
1413 let values = expressions
1414 .into_iter()
1415 .map(|expression| engine::ordered(expression.into_expr().0))
1416 .collect();
1417 self.edit(|expression| {
1418 engine::apply_order_by(expression, values, options.append)
1419 .expect("select builder accepts ORDER BY clauses")
1420 })
1421 }
1422
1423 pub fn sort_by<I, E>(self, expressions: I) -> Self
1430 where
1431 I: IntoIterator<Item = E>,
1432 E: IntoExpr,
1433 {
1434 self.sort_by_with_options(expressions, ClauseOptions::default())
1435 }
1436
1437 pub fn sort_by_with_options<I, E>(self, expressions: I, options: ClauseOptions) -> Self
1439 where
1440 I: IntoIterator<Item = E>,
1441 E: IntoExpr,
1442 {
1443 let values = expressions
1444 .into_iter()
1445 .map(|expression| engine::ordered(expression.into_expr().0))
1446 .collect();
1447 self.edit(|expression| {
1448 engine::apply_sort_by(expression, values, options.append)
1449 .expect("select builder accepts SORT BY clauses")
1450 })
1451 }
1452
1453 pub fn limit(self, count: usize) -> Self {
1455 self.edit(|expression| {
1456 engine::apply_limit(
1457 expression,
1458 Expression::Literal(Box::new(Literal::Number(count.to_string()))),
1459 )
1460 .expect("select builder accepts LIMIT clauses")
1461 })
1462 }
1463
1464 pub fn offset(self, count: usize) -> Self {
1466 self.edit(|expression| {
1467 engine::apply_offset(
1468 expression,
1469 Expression::Literal(Box::new(Literal::Number(count.to_string()))),
1470 )
1471 .expect("select builder accepts OFFSET clauses")
1472 })
1473 }
1474
1475 pub fn distinct(self) -> Self {
1477 self.edit(|expression| {
1478 engine::apply_distinct(expression, true)
1479 .expect("select builder accepts DISTINCT clauses")
1480 })
1481 }
1482
1483 pub fn qualify(self, condition: Expr) -> Self {
1488 self.qualify_with_options(condition, ClauseOptions::default())
1489 }
1490
1491 pub fn qualify_with_options(self, condition: Expr, options: ClauseOptions) -> Self {
1493 self.edit(|expression| {
1494 engine::apply_qualify(expression, condition.0, options.append)
1495 .expect("select builder accepts QUALIFY clauses")
1496 })
1497 }
1498
1499 pub fn right_join(self, table_name: &str, on: Expr) -> Self {
1501 self.join_with_kind(table_name, Some(on), JoinKind::Right)
1502 }
1503
1504 pub fn full_join(self, table_name: &str, on: Expr) -> Self {
1506 self.join_with_kind(table_name, Some(on), JoinKind::Full)
1507 }
1508
1509 pub fn cross_join(self, table_name: &str) -> Self {
1511 self.join_with_kind(table_name, None, JoinKind::Cross)
1512 }
1513
1514 pub fn lateral_view<S: AsRef<str>>(
1521 self,
1522 table_function: Expr,
1523 table_alias: &str,
1524 column_aliases: impl IntoIterator<Item = S>,
1525 ) -> Self {
1526 self.lateral_view_with_options(
1527 table_function,
1528 table_alias,
1529 column_aliases,
1530 LateralViewOptions::default(),
1531 )
1532 }
1533
1534 pub fn lateral_view_with_options<S: AsRef<str>>(
1536 self,
1537 table_function: Expr,
1538 table_alias: &str,
1539 column_aliases: impl IntoIterator<Item = S>,
1540 options: LateralViewOptions,
1541 ) -> Self {
1542 let aliases = column_aliases
1543 .into_iter()
1544 .map(|c| builder_identifier(c.as_ref()))
1545 .collect();
1546 self.edit(|expression| {
1547 engine::append_lateral_view(
1548 expression,
1549 table_function.0,
1550 Some(builder_identifier(table_alias)),
1551 aliases,
1552 options.outer,
1553 )
1554 .expect("select builder accepts LATERAL VIEW clauses")
1555 })
1556 }
1557
1558 pub fn window(self, name: &str, def: WindowDefBuilder) -> Self {
1564 let order_by = def.order_by;
1565 self.edit(|expression| {
1566 engine::append_window(
1567 expression,
1568 builder_identifier(name),
1569 def.partition_by,
1570 order_by,
1571 )
1572 .expect("select builder accepts WINDOW clauses")
1573 })
1574 }
1575
1576 pub fn for_update(self) -> Self {
1581 self.edit(|expression| {
1582 engine::append_lock(expression, engine::LockKind::Update)
1583 .expect("select builder accepts locking clauses")
1584 })
1585 }
1586
1587 pub fn for_share(self) -> Self {
1592 self.edit(|expression| {
1593 engine::append_lock(expression, engine::LockKind::Share)
1594 .expect("select builder accepts locking clauses")
1595 })
1596 }
1597
1598 pub fn hint(self, hint_text: &str) -> Self {
1603 self.edit(|expression| {
1604 engine::append_hint(expression, hint_text.to_string())
1605 .expect("select builder accepts query hints")
1606 })
1607 }
1608
1609 pub fn ctas(self, table_name: &str) -> Expression {
1625 self.ctas_with_options(table_name, CtasOptions::default())
1626 }
1627
1628 pub fn ctas_with_options(self, table_name: &str, options: CtasOptions) -> Expression {
1630 engine::create_table_as(
1631 self.build(),
1632 builder_table_ref(table_name),
1633 options.replace,
1634 options.temporary,
1635 )
1636 .expect("select builder CTAS source is a query")
1637 }
1638
1639 pub fn union(self, other: SelectBuilder) -> SetOpBuilder {
1643 SetOpBuilder::new(SetOpKind::Union, self, other, false)
1644 }
1645
1646 pub fn union_all(self, other: SelectBuilder) -> SetOpBuilder {
1650 SetOpBuilder::new(SetOpKind::Union, self, other, true)
1651 }
1652
1653 pub fn intersect(self, other: SelectBuilder) -> SetOpBuilder {
1657 SetOpBuilder::new(SetOpKind::Intersect, self, other, false)
1658 }
1659
1660 pub fn except_(self, other: SelectBuilder) -> SetOpBuilder {
1664 SetOpBuilder::new(SetOpKind::Except, self, other, false)
1665 }
1666
1667 pub fn build(self) -> Expression {
1669 Expression::Select(Box::new(self.select))
1670 }
1671
1672 pub fn to_sql(self) -> String {
1677 generate_builder_sql(&self.build())
1678 }
1679}
1680
1681pub struct DeleteBuilder {
1690 delete: Delete,
1691}
1692
1693impl DeleteBuilder {
1694 pub fn where_(self, condition: Expr) -> Self {
1696 self.where_with_options(condition, ClauseOptions::default())
1697 }
1698
1699 pub fn where_with_options(mut self, condition: Expr, options: ClauseOptions) -> Self {
1701 let mut expression = Expression::Delete(Box::new(self.delete));
1702 engine::apply_where(&mut expression, condition.0, options.append)
1703 .expect("delete builder accepts WHERE clauses");
1704 self.delete = match expression {
1705 Expression::Delete(delete) => *delete,
1706 _ => unreachable!("delete builder engine changed the expression kind"),
1707 };
1708 self
1709 }
1710
1711 pub fn build(self) -> Expression {
1713 Expression::Delete(Box::new(self.delete))
1714 }
1715
1716 pub fn to_sql(self) -> String {
1718 generate_builder_sql(&self.build())
1719 }
1720}
1721
1722pub struct InsertBuilder {
1733 insert: Insert,
1734}
1735
1736impl InsertBuilder {
1737 fn edit(mut self, edit: impl FnOnce(&mut Expression)) -> Self {
1738 let mut expression = Expression::Insert(Box::new(self.insert));
1739 edit(&mut expression);
1740 self.insert = match expression {
1741 Expression::Insert(insert) => *insert,
1742 _ => unreachable!("insert builder engine changed the expression kind"),
1743 };
1744 self
1745 }
1746
1747 pub fn columns<I, S>(self, columns: I) -> Self
1749 where
1750 I: IntoIterator<Item = S>,
1751 S: AsRef<str>,
1752 {
1753 let columns = columns
1754 .into_iter()
1755 .map(|c| builder_identifier(c.as_ref()))
1756 .collect();
1757 self.edit(|expression| {
1758 engine::set_insert_columns(expression, columns)
1759 .expect("insert builder accepts target columns")
1760 })
1761 }
1762
1763 pub fn values<I>(self, values: I) -> Self
1767 where
1768 I: IntoIterator<Item = Expr>,
1769 {
1770 let row = values.into_iter().map(|v| v.0).collect();
1771 self.edit(|expression| {
1772 engine::apply_insert_values(expression, vec![row], true)
1773 .expect("insert builder accepts VALUES clauses")
1774 })
1775 }
1776
1777 pub fn query(self, query: SelectBuilder) -> Self {
1781 self.edit(|expression| {
1782 engine::set_insert_query(expression, query.build())
1783 .expect("insert builder accepts query sources")
1784 })
1785 }
1786
1787 pub fn build(self) -> Expression {
1789 Expression::Insert(Box::new(self.insert))
1790 }
1791
1792 pub fn to_sql(self) -> String {
1794 generate_builder_sql(&self.build())
1795 }
1796}
1797
1798pub struct UpdateBuilder {
1808 update: Update,
1809}
1810
1811impl UpdateBuilder {
1812 fn edit(mut self, edit: impl FnOnce(&mut Expression)) -> Self {
1813 let mut expression = Expression::Update(Box::new(self.update));
1814 edit(&mut expression);
1815 self.update = match expression {
1816 Expression::Update(update) => *update,
1817 _ => unreachable!("update builder engine changed the expression kind"),
1818 };
1819 self
1820 }
1821
1822 pub fn set(self, column: &str, value: Expr) -> Self {
1826 self.edit(|expression| {
1827 engine::append_update_assignments(
1828 expression,
1829 vec![(builder_identifier(column), value.0)],
1830 )
1831 .expect("update builder accepts SET assignments")
1832 })
1833 }
1834
1835 pub fn where_(self, condition: Expr) -> Self {
1837 self.where_with_options(condition, ClauseOptions::default())
1838 }
1839
1840 pub fn where_with_options(mut self, condition: Expr, options: ClauseOptions) -> Self {
1842 let mut expression = Expression::Update(Box::new(self.update));
1843 engine::apply_where(&mut expression, condition.0, options.append)
1844 .expect("update builder accepts WHERE clauses");
1845 self.update = match expression {
1846 Expression::Update(update) => *update,
1847 _ => unreachable!("update builder engine changed the expression kind"),
1848 };
1849 self
1850 }
1851
1852 pub fn from(self, table_name: &str) -> Self {
1856 self.edit(|expression| {
1857 engine::set_from(
1858 expression,
1859 vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1860 )
1861 .expect("update builder accepts FROM clauses")
1862 })
1863 }
1864
1865 pub fn build(self) -> Expression {
1867 Expression::Update(Box::new(self.update))
1868 }
1869
1870 pub fn to_sql(self) -> String {
1872 generate_builder_sql(&self.build())
1873 }
1874}
1875
1876pub fn case() -> CaseBuilder {
1901 CaseBuilder {
1902 operand: None,
1903 whens: Vec::new(),
1904 else_: None,
1905 }
1906}
1907
1908pub fn case_of(operand: Expr) -> CaseBuilder {
1929 CaseBuilder {
1930 operand: Some(operand.0),
1931 whens: Vec::new(),
1932 else_: None,
1933 }
1934}
1935
1936pub struct CaseBuilder {
1944 operand: Option<Expression>,
1945 whens: Vec<(Expression, Expression)>,
1946 else_: Option<Expression>,
1947}
1948
1949impl CaseBuilder {
1950 pub fn when(mut self, condition: Expr, result: Expr) -> Self {
1955 self.whens.push((condition.0, result.0));
1956 self
1957 }
1958
1959 pub fn else_(mut self, result: Expr) -> Self {
1964 self.else_ = Some(result.0);
1965 self
1966 }
1967
1968 pub fn build(self) -> Expr {
1970 Expr(self.build_expr())
1971 }
1972
1973 pub fn build_expr(self) -> Expression {
1978 let mut expression = engine::case(self.operand);
1979 for (condition, result) in self.whens {
1980 engine::append_case_when(&mut expression, condition, result)
1981 .expect("case builder accepts WHEN branches");
1982 }
1983 if let Some(result) = self.else_ {
1984 engine::set_case_else(&mut expression, result)
1985 .expect("case builder accepts ELSE branches");
1986 }
1987 expression
1988 }
1989}
1990
1991pub fn subquery(query: SelectBuilder, alias_name: &str) -> Expr {
2015 subquery_expr(query.build(), alias_name)
2016}
2017
2018pub fn subquery_expr(expr: Expression, alias_name: &str) -> Expr {
2023 Expr(
2024 engine::subquery(expr, Some(builder_identifier(alias_name)), true)
2025 .expect("subquery builder source is a query"),
2026 )
2027}
2028
2029#[derive(Debug, Clone, Copy)]
2035enum SetOpKind {
2036 Union,
2037 Intersect,
2038 Except,
2039}
2040
2041pub struct SetOpBuilder {
2062 kind: SetOpKind,
2063 left: Expression,
2064 right: Expression,
2065 all: bool,
2066 order_by: Option<OrderBy>,
2067 limit: Option<Box<Expression>>,
2068 offset: Option<Box<Expression>>,
2069}
2070
2071impl SetOpBuilder {
2072 fn new(kind: SetOpKind, left: SelectBuilder, right: SelectBuilder, all: bool) -> Self {
2073 SetOpBuilder {
2074 kind,
2075 left: left.build(),
2076 right: right.build(),
2077 all,
2078 order_by: None,
2079 limit: None,
2080 offset: None,
2081 }
2082 }
2083
2084 pub fn order_by<I, E>(self, expressions: I) -> Self
2089 where
2090 I: IntoIterator<Item = E>,
2091 E: IntoExpr,
2092 {
2093 self.order_by_with_options(expressions, ClauseOptions::default())
2094 }
2095
2096 pub fn order_by_with_options<I, E>(mut self, expressions: I, options: ClauseOptions) -> Self
2098 where
2099 I: IntoIterator<Item = E>,
2100 E: IntoExpr,
2101 {
2102 let values: Vec<_> = expressions
2103 .into_iter()
2104 .map(|expression| engine::ordered(expression.into_expr().0))
2105 .collect();
2106 if options.append {
2107 self.order_by
2108 .get_or_insert_with(|| OrderBy {
2109 siblings: false,
2110 comments: Vec::new(),
2111 expressions: Vec::new(),
2112 })
2113 .expressions
2114 .extend(values);
2115 } else {
2116 self.order_by = Some(OrderBy {
2117 siblings: false,
2118 comments: Vec::new(),
2119 expressions: values,
2120 });
2121 }
2122 self
2123 }
2124
2125 pub fn limit(mut self, count: usize) -> Self {
2127 self.limit = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2128 count.to_string(),
2129 )))));
2130 self
2131 }
2132
2133 pub fn offset(mut self, count: usize) -> Self {
2135 self.offset = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2136 count.to_string(),
2137 )))));
2138 self
2139 }
2140
2141 pub fn build(self) -> Expression {
2146 let kind = match self.kind {
2147 SetOpKind::Union => engine::SetKind::Union,
2148 SetOpKind::Intersect => engine::SetKind::Intersect,
2149 SetOpKind::Except => engine::SetKind::Except,
2150 };
2151 let mut expression = engine::set_operation(kind, self.left, self.right, !self.all)
2152 .expect("set builder operands are queries");
2153 if let Some(order_by) = self.order_by {
2154 engine::apply_order_by(&mut expression, order_by.expressions, false)
2155 .expect("set operations accept ORDER BY clauses");
2156 }
2157 if let Some(limit) = self.limit {
2158 engine::apply_limit(&mut expression, *limit)
2159 .expect("set operations accept LIMIT clauses");
2160 }
2161 if let Some(offset) = self.offset {
2162 engine::apply_offset(&mut expression, *offset)
2163 .expect("set operations accept OFFSET clauses");
2164 }
2165 expression
2166 }
2167
2168 pub fn to_sql(self) -> String {
2170 generate_builder_sql(&self.build())
2171 }
2172}
2173
2174pub fn union(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2178 SetOpBuilder::new(SetOpKind::Union, left, right, false)
2179}
2180
2181pub fn union_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2185 SetOpBuilder::new(SetOpKind::Union, left, right, true)
2186}
2187
2188pub fn intersect(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2192 SetOpBuilder::new(SetOpKind::Intersect, left, right, false)
2193}
2194
2195pub fn intersect_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2199 SetOpBuilder::new(SetOpKind::Intersect, left, right, true)
2200}
2201
2202pub fn except_(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2206 SetOpBuilder::new(SetOpKind::Except, left, right, false)
2207}
2208
2209pub fn except_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2213 SetOpBuilder::new(SetOpKind::Except, left, right, true)
2214}
2215
2216pub struct WindowDefBuilder {
2241 partition_by: Vec<Expression>,
2242 order_by: Vec<Ordered>,
2243}
2244
2245impl WindowDefBuilder {
2246 pub fn new() -> Self {
2248 WindowDefBuilder {
2249 partition_by: Vec::new(),
2250 order_by: Vec::new(),
2251 }
2252 }
2253
2254 pub fn partition_by<I, E>(mut self, expressions: I) -> Self
2256 where
2257 I: IntoIterator<Item = E>,
2258 E: IntoExpr,
2259 {
2260 self.partition_by = expressions.into_iter().map(|e| e.into_expr().0).collect();
2261 self
2262 }
2263
2264 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2269 where
2270 I: IntoIterator<Item = E>,
2271 E: IntoExpr,
2272 {
2273 self.order_by = expressions
2274 .into_iter()
2275 .map(|e| {
2276 let expr = e.into_expr().0;
2277 match expr {
2278 Expression::Ordered(o) => *o,
2279 other => Ordered {
2280 nulls_auto: false,
2281 this: other,
2282 desc: false,
2283 nulls_first: None,
2284 explicit_asc: false,
2285 with_fill: None,
2286 },
2287 }
2288 })
2289 .collect();
2290 self
2291 }
2292}
2293
2294pub trait IntoExpr {
2313 fn into_expr(self) -> Expr;
2315}
2316
2317impl IntoExpr for Expr {
2318 fn into_expr(self) -> Expr {
2319 self
2320 }
2321}
2322
2323impl IntoExpr for &str {
2324 fn into_expr(self) -> Expr {
2326 col(self)
2327 }
2328}
2329
2330impl IntoExpr for String {
2331 fn into_expr(self) -> Expr {
2333 col(&self)
2334 }
2335}
2336
2337impl IntoExpr for Expression {
2338 fn into_expr(self) -> Expr {
2340 Expr(self)
2341 }
2342}
2343
2344pub trait IntoLiteral {
2359 fn into_literal(self) -> Expr;
2361}
2362
2363impl IntoLiteral for &str {
2364 fn into_literal(self) -> Expr {
2366 Expr(Expression::Literal(Box::new(Literal::String(
2367 self.to_string(),
2368 ))))
2369 }
2370}
2371
2372impl IntoLiteral for String {
2373 fn into_literal(self) -> Expr {
2375 Expr(Expression::Literal(Box::new(Literal::String(self))))
2376 }
2377}
2378
2379impl IntoLiteral for i64 {
2380 fn into_literal(self) -> Expr {
2382 Expr(Expression::Literal(Box::new(Literal::Number(
2383 self.to_string(),
2384 ))))
2385 }
2386}
2387
2388impl IntoLiteral for i32 {
2389 fn into_literal(self) -> Expr {
2391 Expr(Expression::Literal(Box::new(Literal::Number(
2392 self.to_string(),
2393 ))))
2394 }
2395}
2396
2397impl IntoLiteral for usize {
2398 fn into_literal(self) -> Expr {
2400 Expr(Expression::Literal(Box::new(Literal::Number(
2401 self.to_string(),
2402 ))))
2403 }
2404}
2405
2406impl IntoLiteral for f64 {
2407 fn into_literal(self) -> Expr {
2409 Expr(Expression::Literal(Box::new(Literal::Number(
2410 self.to_string(),
2411 ))))
2412 }
2413}
2414
2415impl IntoLiteral for bool {
2416 fn into_literal(self) -> Expr {
2418 Expr(Expression::Boolean(BooleanLiteral { value: self }))
2419 }
2420}
2421
2422pub fn merge_into(target: &str) -> MergeBuilder {
2444 MergeBuilder {
2445 expression: engine::merge(Expression::Table(Box::new(builder_table_ref(target)))),
2446 }
2447}
2448
2449pub struct MergeBuilder {
2453 expression: Expression,
2454}
2455
2456impl MergeBuilder {
2457 pub fn using(mut self, source: &str, on: Expr) -> Self {
2459 engine::set_merge_using(
2460 &mut self.expression,
2461 Expression::Table(Box::new(builder_table_ref(source))),
2462 on.0,
2463 )
2464 .expect("merge builder accepts a USING clause");
2465 self
2466 }
2467
2468 pub fn when_matched_update(mut self, assignments: Vec<(&str, Expr)>) -> Self {
2470 let assignments = assignments
2471 .into_iter()
2472 .map(|(column, value)| (builder_identifier(column), value.0))
2473 .collect();
2474 engine::append_merge_update(&mut self.expression, assignments, None)
2475 .expect("merge builder accepts matched update actions");
2476 self
2477 }
2478
2479 pub fn when_matched_update_where(
2481 mut self,
2482 condition: Expr,
2483 assignments: Vec<(&str, Expr)>,
2484 ) -> Self {
2485 let assignments = assignments
2486 .into_iter()
2487 .map(|(column, value)| (builder_identifier(column), value.0))
2488 .collect();
2489 engine::append_merge_update(&mut self.expression, assignments, Some(condition.0))
2490 .expect("merge builder accepts conditional matched update actions");
2491 self
2492 }
2493
2494 pub fn when_matched_delete(mut self) -> Self {
2496 engine::append_merge_delete(&mut self.expression, None)
2497 .expect("merge builder accepts matched delete actions");
2498 self
2499 }
2500
2501 pub fn when_matched_delete_where(mut self, condition: Expr) -> Self {
2503 engine::append_merge_delete(&mut self.expression, Some(condition.0))
2504 .expect("merge builder accepts conditional matched delete actions");
2505 self
2506 }
2507
2508 pub fn when_not_matched_insert(mut self, columns: &[&str], values: Vec<Expr>) -> Self {
2510 engine::append_merge_insert(
2511 &mut self.expression,
2512 columns
2513 .iter()
2514 .map(|column| builder_identifier(column))
2515 .collect(),
2516 values.into_iter().map(|value| value.0).collect(),
2517 None,
2518 )
2519 .expect("merge builder accepts not-matched insert actions");
2520 self
2521 }
2522
2523 pub fn when_not_matched_insert_where(
2525 mut self,
2526 condition: Expr,
2527 columns: &[&str],
2528 values: Vec<Expr>,
2529 ) -> Self {
2530 engine::append_merge_insert(
2531 &mut self.expression,
2532 columns
2533 .iter()
2534 .map(|column| builder_identifier(column))
2535 .collect(),
2536 values.into_iter().map(|value| value.0).collect(),
2537 Some(condition.0),
2538 )
2539 .expect("merge builder accepts conditional not-matched insert actions");
2540 self
2541 }
2542
2543 pub fn build(self) -> Expression {
2545 self.expression
2546 }
2547
2548 pub fn to_sql(self) -> String {
2550 generate_builder_sql(&self.build())
2551 }
2552}
2553
2554fn parse_simple_data_type(name: &str) -> DataType {
2555 let upper = name.trim().to_uppercase();
2556 match upper.as_str() {
2557 "INT" | "INTEGER" => DataType::Int {
2558 length: None,
2559 integer_spelling: upper == "INTEGER",
2560 },
2561 "BIGINT" => DataType::BigInt { length: None },
2562 "SMALLINT" => DataType::SmallInt { length: None },
2563 "TINYINT" => DataType::TinyInt { length: None },
2564 "FLOAT" => DataType::Float {
2565 precision: None,
2566 scale: None,
2567 real_spelling: false,
2568 },
2569 "DOUBLE" => DataType::Double {
2570 precision: None,
2571 scale: None,
2572 },
2573 "BOOLEAN" | "BOOL" => DataType::Boolean,
2574 "TEXT" => DataType::Text,
2575 "DATE" => DataType::Date,
2576 "TIMESTAMP" => DataType::Timestamp {
2577 precision: None,
2578 timezone: false,
2579 },
2580 "VARCHAR" => DataType::VarChar {
2581 length: None,
2582 parenthesized_length: false,
2583 },
2584 "CHAR" => DataType::Char { length: None },
2585 _ => {
2586 if let Ok(ast) =
2588 crate::parser::Parser::parse_sql(&format!("SELECT CAST(x AS {})", name))
2589 {
2590 if let Expression::Select(s) = &ast[0] {
2591 if let Some(Expression::Cast(c)) = s.expressions.first() {
2592 return c.to.clone();
2593 }
2594 }
2595 }
2596 DataType::Custom {
2598 name: name.to_string(),
2599 }
2600 }
2601 }
2602}
2603
2604#[cfg(test)]
2605mod tests {
2606 use super::*;
2607
2608 #[test]
2609 fn test_simple_select() {
2610 let sql = select(["id", "name"]).from("users").to_sql();
2611 assert_eq!(sql, "SELECT id, name FROM users");
2612 }
2613
2614 #[test]
2615 fn test_builder_quotes_unsafe_identifier_tokens() {
2616 let sql = select(["Name; DROP TABLE titanic"]).to_sql();
2617 assert_eq!(sql, r#"SELECT "Name; DROP TABLE titanic""#);
2618 }
2619
2620 #[test]
2621 fn test_builder_string_literal_requires_lit() {
2622 let sql = select([lit("Name; DROP TABLE titanic")]).to_sql();
2623 assert_eq!(sql, "SELECT 'Name; DROP TABLE titanic'");
2624 }
2625
2626 #[test]
2627 fn test_builder_quotes_unsafe_table_name_tokens() {
2628 let sql = select(["id"]).from("users; DROP TABLE x").to_sql();
2629 assert_eq!(sql, r#"SELECT id FROM "users; DROP TABLE x""#);
2630 }
2631
2632 #[test]
2633 fn test_select_star() {
2634 let sql = select([star()]).from("users").to_sql();
2635 assert_eq!(sql, "SELECT * FROM users");
2636 }
2637
2638 #[test]
2639 fn test_select_with_where() {
2640 let sql = select(["id", "name"])
2641 .from("users")
2642 .where_(col("age").gt(lit(18)))
2643 .to_sql();
2644 assert_eq!(sql, "SELECT id, name FROM users WHERE age > 18");
2645 }
2646
2647 #[test]
2648 fn test_select_with_join() {
2649 let sql = select(["u.id", "o.amount"])
2650 .from("users")
2651 .join("orders", col("u.id").eq(col("o.user_id")))
2652 .to_sql();
2653 assert_eq!(
2654 sql,
2655 "SELECT u.id, o.amount FROM users JOIN orders ON u.id = o.user_id"
2656 );
2657 }
2658
2659 #[test]
2660 fn test_select_with_group_by_having() {
2661 let sql = select([col("dept"), func("COUNT", [star()]).alias("cnt")])
2662 .from("employees")
2663 .group_by(["dept"])
2664 .having(func("COUNT", [star()]).gt(lit(5)))
2665 .to_sql();
2666 assert_eq!(
2667 sql,
2668 "SELECT dept, COUNT(*) AS cnt FROM employees GROUP BY dept HAVING COUNT(*) > 5"
2669 );
2670 }
2671
2672 #[test]
2673 fn test_select_with_order_limit_offset() {
2674 let sql = select(["id", "name"])
2675 .from("users")
2676 .order_by(["name"])
2677 .limit(10)
2678 .offset(20)
2679 .to_sql();
2680 assert_eq!(
2681 sql,
2682 "SELECT id, name FROM users ORDER BY name LIMIT 10 OFFSET 20"
2683 );
2684 }
2685
2686 #[test]
2687 fn test_select_distinct() {
2688 let sql = select(["name"]).from("users").distinct().to_sql();
2689 assert_eq!(sql, "SELECT DISTINCT name FROM users");
2690 }
2691
2692 #[test]
2693 fn test_insert_values() {
2694 let sql = insert_into("users")
2695 .columns(["id", "name"])
2696 .values([lit(1), lit("Alice")])
2697 .values([lit(2), lit("Bob")])
2698 .to_sql();
2699 assert_eq!(
2700 sql,
2701 "INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob')"
2702 );
2703 }
2704
2705 #[test]
2706 fn test_insert_select() {
2707 let sql = insert_into("archive")
2708 .columns(["id", "name"])
2709 .query(select(["id", "name"]).from("users"))
2710 .to_sql();
2711 assert_eq!(
2712 sql,
2713 "INSERT INTO archive (id, name) SELECT id, name FROM users"
2714 );
2715 }
2716
2717 #[test]
2718 fn test_update() {
2719 let sql = update("users")
2720 .set("name", lit("Bob"))
2721 .set("age", lit(30))
2722 .where_(col("id").eq(lit(1)))
2723 .to_sql();
2724 assert_eq!(sql, "UPDATE users SET name = 'Bob', age = 30 WHERE id = 1");
2725 }
2726
2727 #[test]
2728 fn test_delete() {
2729 let sql = delete("users").where_(col("id").eq(lit(1))).to_sql();
2730 assert_eq!(sql, "DELETE FROM users WHERE id = 1");
2731 }
2732
2733 #[test]
2734 fn test_complex_where() {
2735 let sql = select(["id"])
2736 .from("users")
2737 .where_(
2738 col("age")
2739 .gte(lit(18))
2740 .and(col("active").eq(boolean(true)))
2741 .and(col("name").like(lit("%test%"))),
2742 )
2743 .to_sql();
2744 assert_eq!(
2745 sql,
2746 "SELECT id FROM users WHERE age >= 18 AND active = TRUE AND name LIKE '%test%'"
2747 );
2748 }
2749
2750 #[test]
2751 fn test_in_list() {
2752 let sql = select(["id"])
2753 .from("users")
2754 .where_(col("status").in_list([lit("active"), lit("pending")]))
2755 .to_sql();
2756 assert_eq!(
2757 sql,
2758 "SELECT id FROM users WHERE status IN ('active', 'pending')"
2759 );
2760 }
2761
2762 #[test]
2763 fn test_between() {
2764 let sql = select(["id"])
2765 .from("orders")
2766 .where_(col("amount").between(lit(100), lit(500)))
2767 .to_sql();
2768 assert_eq!(
2769 sql,
2770 "SELECT id FROM orders WHERE amount BETWEEN 100 AND 500"
2771 );
2772 }
2773
2774 #[test]
2775 fn test_is_null() {
2776 let sql = select(["id"])
2777 .from("users")
2778 .where_(col("email").is_null())
2779 .to_sql();
2780 assert_eq!(sql, "SELECT id FROM users WHERE email IS NULL");
2781 }
2782
2783 #[test]
2784 fn test_arithmetic() {
2785 let sql = select([col("price").mul(col("quantity")).alias("total")])
2786 .from("items")
2787 .to_sql();
2788 assert_eq!(sql, "SELECT price * quantity AS total FROM items");
2789 }
2790
2791 #[test]
2792 fn test_nested_operator_grouping() {
2793 assert_eq!(
2794 or(col("a").eq(lit(1)), col("b").eq(lit(2)))
2795 .and(col("c").eq(lit(3)))
2796 .to_sql(),
2797 "(a = 1 OR b = 2) AND c = 3"
2798 );
2799 assert_eq!(
2800 col("a")
2801 .eq(lit(1))
2802 .and(or(col("b").eq(lit(2)), col("c").eq(lit(3))))
2803 .to_sql(),
2804 "a = 1 AND (b = 2 OR c = 3)"
2805 );
2806 assert_eq!(col("a").add(col("b")).mul(col("c")).to_sql(), "(a + b) * c");
2807 assert_eq!(col("a").mul(col("b").add(col("c"))).to_sql(), "a * (b + c)");
2808 assert_eq!(col("a").sub(col("b").sub(col("c"))).to_sql(), "a - (b - c)");
2809 assert_eq!(col("a").div(col("b").div(col("c"))).to_sql(), "a / (b / c)");
2810 }
2811
2812 #[test]
2813 fn test_cast() {
2814 let sql = select([col("id").cast("VARCHAR")]).from("users").to_sql();
2815 assert_eq!(sql, "SELECT CAST(id AS VARCHAR) FROM users");
2816 }
2817
2818 #[test]
2819 fn test_cast_int128() {
2820 for name in ["HUGEINT", "INT128"] {
2821 let Expression::Cast(cast) = col("value").cast(name).0 else {
2822 panic!("expected cast");
2823 };
2824 assert_eq!(cast.to, DataType::Int128);
2825 }
2826 }
2827
2828 #[test]
2829 fn test_cast_unsigned_integer_types() {
2830 for (name, expected) in [
2831 ("UTINYINT", DataType::UInt8),
2832 ("UINT8", DataType::UInt8),
2833 ("USMALLINT", DataType::UInt16),
2834 ("UINT16", DataType::UInt16),
2835 ("UINTEGER", DataType::UInt32),
2836 ("UINT32", DataType::UInt32),
2837 ("UBIGINT", DataType::UInt64),
2838 ("UINT64", DataType::UInt64),
2839 ("UHUGEINT", DataType::UInt128),
2840 ("UINT128", DataType::UInt128),
2841 ] {
2842 let Expression::Cast(cast) = col("value").cast(name).0 else {
2843 panic!("expected cast")
2844 };
2845 assert_eq!(cast.to, expected, "{name}");
2846 }
2847 }
2848
2849 #[test]
2850 fn test_from_starter() {
2851 let sql = from("users").select_cols(["id", "name"]).to_sql();
2852 assert_eq!(sql, "SELECT id, name FROM users");
2853 }
2854
2855 #[test]
2856 fn test_qualified_column() {
2857 let sql = select([col("u.id"), col("u.name")]).from("users").to_sql();
2858 assert_eq!(sql, "SELECT u.id, u.name FROM users");
2859 }
2860
2861 #[test]
2862 fn test_nested_dot_column() {
2863 let sql = select([col("t.s.f")]).from("users").to_sql();
2864 assert_eq!(sql, "SELECT t.s.f FROM users");
2865 }
2866
2867 #[test]
2868 fn test_not_condition() {
2869 let sql = select(["id"])
2870 .from("users")
2871 .where_(not(col("active").eq(boolean(true))))
2872 .to_sql();
2873 assert_eq!(sql, "SELECT id FROM users WHERE NOT active = TRUE");
2874 }
2875
2876 #[test]
2877 fn test_order_by_desc() {
2878 let sql = select(["id", "name"])
2879 .from("users")
2880 .order_by([col("name").desc()])
2881 .to_sql();
2882 assert_eq!(sql, "SELECT id, name FROM users ORDER BY name DESC");
2883 }
2884
2885 #[test]
2886 fn test_left_join() {
2887 let sql = select(["u.id", "o.amount"])
2888 .from("users")
2889 .left_join("orders", col("u.id").eq(col("o.user_id")))
2890 .to_sql();
2891 assert_eq!(
2892 sql,
2893 "SELECT u.id, o.amount FROM users LEFT JOIN orders ON u.id = o.user_id"
2894 );
2895 }
2896
2897 #[test]
2898 fn test_build_returns_expression() {
2899 let expr = select(["id"]).from("users").build();
2900 assert!(matches!(expr, Expression::Select(_)));
2901 }
2902
2903 #[test]
2904 fn test_expr_interop() {
2905 let age_check = col("age").gt(lit(18));
2907 let sql = select([col("id"), age_check.alias("is_adult")])
2908 .from("users")
2909 .to_sql();
2910 assert_eq!(sql, "SELECT id, age > 18 AS is_adult FROM users");
2911 }
2912
2913 #[test]
2916 fn test_sql_expr_simple() {
2917 let expr = sql_expr("age > 18");
2918 let sql = select(["id"]).from("users").where_(expr).to_sql();
2919 assert_eq!(sql, "SELECT id FROM users WHERE age > 18");
2920 }
2921
2922 #[test]
2923 fn test_sql_expr_compound() {
2924 let expr = sql_expr("a > 1 AND b < 10");
2925 let sql = select(["*"]).from("t").where_(expr).to_sql();
2926 assert_eq!(sql, "SELECT * FROM t WHERE a > 1 AND b < 10");
2927 }
2928
2929 #[test]
2930 fn test_sql_expr_function() {
2931 let expr = sql_expr("COALESCE(a, b, 0)");
2932 let sql = select([expr.alias("val")]).from("t").to_sql();
2933 assert_eq!(sql, "SELECT COALESCE(a, b, 0) AS val FROM t");
2934 }
2935
2936 #[test]
2937 fn test_condition_alias() {
2938 let cond = condition("x > 0");
2939 let sql = select(["*"]).from("t").where_(cond).to_sql();
2940 assert_eq!(sql, "SELECT * FROM t WHERE x > 0");
2941 }
2942
2943 #[test]
2946 fn test_ilike() {
2947 let sql = select(["id"])
2948 .from("users")
2949 .where_(col("name").ilike(lit("%test%")))
2950 .to_sql();
2951 assert_eq!(sql, "SELECT id FROM users WHERE name ILIKE '%test%'");
2952 }
2953
2954 #[test]
2955 fn test_rlike() {
2956 let sql = select(["id"])
2957 .from("users")
2958 .where_(col("name").rlike(lit("^[A-Z]")))
2959 .to_sql();
2960 assert_eq!(
2961 sql,
2962 "SELECT id FROM users WHERE REGEXP_LIKE(name, '^[A-Z]')"
2963 );
2964 }
2965
2966 #[test]
2967 fn test_not_in() {
2968 let sql = select(["id"])
2969 .from("users")
2970 .where_(col("status").not_in([lit("deleted"), lit("banned")]))
2971 .to_sql();
2972 assert_eq!(
2973 sql,
2974 "SELECT id FROM users WHERE status NOT IN ('deleted', 'banned')"
2975 );
2976 }
2977
2978 #[test]
2979 fn repeated_clauses_append_unless_replacement_is_requested() {
2980 let appended = select(["x"])
2981 .where_(col("x").gt(lit(0)))
2982 .where_(col("x").lt(lit(10)))
2983 .group_by(["x"])
2984 .group_by(["y"])
2985 .to_sql();
2986 assert_eq!(appended, "SELECT x WHERE x > 0 AND x < 10 GROUP BY x, y");
2987
2988 let replaced = select(["x"])
2989 .where_(col("x").gt(lit(0)))
2990 .where_with_options(col("x").eq(lit(5)), ClauseOptions { append: false })
2991 .group_by(["x"])
2992 .group_by_with_options(["y"], ClauseOptions { append: false })
2993 .to_sql();
2994 assert_eq!(replaced, "SELECT x WHERE x = 5 GROUP BY y");
2995 }
2996
2997 #[test]
3000 fn test_case_searched() {
3001 let expr = case()
3002 .when(col("x").gt(lit(0)), lit("positive"))
3003 .when(col("x").eq(lit(0)), lit("zero"))
3004 .else_(lit("negative"))
3005 .build();
3006 let sql = select([expr.alias("label")]).from("t").to_sql();
3007 assert_eq!(
3008 sql,
3009 "SELECT CASE WHEN x > 0 THEN 'positive' WHEN x = 0 THEN 'zero' ELSE 'negative' END AS label FROM t"
3010 );
3011 }
3012
3013 #[test]
3014 fn test_case_simple() {
3015 let expr = case_of(col("status"))
3016 .when(lit(1), lit("active"))
3017 .when(lit(0), lit("inactive"))
3018 .build();
3019 let sql = select([expr.alias("status_label")]).from("t").to_sql();
3020 assert_eq!(
3021 sql,
3022 "SELECT CASE status WHEN 1 THEN 'active' WHEN 0 THEN 'inactive' END AS status_label FROM t"
3023 );
3024 }
3025
3026 #[test]
3027 fn test_case_no_else() {
3028 let expr = case().when(col("x").gt(lit(0)), lit("yes")).build();
3029 let sql = select([expr]).from("t").to_sql();
3030 assert_eq!(sql, "SELECT CASE WHEN x > 0 THEN 'yes' END FROM t");
3031 }
3032
3033 #[test]
3036 fn test_subquery_in_from() {
3037 let inner = select(["id", "name"])
3038 .from("users")
3039 .where_(col("active").eq(boolean(true)));
3040 let outer = select(["sub.id"])
3041 .from_expr(subquery(inner, "sub"))
3042 .to_sql();
3043 assert_eq!(
3044 outer,
3045 "SELECT sub.id FROM (SELECT id, name FROM users WHERE active = TRUE) AS sub"
3046 );
3047 }
3048
3049 #[test]
3050 fn test_subquery_in_join() {
3051 let inner = select([col("user_id"), func("SUM", [col("amount")]).alias("total")])
3052 .from("orders")
3053 .group_by(["user_id"]);
3054 let sql = select(["u.name", "o.total"])
3055 .from("users")
3056 .join("orders", col("u.id").eq(col("o.user_id")))
3057 .to_sql();
3058 assert!(sql.contains("JOIN"));
3059 let _sub = subquery(inner, "o");
3061 }
3062
3063 #[test]
3066 fn test_union() {
3067 let sql = union(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3068 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3069 }
3070
3071 #[test]
3072 fn test_union_all() {
3073 let sql = union_all(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3074 assert_eq!(sql, "SELECT id FROM a UNION ALL SELECT id FROM b");
3075 }
3076
3077 #[test]
3078 fn test_intersect_builder() {
3079 let sql = intersect(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3080 assert_eq!(sql, "SELECT id FROM a INTERSECT SELECT id FROM b");
3081 }
3082
3083 #[test]
3084 fn test_except_builder() {
3085 let sql = except_(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3086 assert_eq!(sql, "SELECT id FROM a EXCEPT SELECT id FROM b");
3087 }
3088
3089 #[test]
3090 fn test_union_with_order_limit() {
3091 let sql = union(select(["id"]).from("a"), select(["id"]).from("b"))
3092 .order_by(["id"])
3093 .limit(10)
3094 .to_sql();
3095 assert!(sql.contains("UNION"));
3096 assert!(sql.contains("ORDER BY"));
3097 assert!(sql.contains("LIMIT"));
3098 }
3099
3100 #[test]
3101 fn test_select_builder_union() {
3102 let sql = select(["id"])
3103 .from("a")
3104 .union(select(["id"]).from("b"))
3105 .to_sql();
3106 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3107 }
3108
3109 #[test]
3112 fn test_qualify() {
3113 let sql = select(["id", "name"])
3114 .from("users")
3115 .qualify(col("rn").eq(lit(1)))
3116 .to_sql();
3117 assert_eq!(sql, "SELECT id, name FROM users QUALIFY rn = 1");
3118 }
3119
3120 #[test]
3121 fn test_right_join() {
3122 let sql = select(["u.id", "o.amount"])
3123 .from("users")
3124 .right_join("orders", col("u.id").eq(col("o.user_id")))
3125 .to_sql();
3126 assert_eq!(
3127 sql,
3128 "SELECT u.id, o.amount FROM users RIGHT JOIN orders ON u.id = o.user_id"
3129 );
3130 }
3131
3132 #[test]
3133 fn test_cross_join() {
3134 let sql = select(["a.x", "b.y"]).from("a").cross_join("b").to_sql();
3135 assert_eq!(sql, "SELECT a.x, b.y FROM a CROSS JOIN b");
3136 }
3137
3138 #[test]
3139 fn test_lateral_view() {
3140 let sql = select(["id", "col_val"])
3141 .from("t")
3142 .lateral_view(func("EXPLODE", [col("arr")]), "lv", ["col_val"])
3143 .to_sql();
3144 assert!(sql.contains("LATERAL VIEW"));
3145 assert!(sql.contains("EXPLODE"));
3146
3147 let expression = select(["id"])
3148 .from("t")
3149 .lateral_view_with_options(
3150 func("EXPLODE", [col("arr")]),
3151 "lv",
3152 ["value"],
3153 LateralViewOptions { outer: true },
3154 )
3155 .build();
3156 let Expression::Select(select) = expression else {
3157 panic!("expected SELECT")
3158 };
3159 assert!(select.lateral_views[0].outer);
3160 }
3161
3162 #[test]
3163 fn test_window_clause() {
3164 let sql = select(["id"])
3165 .from("t")
3166 .window(
3167 "w",
3168 WindowDefBuilder::new()
3169 .partition_by(["dept"])
3170 .order_by(["salary"]),
3171 )
3172 .to_sql();
3173 assert!(sql.contains("WINDOW"));
3174 assert!(sql.contains("PARTITION BY"));
3175 }
3176
3177 #[test]
3180 fn test_xor() {
3181 let sql = select(["*"])
3182 .from("t")
3183 .where_(col("a").xor(col("b")))
3184 .to_sql();
3185 assert_eq!(sql, "SELECT * FROM t WHERE a XOR b");
3186 }
3187
3188 #[test]
3191 fn test_for_update() {
3192 let sql = select(["id"]).from("t").for_update().to_sql();
3193 assert_eq!(sql, "SELECT id FROM t FOR UPDATE");
3194 }
3195
3196 #[test]
3197 fn test_for_share() {
3198 let sql = select(["id"]).from("t").for_share().to_sql();
3199 assert_eq!(sql, "SELECT id FROM t FOR SHARE");
3200 }
3201
3202 #[test]
3205 fn test_hint() {
3206 let sql = select(["*"]).from("t").hint("FULL(t)").to_sql();
3207 assert!(sql.contains("FULL(t)"), "Expected hint in: {}", sql);
3208 }
3209
3210 #[test]
3213 fn test_ctas() {
3214 let expr = select(["*"]).from("t").ctas("new_table");
3215 let sql = Generator::sql(&expr).unwrap();
3216 assert_eq!(sql, "CREATE TABLE new_table AS SELECT * FROM t");
3217
3218 let expr = select(["*"]).from("t").ctas_with_options(
3219 "new_table",
3220 CtasOptions {
3221 replace: true,
3222 temporary: true,
3223 },
3224 );
3225 let Expression::CreateTable(create) = expr else {
3226 panic!("expected CREATE TABLE")
3227 };
3228 assert!(create.or_replace);
3229 assert!(create.temporary);
3230 }
3231
3232 #[test]
3235 fn test_merge_update_insert() {
3236 let sql = merge_into("target")
3237 .using("source", col("target.id").eq(col("source.id")))
3238 .when_matched_update(vec![("name", col("source.name"))])
3239 .when_not_matched_insert(&["id", "name"], vec![col("source.id"), col("source.name")])
3240 .to_sql();
3241 assert!(
3242 sql.contains("MERGE INTO"),
3243 "Expected MERGE INTO in: {}",
3244 sql
3245 );
3246 assert!(sql.contains("USING"), "Expected USING in: {}", sql);
3247 assert!(
3248 sql.contains("WHEN MATCHED"),
3249 "Expected WHEN MATCHED in: {}",
3250 sql
3251 );
3252 assert!(
3253 sql.contains("UPDATE SET"),
3254 "Expected UPDATE SET in: {}",
3255 sql
3256 );
3257 assert!(
3258 sql.contains("WHEN NOT MATCHED"),
3259 "Expected WHEN NOT MATCHED in: {}",
3260 sql
3261 );
3262 assert!(sql.contains("INSERT"), "Expected INSERT in: {}", sql);
3263 }
3264
3265 #[test]
3266 fn test_merge_delete() {
3267 let sql = merge_into("target")
3268 .using("source", col("target.id").eq(col("source.id")))
3269 .when_matched_delete()
3270 .to_sql();
3271 assert!(
3272 sql.contains("MERGE INTO"),
3273 "Expected MERGE INTO in: {}",
3274 sql
3275 );
3276 assert!(
3277 sql.contains("WHEN MATCHED THEN DELETE"),
3278 "Expected WHEN MATCHED THEN DELETE in: {}",
3279 sql
3280 );
3281 }
3282
3283 #[test]
3284 fn test_merge_with_condition() {
3285 let sql = merge_into("target")
3286 .using("source", col("target.id").eq(col("source.id")))
3287 .when_matched_update_where(
3288 col("source.active").eq(boolean(true)),
3289 vec![("name", col("source.name"))],
3290 )
3291 .to_sql();
3292 assert!(
3293 sql.contains("MERGE INTO"),
3294 "Expected MERGE INTO in: {}",
3295 sql
3296 );
3297 assert!(
3298 sql.contains("AND source.active = TRUE"),
3299 "Expected condition in: {}",
3300 sql
3301 );
3302 }
3303}