From 44a241da2e5c0a96269b70a1cc4a864d5bf744d6 Mon Sep 17 00:00:00 2001 From: Huliiiii <134658521+Huliiiiii@users.noreply.github.com> Date: Thu, 22 May 2025 15:38:48 +0800 Subject: [PATCH] Unify `Expr` and `SimpleExpr` - Add `non_exhaustive` to `Expr` - Replace generic with impl syntax on some method to simplify code - Rename `new_with_left` to `new` - Remove method `expr` because we can use `new` - Remove inherent methods of Expr from ExprTrait --- src/backend/mod.rs | 2 +- src/backend/mysql/mod.rs | 2 +- src/backend/postgres/query.rs | 8 +- src/backend/query_builder.rs | 82 +- src/backend/sqlite/mod.rs | 2 +- src/backend/table_builder.rs | 4 +- src/expr.rs | 2500 ++++---------------------------- src/extension/postgres/expr.rs | 37 +- src/extension/postgres/func.rs | 44 +- src/extension/sqlite/expr.rs | 19 +- src/func.rs | 60 +- src/index/common.rs | 8 +- src/query/case.rs | 18 +- src/query/condition.rs | 30 +- src/query/delete.rs | 10 +- src/query/insert.rs | 12 +- src/query/on_conflict.rs | 22 +- src/query/ordered.rs | 20 +- src/query/returning.rs | 8 +- src/query/select.rs | 44 +- src/query/update.rs | 22 +- src/query/window.rs | 20 +- src/query/with.rs | 15 +- src/table/column.rs | 20 +- src/table/create.rs | 6 +- src/types.rs | 8 +- tests/more-parentheses.rs | 2 +- tests/mysql/query.rs | 16 +- tests/postgres/query.rs | 65 +- tests/sqlite/query.rs | 21 +- 30 files changed, 615 insertions(+), 2512 deletions(-) diff --git a/src/backend/mod.rs b/src/backend/mod.rs index b918e8544..debdcc8d1 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -92,7 +92,7 @@ pub trait PrecedenceDecider { // but dropping parentheses due to these relations can be confusing for readers. fn inner_expr_well_known_greater_precedence( &self, - inner: &SimpleExpr, + inner: &Expr, outer_oper: &Oper, ) -> bool; } diff --git a/src/backend/mysql/mod.rs b/src/backend/mysql/mod.rs index 4f972e9ed..533e8c676 100644 --- a/src/backend/mysql/mod.rs +++ b/src/backend/mysql/mod.rs @@ -30,7 +30,7 @@ impl TableRefBuilder for MysqlQueryBuilder {} impl PrecedenceDecider for MysqlQueryBuilder { fn inner_expr_well_known_greater_precedence( &self, - inner: &SimpleExpr, + inner: &Expr, outer_oper: &Oper, ) -> bool { common_inner_expr_well_known_greater_precedence(inner, outer_oper) diff --git a/src/backend/postgres/query.rs b/src/backend/postgres/query.rs index 15548a726..eea6d1f97 100644 --- a/src/backend/postgres/query.rs +++ b/src/backend/postgres/query.rs @@ -12,12 +12,12 @@ impl OperLeftAssocDecider for PostgresQueryBuilder { impl PrecedenceDecider for PostgresQueryBuilder { fn inner_expr_well_known_greater_precedence( &self, - inner: &SimpleExpr, + inner: &Expr, outer_oper: &Oper, ) -> bool { let common_answer = common_inner_expr_well_known_greater_precedence(inner, outer_oper); let pg_specific_answer = match inner { - SimpleExpr::Binary(_, inner_bin_oper, _) => { + Expr::Binary(_, inner_bin_oper, _) => { let inner_oper: Oper = (*inner_bin_oper).into(); if inner_oper.is_arithmetic() || inner_oper.is_shift() { is_ilike(inner_bin_oper) @@ -38,9 +38,9 @@ impl QueryBuilder for PostgresQueryBuilder { ("$", true) } - fn prepare_simple_expr(&self, simple_expr: &SimpleExpr, sql: &mut dyn SqlWriter) { + fn prepare_simple_expr(&self, simple_expr: &Expr, sql: &mut dyn SqlWriter) { match simple_expr { - SimpleExpr::AsEnum(type_name, expr) => { + Expr::AsEnum(type_name, expr) => { write!(sql, "CAST(").unwrap(); self.prepare_simple_expr_common(expr, sql); let q = self.quote(); diff --git a/src/backend/query_builder.rs b/src/backend/query_builder.rs index 175e66b91..599e85f95 100644 --- a/src/backend/query_builder.rs +++ b/src/backend/query_builder.rs @@ -351,20 +351,20 @@ pub trait QueryBuilder: } } - /// Translate [`SimpleExpr`] into SQL statement. - fn prepare_simple_expr(&self, simple_expr: &SimpleExpr, sql: &mut dyn SqlWriter) { + /// Translate [`Expr`] into SQL statement. + fn prepare_simple_expr(&self, simple_expr: &Expr, sql: &mut dyn SqlWriter) { self.prepare_simple_expr_common(simple_expr, sql); } - fn prepare_simple_expr_common(&self, simple_expr: &SimpleExpr, sql: &mut dyn SqlWriter) { + fn prepare_simple_expr_common(&self, simple_expr: &Expr, sql: &mut dyn SqlWriter) { match simple_expr { - SimpleExpr::Column(column_ref) => { + Expr::Column(column_ref) => { self.prepare_column_ref(column_ref, sql); } - SimpleExpr::Tuple(exprs) => { + Expr::Tuple(exprs) => { self.prepare_tuple(exprs, sql); } - SimpleExpr::Unary(op, expr) => { + Expr::Unary(op, expr) => { self.prepare_un_oper(op, sql); write!(sql, " ").unwrap(); let drop_expr_paren = @@ -377,20 +377,20 @@ pub trait QueryBuilder: write!(sql, ")").unwrap(); } } - SimpleExpr::FunctionCall(func) => { + Expr::FunctionCall(func) => { self.prepare_function_name(&func.func, sql); self.prepare_function_arguments(func, sql); } - SimpleExpr::Binary(left, op, right) => match (op, right.as_ref()) { - (BinOper::In, SimpleExpr::Tuple(t)) if t.is_empty() => { + Expr::Binary(left, op, right) => match (op, right.as_ref()) { + (BinOper::In, Expr::Tuple(t)) if t.is_empty() => { self.binary_expr(&1i32.into(), &BinOper::Equal, &2i32.into(), sql) } - (BinOper::NotIn, SimpleExpr::Tuple(t)) if t.is_empty() => { + (BinOper::NotIn, Expr::Tuple(t)) if t.is_empty() => { self.binary_expr(&1i32.into(), &BinOper::Equal, &1i32.into(), sql) } _ => self.binary_expr(left, op, right, sql), }, - SimpleExpr::SubQuery(oper, sel) => { + Expr::SubQuery(oper, sel) => { if let Some(oper) = oper { self.prepare_sub_query_oper(oper, sql); } @@ -398,10 +398,10 @@ pub trait QueryBuilder: self.prepare_query_statement(sel.deref(), sql); write!(sql, ")").unwrap(); } - SimpleExpr::Value(val) => { + Expr::Value(val) => { self.prepare_value(val, sql); } - SimpleExpr::Values(list) => { + Expr::Values(list) => { write!(sql, "(").unwrap(); list.iter().fold(true, |first, val| { if !first { @@ -412,10 +412,10 @@ pub trait QueryBuilder: }); write!(sql, ")").unwrap(); } - SimpleExpr::Custom(s) => { + Expr::Custom(s) => { write!(sql, "{s}").unwrap(); } - SimpleExpr::CustomWithExpr(expr, values) => { + Expr::CustomWithExpr(expr, values) => { let (placeholder, numbered) = self.placeholder(); let mut tokenizer = Tokenizer::new(expr).iter().peekable(); let mut count = 0; @@ -441,16 +441,16 @@ pub trait QueryBuilder: }; } } - SimpleExpr::Keyword(keyword) => { + Expr::Keyword(keyword) => { self.prepare_keyword(keyword, sql); } - SimpleExpr::AsEnum(_, expr) => { + Expr::AsEnum(_, expr) => { self.prepare_simple_expr(expr, sql); } - SimpleExpr::Case(case_stmt) => { + Expr::Case(case_stmt) => { self.prepare_case_statement(case_stmt, sql); } - SimpleExpr::Constant(val) => { + Expr::Constant(val) => { self.prepare_constant(val, sql); } } @@ -703,8 +703,8 @@ pub trait QueryBuilder: write!(sql, " {oper} ").unwrap(); } let both_binary = match simple_expr { - SimpleExpr::Binary(_, _, right) => { - matches!(right.as_ref(), SimpleExpr::Binary(_, _, _)) + Expr::Binary(_, _, right) => { + matches!(right.as_ref(), Expr::Binary(_, _, _)) } _ => false, }; @@ -1028,8 +1028,8 @@ pub trait QueryBuilder: }); } - /// Translate [`SimpleExpr::Tuple`] into SQL statement. - fn prepare_tuple(&self, exprs: &[SimpleExpr], sql: &mut dyn SqlWriter) { + /// Translate [`Expr::Tuple`] into SQL statement. + fn prepare_tuple(&self, exprs: &[Expr], sql: &mut dyn SqlWriter) { write!(sql, "(").unwrap(); for (i, expr) in exprs.iter().enumerate() { if i != 0 { @@ -1454,13 +1454,7 @@ pub trait QueryBuilder: #[doc(hidden)] /// Translate a binary expr to SQL. - fn binary_expr( - &self, - left: &SimpleExpr, - op: &BinOper, - right: &SimpleExpr, - sql: &mut dyn SqlWriter, - ) { + fn binary_expr(&self, left: &Expr, op: &BinOper, right: &Expr, sql: &mut dyn SqlWriter) { // If left has higher precedence than op, we can drop parentheses around left let drop_left_higher_precedence = self.inner_expr_well_known_greater_precedence(left, &(*op).into()); @@ -1499,7 +1493,7 @@ pub trait QueryBuilder: && matches!(right.get_bin_oper(), Some(&BinOper::Escape)); // Due to custom representation of casting AS datatype - let drop_right_as_hack = (op == &BinOper::As) && matches!(right, SimpleExpr::Custom(_)); + let drop_right_as_hack = (op == &BinOper::As) && matches!(right, Expr::Custom(_)); let right_paren = !drop_right_higher_precedence && !drop_right_escape_hack @@ -1615,11 +1609,7 @@ impl OperLeftAssocDecider for CommonSqlQueryBuilder { } impl PrecedenceDecider for CommonSqlQueryBuilder { - fn inner_expr_well_known_greater_precedence( - &self, - inner: &SimpleExpr, - outer_oper: &Oper, - ) -> bool { + fn inner_expr_well_known_greater_precedence(&self, inner: &Expr, outer_oper: &Oper) -> bool { common_inner_expr_well_known_greater_precedence(inner, outer_oper) } } @@ -1649,7 +1639,7 @@ impl TableRefBuilder for CommonSqlQueryBuilder {} allow(unreachable_code, unused_variables) )] pub(crate) fn common_inner_expr_well_known_greater_precedence( - inner: &SimpleExpr, + inner: &Expr, outer_oper: &Oper, ) -> bool { match inner { @@ -1658,15 +1648,15 @@ pub(crate) fn common_inner_expr_well_known_greater_precedence( // We do not need to wrap with parentheses: // Columns, tuples (already wrapped), constants, function calls, values, // keywords, subqueries (already wrapped), case (already wrapped) - SimpleExpr::Column(_) - | SimpleExpr::Tuple(_) - | SimpleExpr::Constant(_) - | SimpleExpr::FunctionCall(_) - | SimpleExpr::Value(_) - | SimpleExpr::Keyword(_) - | SimpleExpr::Case(_) - | SimpleExpr::SubQuery(_, _) => true, - SimpleExpr::Binary(_, inner_oper, _) => { + Expr::Column(_) + | Expr::Tuple(_) + | Expr::Constant(_) + | Expr::FunctionCall(_) + | Expr::Value(_) + | Expr::Keyword(_) + | Expr::Case(_) + | Expr::SubQuery(_, _) => true, + Expr::Binary(_, inner_oper, _) => { #[cfg(feature = "option-more-parentheses")] { return false; diff --git a/src/backend/sqlite/mod.rs b/src/backend/sqlite/mod.rs index b884cc5ed..968726efe 100644 --- a/src/backend/sqlite/mod.rs +++ b/src/backend/sqlite/mod.rs @@ -36,7 +36,7 @@ impl TableRefBuilder for SqliteQueryBuilder {} impl PrecedenceDecider for SqliteQueryBuilder { fn inner_expr_well_known_greater_precedence( &self, - inner: &SimpleExpr, + inner: &Expr, outer_oper: &Oper, ) -> bool { common_inner_expr_well_known_greater_precedence(inner, outer_oper) diff --git a/src/backend/table_builder.rs b/src/backend/table_builder.rs index 7520afd9b..c41b61572 100644 --- a/src/backend/table_builder.rs +++ b/src/backend/table_builder.rs @@ -195,14 +195,14 @@ pub trait TableBuilder: } /// Translate the check constraint into SQL statement - fn prepare_check_constraint(&self, check: &SimpleExpr, sql: &mut dyn SqlWriter) { + fn prepare_check_constraint(&self, check: &Expr, sql: &mut dyn SqlWriter) { write!(sql, "CHECK (").unwrap(); QueryBuilder::prepare_simple_expr(self, check, sql); write!(sql, ")").unwrap(); } /// Translate the generated column into SQL statement - fn prepare_generated_column(&self, gen: &SimpleExpr, stored: bool, sql: &mut dyn SqlWriter) { + fn prepare_generated_column(&self, gen: &Expr, stored: bool, sql: &mut dyn SqlWriter) { write!(sql, "GENERATED ALWAYS AS (").unwrap(); QueryBuilder::prepare_simple_expr(self, gen, sql); write!(sql, ")").unwrap(); diff --git a/src/expr.rs b/src/expr.rs index a765fc4e8..5a0828f68 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1,38 +1,28 @@ //! Building blocks of SQL statements. //! -//! [`Expr`] representing the primitive building block in the expressions. -//! -//! [`SimpleExpr`] is the expression common among select fields, where clauses and many other places. +//! [`Expr`] is the expression common among select fields, where clauses and many other places. use crate::{func::*, query::*, types::*, value::*}; -/// Helper to build a [`SimpleExpr`]. -#[derive(Debug, Clone)] -pub struct Expr { - pub(crate) left: SimpleExpr, - pub(crate) right: Option, - pub(crate) uopr: Option, - pub(crate) bopr: Option, -} - /// Represents a Simple Expression in SQL. /// -/// [`SimpleExpr`] is a node in the expression tree and can represent identifiers, function calls, +/// [`Expr`] is a node in the expression tree and can represent identifiers, function calls, /// various operators and sub-queries. #[derive(Debug, Clone, PartialEq)] -pub enum SimpleExpr { +#[non_exhaustive] +pub enum Expr { Column(ColumnRef), - Tuple(Vec), - Unary(UnOper, Box), + Tuple(Vec), + Unary(UnOper, Box), FunctionCall(FunctionCall), - Binary(Box, BinOper, Box), + Binary(Box, BinOper, Box), SubQuery(Option, Box), Value(Value), Values(Vec), Custom(String), - CustomWithExpr(String, Vec), + CustomWithExpr(String, Vec), Keyword(Keyword), - AsEnum(DynIden, Box), + AsEnum(DynIden, Box), Case(Box), Constant(Value), } @@ -40,7 +30,7 @@ pub enum SimpleExpr { /// "Operator" methods for building expressions. /// /// Before `sea_query` 0.32.0 (`sea_orm` 1.1.1), -/// these methods were awailable only on [`Expr`]/[`SimpleExpr`] +/// these methods were awailable only on [`Expr`]/[`Expr`] /// and you needed to manually construct these types first. /// /// Now, you can call them directly on any expression type: @@ -81,11 +71,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 + 1 = 2"# /// ); /// ``` - fn add(self, right: R) -> SimpleExpr + fn add(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::Add, right) + self.binary(BinOper::Add, right) } /// Express a `AS enum` expression. @@ -115,15 +105,15 @@ pub trait ExprTrait: Sized { /// ); /// ``` #[allow(clippy::wrong_self_convention)] - fn as_enum(self, type_name: N) -> SimpleExpr + fn as_enum(self, type_name: N) -> Expr where N: IntoIden; - fn and(self, right: R) -> SimpleExpr + fn and(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::And, right) + self.binary(BinOper::And, right) } /// Express a `BETWEEN` expression. @@ -152,14 +142,14 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" BETWEEN 1 AND 10"# /// ); /// ``` - fn between(self, a: A, b: B) -> SimpleExpr + fn between(self, a: A, b: B) -> Expr where - A: Into, - B: Into, + A: Into, + B: Into, { self.binary( BinOper::Between, - SimpleExpr::Binary(Box::new(a.into()), BinOper::And, Box::new(b.into())), + Expr::Binary(Box::new(a.into()), BinOper::And, Box::new(b.into())), ) } @@ -190,10 +180,10 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "size_w" < 10 AND "size_w" > "size_h""# /// ); /// ``` - fn binary(self, op: O, right: R) -> SimpleExpr + fn binary(self, op: O, right: R) -> Expr where O: Into, - R: Into; + R: Into; /// Express a `CAST AS` expression. /// @@ -217,7 +207,7 @@ pub trait ExprTrait: Sized { /// r#"SELECT CAST('1' AS integer)"# /// ); /// ``` - fn cast_as(self, type_name: N) -> SimpleExpr + fn cast_as(self, type_name: N) -> Expr where N: IntoIden; @@ -247,11 +237,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 / 1 = 2"# /// ); /// ``` - fn div(self, right: R) -> SimpleExpr + fn div(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::Div, right) + self.binary(BinOper::Div, right) } /// Express an equal (`=`) expression. @@ -282,11 +272,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'What!' = 'Nothing' AND "id" = 1"# /// ); /// ``` - fn eq(self, right: R) -> SimpleExpr + fn eq(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::Equal, right) + self.binary(BinOper::Equal, right) } /// Express a equal expression between two table columns, @@ -316,7 +306,7 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" = "font"."id""# /// ); /// ``` - fn equals(self, col: C) -> SimpleExpr + fn equals(self, col: C) -> Expr where C: IntoColumnRef, { @@ -349,11 +339,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" > 2"# /// ); /// ``` - fn gt(self, right: R) -> SimpleExpr + fn gt(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::GreaterThan, right) + self.binary(BinOper::GreaterThan, right) } /// Express a greater than or equal (`>=`) expression. @@ -382,11 +372,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" >= 2"# /// ); /// ``` - fn gte(self, right: R) -> SimpleExpr + fn gte(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::GreaterThanOrEqual, right) + self.binary(BinOper::GreaterThanOrEqual, right) } /// Express a `IN` sub-query expression. @@ -419,10 +409,10 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "size_w" IN (SELECT 3 + 2 * 2)"# /// ); /// ``` - fn in_subquery(self, sel: SelectStatement) -> SimpleExpr { + fn in_subquery(self, sel: SelectStatement) -> Expr { self.binary( BinOper::In, - SimpleExpr::SubQuery(None, Box::new(sel.into_sub_query_statement())), + Expr::SubQuery(None, Box::new(sel.into_sub_query_statement())), ) } @@ -462,16 +452,16 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "font_id" FROM "character" WHERE ("character", "font_id") IN ((1, '1'), (2, '2'))"# /// ); /// ``` - fn in_tuples(self, v: I) -> SimpleExpr + fn in_tuples(self, v: I) -> Expr where V: IntoValueTuple, I: IntoIterator, { self.binary( BinOper::In, - SimpleExpr::Tuple( + Expr::Tuple( v.into_iter() - .map(|m| SimpleExpr::Values(m.into_value_tuple().into_iter().collect())) + .map(|m| Expr::Values(m.into_value_tuple().into_iter().collect())) .collect(), ), ) @@ -503,9 +493,9 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."ascii" IS TRUE"# /// ); /// ``` - fn is(self, right: R) -> SimpleExpr + fn is(self, right: R) -> Expr where - R: Into, + R: Into, { self.binary(BinOper::Is, right) } @@ -568,14 +558,14 @@ pub trait ExprTrait: Sized { /// ); /// ``` #[allow(clippy::wrong_self_convention)] - fn is_in(self, v: I) -> SimpleExpr + fn is_in(self, v: I) -> Expr where - V: Into, + V: Into, I: IntoIterator, { self.binary( BinOper::In, - SimpleExpr::Tuple(v.into_iter().map(|v| v.into()).collect()), + Expr::Tuple(v.into_iter().map(|v| v.into()).collect()), ) } @@ -606,9 +596,9 @@ pub trait ExprTrait: Sized { /// ); /// ``` #[allow(clippy::wrong_self_convention)] - fn is_not(self, right: R) -> SimpleExpr + fn is_not(self, right: R) -> Expr where - R: Into, + R: Into, { self.binary(BinOper::IsNot, right) } @@ -671,14 +661,14 @@ pub trait ExprTrait: Sized { /// ); /// ``` #[allow(clippy::wrong_self_convention)] - fn is_not_in(self, v: I) -> SimpleExpr + fn is_not_in(self, v: I) -> Expr where - V: Into, + V: Into, I: IntoIterator, { self.binary( BinOper::NotIn, - SimpleExpr::Tuple(v.into_iter().map(|v| v.into()).collect()), + Expr::Tuple(v.into_iter().map(|v| v.into()).collect()), ) } @@ -709,7 +699,7 @@ pub trait ExprTrait: Sized { /// ); /// ``` #[allow(clippy::wrong_self_convention)] - fn is_not_null(self) -> SimpleExpr { + fn is_not_null(self) -> Expr { self.binary(BinOper::IsNot, Keyword::Null) } @@ -740,7 +730,7 @@ pub trait ExprTrait: Sized { /// ); /// ``` #[allow(clippy::wrong_self_convention)] - fn is_null(self) -> SimpleExpr { + fn is_null(self) -> Expr { self.binary(BinOper::Is, Keyword::Null) } @@ -770,9 +760,9 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 << 1 = 2"# /// ); /// ``` - fn left_shift(self, right: R) -> SimpleExpr + fn left_shift(self, right: R) -> Expr where - R: Into, + R: Into, { self.binary(BinOper::LShift, right) } @@ -828,11 +818,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."character" LIKE '|_Our|_' ESCAPE '|'"# /// ); /// ``` - fn like(self, like: L) -> SimpleExpr + fn like(self, like: L) -> Expr where L: IntoLikeExpr, { - ExprTrait::binary(self, BinOper::Like, like.into_like_expr()) + self.binary(BinOper::Like, like.into_like_expr()) } /// Express a less than (`<`) expression. @@ -861,11 +851,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" < 2"# /// ); /// ``` - fn lt(self, right: R) -> SimpleExpr + fn lt(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::SmallerThan, right) + self.binary(BinOper::SmallerThan, right) } /// Express a less than or equal (`<=`) expression. @@ -894,11 +884,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" <= 2"# /// ); /// ``` - fn lte(self, right: R) -> SimpleExpr + fn lte(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::SmallerThanOrEqual, right) + self.binary(BinOper::SmallerThanOrEqual, right) } /// Express an arithmetic modulo operation. @@ -927,9 +917,9 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 % 1 = 2"# /// ); /// ``` - fn modulo(self, right: R) -> SimpleExpr + fn modulo(self, right: R) -> Expr where - R: Into, + R: Into, { self.binary(BinOper::Mod, right) } @@ -960,11 +950,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 * 1 = 2"# /// ); /// ``` - fn mul(self, right: R) -> SimpleExpr + fn mul(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::Mul, right) + self.binary(BinOper::Mul, right) } /// Express a not equal (`<>`) expression. @@ -995,11 +985,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'Morning' <> 'Good' AND "id" <> 1"# /// ); /// ``` - fn ne(self, right: R) -> SimpleExpr + fn ne(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::NotEqual, right) + self.binary(BinOper::NotEqual, right) } /// Negates an expression with `NOT`. @@ -1028,7 +1018,7 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE NOT "character"."size_w" IS NULL"# /// ); /// ``` - fn not(self) -> SimpleExpr { + fn not(self) -> Expr { self.unary(UnOper::Not) } @@ -1058,14 +1048,14 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" NOT BETWEEN 1 AND 10"# /// ); /// ``` - fn not_between(self, a: A, b: B) -> SimpleExpr + fn not_between(self, a: A, b: B) -> Expr where - A: Into, - B: Into, + A: Into, + B: Into, { self.binary( BinOper::NotBetween, - SimpleExpr::Binary(Box::new(a.into()), BinOper::And, Box::new(b.into())), + Expr::Binary(Box::new(a.into()), BinOper::And, Box::new(b.into())), ) } @@ -1096,7 +1086,7 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" <> "font"."id""# /// ); /// ``` - fn not_equals(self, col: C) -> SimpleExpr + fn not_equals(self, col: C) -> Expr where C: IntoColumnRef, { @@ -1133,10 +1123,10 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "size_w" NOT IN (SELECT 3 + 2 * 2)"# /// ); /// ``` - fn not_in_subquery(self, sel: SelectStatement) -> SimpleExpr { + fn not_in_subquery(self, sel: SelectStatement) -> Expr { self.binary( BinOper::NotIn, - SimpleExpr::SubQuery(None, Box::new(sel.into_sub_query_statement())), + Expr::SubQuery(None, Box::new(sel.into_sub_query_statement())), ) } @@ -1166,11 +1156,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."character" NOT LIKE 'Ours''%'"# /// ); /// ``` - fn not_like(self, like: L) -> SimpleExpr + fn not_like(self, like: L) -> Expr where L: IntoLikeExpr, { - ExprTrait::binary(self, BinOper::NotLike, like.into_like_expr()) + self.binary(BinOper::NotLike, like.into_like_expr()) } /// Express a logical `OR` operation. @@ -1199,11 +1189,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE FALSE OR TRUE"# /// ); /// ``` - fn or(self, right: R) -> SimpleExpr + fn or(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::Or, right) + self.binary(BinOper::Or, right) } /// Express a bitwise right shift. @@ -1232,9 +1222,9 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 >> 1 = 2"# /// ); /// ``` - fn right_shift(self, right: R) -> SimpleExpr + fn right_shift(self, right: R) -> Expr where - R: Into, + R: Into, { self.binary(BinOper::RShift, right) } @@ -1265,11 +1255,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 - 1 = 2"# /// ); /// ``` - fn sub(self, right: R) -> SimpleExpr + fn sub(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::Sub, right) + self.binary(BinOper::Sub, right) } /// Apply any unary operator to the expression. @@ -1298,7 +1288,7 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE NOT "character"."size_w" IS NULL"# /// ); /// ``` - fn unary(self, o: UnOper) -> SimpleExpr; + fn unary(self, o: UnOper) -> Expr; /// Express a bitwise AND operation. /// @@ -1333,11 +1323,11 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE (1 & 1) = 1"# /// ); /// ``` - fn bit_and(self, right: R) -> SimpleExpr + fn bit_and(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::BitAnd, right) + self.binary(BinOper::BitAnd, right) } /// Express a bitwise OR operation. @@ -1366,64 +1356,55 @@ pub trait ExprTrait: Sized { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE (1 | 1) = 1"# /// ); /// ``` - fn bit_or(self, right: R) -> SimpleExpr + fn bit_or(self, right: R) -> Expr where - R: Into, + R: Into, { - ExprTrait::binary(self, BinOper::BitOr, right) + self.binary(BinOper::BitOr, right) } } /// This generic implementation covers all expression types, -/// including [ColumnRef], [Value], [FunctionCall], [SimpleExpr]... +/// including [ColumnRef], [Value], [FunctionCall], [Expr]... impl ExprTrait for T where - T: Into, + T: Into, { - fn as_enum(self, type_name: N) -> SimpleExpr + fn as_enum(self, type_name: N) -> Expr where N: IntoIden, { - SimpleExpr::AsEnum(type_name.into_iden(), Box::new(self.into())) + Expr::AsEnum(type_name.into_iden(), Box::new(self.into())) } - fn binary(self, op: O, right: R) -> SimpleExpr + fn binary(self, op: O, right: R) -> Expr where O: Into, - R: Into, + R: Into, { - SimpleExpr::Binary(Box::new(self.into()), op.into(), Box::new(right.into())) + Expr::Binary(Box::new(self.into()), op.into(), Box::new(right.into())) } - fn cast_as(self, type_name: N) -> SimpleExpr + fn cast_as(self, type_name: N) -> Expr where N: IntoIden, { - SimpleExpr::FunctionCall(Func::cast_as(self, type_name)) + Expr::FunctionCall(Func::cast_as(self, type_name)) } - fn unary(self, op: UnOper) -> SimpleExpr { - SimpleExpr::Unary(op, Box::new(self.into())) + fn unary(self, op: UnOper) -> Expr { + Expr::Unary(op, Box::new(self.into())) } } impl Expr { - fn new_with_left(left: T) -> Self - where - T: Into, - { - let left = left.into(); - Self { - left, - right: None, - uopr: None, - bopr: None, - } + pub fn new(expr: impl Into) -> Self { + expr.into() } #[deprecated(since = "0.29.0", note = "Please use the [`Asterisk`]")] pub fn asterisk() -> Self { - Self::col(Asterisk) + Self::Column(Asterisk.into_column_ref()) } /// Express the target column without table prefix. @@ -1475,70 +1456,11 @@ impl Expr { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" = 1"# /// ); /// ``` - pub fn col(n: T) -> Self - where - T: IntoColumnRef, - { - Self::new_with_left(n.into_column_ref()) - } - - /// Express the target column without table prefix, returning a [`SimpleExpr`]. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::column(Char::SizeW).eq(1)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `size_w` = 1"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "size_w" = 1"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "size_w" = 1"# - /// ); - /// ``` - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::column((Char::Table, Char::SizeW)).eq(1)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`size_w` = 1"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" = 1"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" = 1"# - /// ); - /// ``` - pub fn column(n: T) -> SimpleExpr - where - T: IntoColumnRef, - { - SimpleExpr::Column(n.into_column_ref()) + pub fn col(n: impl IntoColumnRef) -> Self { + Self::Column(n.into_column_ref()) } - /// Wraps tuple of `SimpleExpr`, can be used for tuple comparison + /// Wraps tuple of `Expr`, can be used for tuple comparison /// /// # Examples /// @@ -1549,8 +1471,8 @@ impl Expr { /// .columns([Char::Character, Char::SizeW, Char::SizeH]) /// .from(Char::Table) /// .and_where( - /// Expr::tuple([Expr::col(Char::SizeW).into(), Expr::value(100)]) - /// .lt(Expr::tuple([Expr::value(500), Expr::value(100)]))) + /// Expr::tuple([Expr::col(Char::SizeW).into(), Expr::val(100)]) + /// .lt(Expr::tuple([Expr::val(500), Expr::val(100)]))) /// .to_owned(); /// /// assert_eq!( @@ -1566,24 +1488,16 @@ impl Expr { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE ("size_w", 100) < (500, 100)"# /// ); /// ``` - pub fn tuple(n: I) -> Self - where - I: IntoIterator, - { - Expr::expr(SimpleExpr::Tuple( - n.into_iter().collect::>(), - )) + pub fn tuple(n: impl IntoIterator) -> Self { + Expr::Tuple(n.into_iter().collect::>()) } #[deprecated(since = "0.29.0", note = "Please use the [`Asterisk`]")] - pub fn table_asterisk(t: T) -> Self - where - T: IntoIden, - { + pub fn table_asterisk(t: impl IntoIden) -> Self { Self::col((t.into_iden(), Asterisk)) } - /// Express a [`Value`], returning a [`Expr`]. + /// Express a [`Value`] /// /// # Examples /// @@ -1611,118 +1525,8 @@ impl Expr { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 AND 2.5 AND '3'"# /// ); /// ``` - pub fn val(v: V) -> Self - where - V: Into, - { - Self::new_with_left(v) - } - - /// Wrap an expression to perform some operation on it later. - /// - /// Since `sea_query` 0.32.0 (`sea_orm` 1.1.1), **this is not necessary** in most cases! - /// - /// Some SQL operations used to be defined only as inherent methods on [`Expr`]. - /// Thus, to use them, you needed to manually convert from other types to [`Expr`]. - /// But now these operations are also defined as [`ExprTrait`] methods - /// that can be called directly on any expression type, - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// // This is the old style, when `Expr::expr` was necessary: - /// .and_where(Expr::expr(Expr::col(Char::SizeW).if_null(0)).gt(2)) - /// .to_owned(); - /// - /// // But since 0.32.0, this compiles too: - /// let _ = Expr::col(Char::SizeW).if_null(0).gt(2); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE IFNULL(`size_w`, 0) > 2"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE COALESCE("size_w", 0) > 2"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE IFNULL("size_w", 0) > 2"# - /// ); - /// ``` - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .column(Char::Character) - /// .from(Char::Table) - /// // This is the old style, when `Expr::expr` was necessary: - /// .and_where(Expr::expr(Func::lower(Expr::col(Char::Character))).is_in(["a", "b"])) - /// .to_owned(); - /// - /// // But since 0.32.0, this compiles too: - /// let _ = Func::lower(Expr::col(Char::Character)).is_in(["a", "b"]); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character` FROM `character` WHERE LOWER(`character`) IN ('a', 'b')"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character" FROM "character" WHERE LOWER("character") IN ('a', 'b')"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character" FROM "character" WHERE LOWER("character") IN ('a', 'b')"# - /// ); - /// ``` - #[allow(clippy::self_named_constructors)] - pub fn expr(expr: T) -> Self - where - T: Into, - { - Self::new_with_left(expr) - } - - /// Express a [`Value`], returning a [`SimpleExpr`]. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::value(1)) - /// .and_where(Expr::value(2.5)) - /// .and_where(Expr::value("3")) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 1 AND 2.5 AND '3'"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 AND 2.5 AND '3'"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 AND 2.5 AND '3'"# - /// ); - /// ``` - pub fn value(v: V) -> SimpleExpr - where - V: Into, - { - v.into() + pub fn val(v: impl Into) -> Self { + Self::Value(v.into()) } /// Express any custom expression in [`&str`]. @@ -1751,11 +1555,8 @@ impl Expr { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 = 1"# /// ); /// ``` - pub fn cust(s: T) -> SimpleExpr - where - T: Into, - { - SimpleExpr::Custom(s.into()) + pub fn cust(s: impl Into) -> Self { + Expr::Custom(s.into()) } /// Express any custom expression with [`Value`]. Use this if your expression needs variables. @@ -1828,13 +1629,13 @@ impl Expr { /// r#"SELECT data @? ('hello'::JSONPATH)"# /// ); /// ``` - pub fn cust_with_values(s: T, v: I) -> SimpleExpr + pub fn cust_with_values(s: T, v: I) -> Self where T: Into, V: Into, I: IntoIterator, { - SimpleExpr::CustomWithExpr( + Expr::CustomWithExpr( s.into(), v.into_iter() .map(|v| Into::::into(v).into()) @@ -1842,7 +1643,7 @@ impl Expr { ) } - /// Express any custom expression with [`SimpleExpr`]. Use this if your expression needs other expression. + /// Express any custom expression with [`Expr`]. Use this if your expression needs other expression. /// /// # Examples /// @@ -1876,170 +1677,140 @@ impl Expr { /// r#"SELECT json_agg(DISTINCT "character")"# /// ); /// ``` - pub fn cust_with_expr(s: T, expr: E) -> SimpleExpr + pub fn cust_with_expr(s: T, expr: E) -> Self where T: Into, - E: Into, + E: Into, { - SimpleExpr::CustomWithExpr(s.into(), vec![expr.into()]) + Expr::CustomWithExpr(s.into(), vec![expr.into()]) } - /// Express any custom expression with [`SimpleExpr`]. Use this if your expression needs other expressions. - pub fn cust_with_exprs(s: T, v: I) -> SimpleExpr + /// Express any custom expression with [`Expr`]. Use this if your expression needs other expressions. + pub fn cust_with_exprs(s: T, v: I) -> Self where T: Into, - I: IntoIterator, + I: IntoIterator, { - SimpleExpr::CustomWithExpr(s.into(), v.into_iter().collect()) + Expr::CustomWithExpr(s.into(), v.into_iter().collect()) } - /// Express an equal (`=`) expression. - /// - /// This is equivalent to a newer [ExprTrait::eq] and may require more some wrapping beforehand. + /// Express a `MAX` function. /// /// # Examples /// /// ``` - /// use sea_query::{*, tests_cfg::*}; + /// use sea_query::{tests_cfg::*, *}; /// /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .expr(Expr::col((Char::Table, Char::SizeW)).max()) /// .from(Char::Table) - /// .and_where(Expr::val("What!").eq("Nothing")) - /// .and_where(Expr::col(Char::Id).eq(1)) /// .to_owned(); /// /// assert_eq!( /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 'What!' = 'Nothing' AND `id` = 1"# + /// r#"SELECT MAX(`character`.`size_w`) FROM `character`"# /// ); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'What!' = 'Nothing' AND "id" = 1"# + /// r#"SELECT MAX("character"."size_w") FROM "character""# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'What!' = 'Nothing' AND "id" = 1"# + /// r#"SELECT MAX("character"."size_w") FROM "character""# /// ); /// ``` - pub fn eq(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::eq(self, v) + pub fn max(self) -> Self { + Func::max(self).into() } - /// Express a not equal (`<>`) expression. - /// - /// This is equivalent to a newer [ExprTrait::ne] and may require more some wrapping beforehand. + /// Express a `MIN` function. /// /// # Examples /// /// ``` - /// use sea_query::{*, tests_cfg::*}; + /// use sea_query::{tests_cfg::*, *}; /// /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .expr(Expr::col((Char::Table, Char::SizeW)).min()) /// .from(Char::Table) - /// .and_where(Expr::val("Morning").ne("Good")) - /// .and_where(Expr::col(Char::Id).ne(1)) /// .to_owned(); /// /// assert_eq!( /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 'Morning' <> 'Good' AND `id` <> 1"# + /// r#"SELECT MIN(`character`.`size_w`) FROM `character`"# /// ); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'Morning' <> 'Good' AND "id" <> 1"# + /// r#"SELECT MIN("character"."size_w") FROM "character""# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'Morning' <> 'Good' AND "id" <> 1"# + /// r#"SELECT MIN("character"."size_w") FROM "character""# /// ); /// ``` - pub fn ne(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::ne(self, v) + pub fn min(self) -> Self { + Func::min(self).into() } - /// Express a equal expression between two table columns, - /// you will mainly use this to relate identical value between two table columns. - /// - /// This is equivalent to a newer [ExprTrait::equals] and may require more some wrapping beforehand. + /// Express a `SUM` function. /// /// # Examples /// /// ``` - /// use sea_query::{*, tests_cfg::*}; + /// use sea_query::{tests_cfg::*, *}; /// /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .expr(Expr::col((Char::Table, Char::SizeW)).sum()) /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::FontId)).equals((Font::Table, Font::Id))) /// .to_owned(); /// /// assert_eq!( /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`font_id` = `font`.`id`"# + /// r#"SELECT SUM(`character`.`size_w`) FROM `character`"# /// ); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" = "font"."id""# + /// r#"SELECT SUM("character"."size_w") FROM "character""# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" = "font"."id""# + /// r#"SELECT SUM("character"."size_w") FROM "character""# /// ); /// ``` - pub fn equals(self, col: C) -> SimpleExpr - where - C: IntoColumnRef, - { - ExprTrait::equals(self, col) + pub fn sum(self) -> Self { + Func::sum(self).into() } - /// Express a not equal expression between two table columns, - /// you will mainly use this to relate identical value between two table columns. - /// - /// This is equivalent to a newer [ExprTrait::not_equals] and may require more some wrapping beforehand. + /// Express a `COUNT` function. /// /// # Examples /// /// ``` - /// use sea_query::{*, tests_cfg::*}; + /// use sea_query::{tests_cfg::*, *}; /// /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .expr(Expr::col((Char::Table, Char::SizeW)).count()) /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::FontId)).not_equals((Font::Table, Font::Id))) /// .to_owned(); /// /// assert_eq!( /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`font_id` <> `font`.`id`"# + /// r#"SELECT COUNT(`character`.`size_w`) FROM `character`"# /// ); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" <> "font"."id""# + /// r#"SELECT COUNT("character"."size_w") FROM "character""# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" <> "font"."id""# + /// r#"SELECT COUNT("character"."size_w") FROM "character""# /// ); /// ``` - pub fn not_equals(self, col: C) -> SimpleExpr - where - C: IntoColumnRef, - { - ExprTrait::not_equals(self, col) + pub fn count(self) -> Self { + Func::count(self).into() } - /// Express a greater than (`>`) expression. - /// - /// This is equivalent to a newer [ExprTrait::gt] and may require more some wrapping beforehand. + /// Express a `COUNT` function with the DISTINCT modifier. /// /// # Examples /// @@ -2047,34 +1818,28 @@ impl Expr { /// use sea_query::{tests_cfg::*, *}; /// /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .expr(Expr::col((Char::Table, Char::SizeW)).count_distinct()) /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::SizeW)).gt(2)) /// .to_owned(); /// /// assert_eq!( /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`size_w` > 2"# + /// r#"SELECT COUNT(DISTINCT `character`.`size_w`) FROM `character`"# /// ); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" > 2"# + /// r#"SELECT COUNT(DISTINCT "character"."size_w") FROM "character""# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" > 2"# + /// r#"SELECT COUNT(DISTINCT "character"."size_w") FROM "character""# /// ); /// ``` - pub fn gt(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::gt(self, v) + pub fn count_distinct(self) -> Self { + Func::count_distinct(self).into() } - /// Express a greater than or equal (`>=`) expression. - /// - /// This is equivalent to a newer [ExprTrait::gte] and may require more some wrapping beforehand. + /// Express a `IF NULL` function. /// /// # Examples /// @@ -2082,69 +1847,63 @@ impl Expr { /// use sea_query::{tests_cfg::*, *}; /// /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .expr(Expr::col((Char::Table, Char::SizeW)).if_null(0)) /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::SizeW)).gte(2)) /// .to_owned(); /// /// assert_eq!( /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`size_w` >= 2"# + /// r#"SELECT IFNULL(`character`.`size_w`, 0) FROM `character`"# /// ); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" >= 2"# + /// r#"SELECT COALESCE("character"."size_w", 0) FROM "character""# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" >= 2"# + /// r#"SELECT IFNULL("character"."size_w", 0) FROM "character""# /// ); /// ``` - pub fn gte(self, v: V) -> SimpleExpr + pub fn if_null(self, v: V) -> Self where - V: Into, + V: Into, { - ExprTrait::gte(self, v) + Func::if_null(self, v).into() } - /// Express a less than (`<`) expression. - /// - /// This is equivalent to a newer [ExprTrait::lt] and may require more some wrapping beforehand. + /// Express a `EXISTS` sub-query expression. /// /// # Examples /// /// ``` - /// use sea_query::{tests_cfg::*, *}; + /// use sea_query::{*, tests_cfg::*}; /// /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::SizeW)).lt(2)) + /// .expr_as(Expr::exists(Query::select().column(Char::Id).from(Char::Table).take()), "character_exists") + /// .expr_as(Expr::exists(Query::select().column(Glyph::Id).from(Glyph::Table).take()), "glyph_exists") /// .to_owned(); /// /// assert_eq!( /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`size_w` < 2"# + /// r#"SELECT EXISTS(SELECT `id` FROM `character`) AS `character_exists`, EXISTS(SELECT `id` FROM `glyph`) AS `glyph_exists`"# /// ); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" < 2"# + /// r#"SELECT EXISTS(SELECT "id" FROM "character") AS "character_exists", EXISTS(SELECT "id" FROM "glyph") AS "glyph_exists""# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" < 2"# + /// r#"SELECT EXISTS(SELECT "id" FROM "character") AS "character_exists", EXISTS(SELECT "id" FROM "glyph") AS "glyph_exists""# /// ); /// ``` - pub fn lt(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::lt(self, v) + pub fn exists(sel: SelectStatement) -> Self { + Expr::SubQuery( + Some(SubQueryOper::Exists), + Box::new(sel.into_sub_query_statement()), + ) } - /// Express a less than or equal (`<=`) expression. - /// - /// This is equivalent to a newer [ExprTrait::lte] and may require more some wrapping beforehand. + /// Express a `ANY` sub-query expression. /// /// # Examples /// @@ -2152,1540 +1911,30 @@ impl Expr { /// use sea_query::{tests_cfg::*, *}; /// /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::SizeW)).lte(2)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`size_w` <= 2"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" <= 2"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" <= 2"# - /// ); - /// ``` - pub fn lte(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::lte(self, v) - } - - /// Express an arithmetic addition operation. - /// - /// This is equivalent to a newer [ExprTrait::add] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::val(1).add(1).eq(2)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 1 + 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 + 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 + 1 = 2"# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn add(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::add(self, v) - } - - /// Express an arithmetic subtraction operation. - /// - /// This is equivalent to a newer [ExprTrait::sub] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::val(1).sub(1).eq(2)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 1 - 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 - 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 - 1 = 2"# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn sub(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::sub(self, v) - } - - /// Express an arithmetic multiplication operation. - /// - /// This is equivalent to a newer [ExprTrait::mul] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::val(1).mul(1).eq(2)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 1 * 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 * 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 * 1 = 2"# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn mul(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::mul(self, v) - } - - /// Express an arithmetic division operation. - /// - /// This is equivalent to a newer [ExprTrait::div] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::val(1).div(1).eq(2)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 1 / 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 / 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 / 1 = 2"# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn div(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::div(self, v) - } - - /// Express an arithmetic modulo operation. - /// - /// This is equivalent to a newer [ExprTrait::modulo] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::val(1).modulo(1).eq(2)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 1 % 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 % 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 % 1 = 2"# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn modulo(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::modulo(self, v) - } - - /// Express a bitwise left shift. - /// - /// This is equivalent to a newer [ExprTrait::left_shift] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::val(1).left_shift(1).eq(2)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 1 << 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 << 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 << 1 = 2"# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn left_shift(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::left_shift(self, v) - } - - /// Express a bitwise right shift. - /// - /// This is equivalent to a newer [ExprTrait::right_shift] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::val(1).right_shift(1).eq(2)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 1 >> 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 >> 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 >> 1 = 2"# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn right_shift(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::right_shift(self, v) - } - - /// Express a `BETWEEN` expression. - /// - /// This is equivalent to a newer [ExprTrait::between] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::SizeW)).between(1, 10)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`size_w` BETWEEN 1 AND 10"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" BETWEEN 1 AND 10"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" BETWEEN 1 AND 10"# - /// ); - /// ``` - pub fn between(self, a: V, b: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::between(self, a, b) - } - - /// Express a `NOT BETWEEN` expression. - /// - /// This is equivalent to a newer [ExprTrait::not_between] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::SizeW)).not_between(1, 10)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`size_w` NOT BETWEEN 1 AND 10"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" NOT BETWEEN 1 AND 10"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" NOT BETWEEN 1 AND 10"# - /// ); - /// ``` - pub fn not_between(self, a: V, b: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::not_between(self, a, b) - } - - /// Express a `LIKE` expression. - /// - /// This is equivalent to a newer [ExprTrait::like] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::Character)).like("Ours'%")) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`character` LIKE 'Ours\'%'"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."character" LIKE E'Ours\'%'"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."character" LIKE 'Ours''%'"# - /// ); - /// ``` - /// - /// Like with ESCAPE - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::Character)).like(LikeExpr::new(r"|_Our|_").escape('|'))) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`character` LIKE '|_Our|_' ESCAPE '|'"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."character" LIKE '|_Our|_' ESCAPE '|'"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."character" LIKE '|_Our|_' ESCAPE '|'"# - /// ); - /// ``` - pub fn like(self, like: L) -> SimpleExpr { - ExprTrait::like(self, like) - } - - /// Express a `NOT LIKE` expression. - /// - /// This is equivalent to a newer [ExprTrait::not_like] and may require more some wrapping beforehand. - pub fn not_like(self, like: L) -> SimpleExpr { - ExprTrait::not_like(self, like) - } - - /// Express a `IS NULL` expression. - /// - /// This is equivalent to a newer [ExprTrait::is_null] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::SizeW)).is_null()) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`size_w` IS NULL"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" IS NULL"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" IS NULL"# - /// ); - /// ``` - #[allow(clippy::wrong_self_convention)] - pub fn is_null(self) -> SimpleExpr { - ExprTrait::is_null(self) - } - - /// Express a `IS` expression. - /// - /// This is equivalent to a newer [ExprTrait::is] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::Ascii)).is(true)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`ascii` IS TRUE"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."ascii" IS TRUE"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."ascii" IS TRUE"# - /// ); - /// ``` - pub fn is(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::is(self, v) - } - - /// Express a `IS NOT NULL` expression. - /// - /// This is equivalent to a newer [ExprTrait::is_not_null] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::SizeW)).is_not_null()) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`size_w` IS NOT NULL"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" IS NOT NULL"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" IS NOT NULL"# - /// ); - /// ``` - #[allow(clippy::wrong_self_convention)] - pub fn is_not_null(self) -> SimpleExpr { - ExprTrait::is_not_null(self) - } - - /// Express a `IS NOT` expression. - /// - /// This is equivalent to a newer [ExprTrait::is_not] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::Ascii)).is_not(true)) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`ascii` IS NOT TRUE"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."ascii" IS NOT TRUE"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."ascii" IS NOT TRUE"# - /// ); - /// ``` - pub fn is_not(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::is_not(self, v) - } - - /// Create any binary operation - /// - /// This is equivalent to a newer [ExprTrait::binary] and may require more some wrapping beforehand. - /// - /// # Examples - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .cond_where(all![ - /// Expr::col(Char::SizeW).binary(BinOper::SmallerThan, 10), - /// Expr::col(Char::SizeW).binary(BinOper::GreaterThan, Expr::col(Char::SizeH)) - /// ]) - /// .to_owned(); - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `size_w` < 10 AND `size_w` > `size_h`"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "size_w" < 10 AND "size_w" > "size_h""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "size_w" < 10 AND "size_w" > "size_h""# - /// ); - /// ``` - pub fn binary(self, op: O, right: T) -> SimpleExpr - where - O: Into, - T: Into, - { - ExprTrait::binary(self, op, right) - } - - /// Negates an expression with `NOT`. - /// - /// This is equivalent to a newer [ExprTrait::not] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// // Before 0.32.0, you had call `not` on an `Expr`, which had to be constructed using `Expr::expr`: - /// .and_where(Expr::expr(Expr::col((Char::Table, Char::SizeW)).is_null()).not()) - /// .to_owned(); - /// - /// // But since 0.32.0, this compiles too: - /// let _ = Expr::col((Char::Table, Char::SizeW)).is_null().not(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE NOT `character`.`size_w` IS NULL"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE NOT "character"."size_w" IS NULL"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE NOT "character"."size_w" IS NULL"# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn not(self) -> SimpleExpr { - ExprTrait::not(self) - } - - /// Express a `MAX` function. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .expr(Expr::col((Char::Table, Char::SizeW)).max()) - /// .from(Char::Table) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT MAX(`character`.`size_w`) FROM `character`"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT MAX("character"."size_w") FROM "character""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT MAX("character"."size_w") FROM "character""# - /// ); - /// ``` - pub fn max(self) -> SimpleExpr { - Func::max(self.left).into() - } - - /// Express a `MIN` function. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .expr(Expr::col((Char::Table, Char::SizeW)).min()) - /// .from(Char::Table) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT MIN(`character`.`size_w`) FROM `character`"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT MIN("character"."size_w") FROM "character""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT MIN("character"."size_w") FROM "character""# - /// ); - /// ``` - pub fn min(self) -> SimpleExpr { - Func::min(self.left).into() - } - - /// Express a `SUM` function. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .expr(Expr::col((Char::Table, Char::SizeW)).sum()) - /// .from(Char::Table) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT SUM(`character`.`size_w`) FROM `character`"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT SUM("character"."size_w") FROM "character""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT SUM("character"."size_w") FROM "character""# - /// ); - /// ``` - pub fn sum(self) -> SimpleExpr { - Func::sum(self.left).into() - } - - /// Express a `COUNT` function. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .expr(Expr::col((Char::Table, Char::SizeW)).count()) - /// .from(Char::Table) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT COUNT(`character`.`size_w`) FROM `character`"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT COUNT("character"."size_w") FROM "character""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT COUNT("character"."size_w") FROM "character""# - /// ); - /// ``` - pub fn count(self) -> SimpleExpr { - Func::count(self.left).into() - } - - /// Express a `COUNT` function with the DISTINCT modifier. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .expr(Expr::col((Char::Table, Char::SizeW)).count_distinct()) - /// .from(Char::Table) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT COUNT(DISTINCT `character`.`size_w`) FROM `character`"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT COUNT(DISTINCT "character"."size_w") FROM "character""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT COUNT(DISTINCT "character"."size_w") FROM "character""# - /// ); - /// ``` - pub fn count_distinct(self) -> SimpleExpr { - Func::count_distinct(self.left).into() - } - - /// Express a `IF NULL` function. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .expr(Expr::col((Char::Table, Char::SizeW)).if_null(0)) - /// .from(Char::Table) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT IFNULL(`character`.`size_w`, 0) FROM `character`"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT COALESCE("character"."size_w", 0) FROM "character""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT IFNULL("character"."size_w", 0) FROM "character""# - /// ); - /// ``` - pub fn if_null(self, v: V) -> SimpleExpr - where - V: Into, - { - Func::if_null(self.left, v).into() - } - - /// Express a `IN` expression. - /// - /// This is equivalent to a newer [ExprTrait::is_in] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Id]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::SizeW)).is_in([1, 2, 3])) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `id` FROM `character` WHERE `character`.`size_w` IN (1, 2, 3)"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "id" FROM "character" WHERE "character"."size_w" IN (1, 2, 3)"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "id" FROM "character" WHERE "character"."size_w" IN (1, 2, 3)"# - /// ); - /// ``` - /// Empty value list - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Id]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::SizeW)).is_in(Vec::::new())) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `id` FROM `character` WHERE 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "id" FROM "character" WHERE 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "id" FROM "character" WHERE 1 = 2"# - /// ); - /// ``` - #[allow(clippy::wrong_self_convention)] - pub fn is_in(self, v: I) -> SimpleExpr - where - V: Into, - I: IntoIterator, - { - ExprTrait::is_in(self, v) - } - - /// Express a `IN` sub expression. - /// - /// This is equivalent to a newer [ExprTrait::in_tuples] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::FontId]) - /// .from(Char::Table) - /// .and_where( - /// Expr::tuple([ - /// Expr::col(Char::Character).into(), - /// Expr::col(Char::FontId).into(), - /// ]) - /// .in_tuples([(1, String::from("1")), (2, String::from("2"))]) - /// ) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `font_id` FROM `character` WHERE (`character`, `font_id`) IN ((1, '1'), (2, '2'))"# - /// ); - /// - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "font_id" FROM "character" WHERE ("character", "font_id") IN ((1, '1'), (2, '2'))"# - /// ); - /// - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "font_id" FROM "character" WHERE ("character", "font_id") IN ((1, '1'), (2, '2'))"# - /// ); - /// ``` - #[allow(clippy::wrong_self_convention)] - pub fn in_tuples(self, v: I) -> SimpleExpr - where - V: IntoValueTuple, - I: IntoIterator, - { - ExprTrait::in_tuples(self, v) - } - - /// Express a `NOT IN` expression. - /// - /// This is equivalent to a newer [ExprTrait::is_not_in] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Id]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::SizeW)).is_not_in([1, 2, 3])) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `id` FROM `character` WHERE `character`.`size_w` NOT IN (1, 2, 3)"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "id" FROM "character" WHERE "character"."size_w" NOT IN (1, 2, 3)"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "id" FROM "character" WHERE "character"."size_w" NOT IN (1, 2, 3)"# - /// ); - /// ``` - /// Empty value list - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Id]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::SizeW)).is_not_in(Vec::::new())) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `id` FROM `character` WHERE 1 = 1"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "id" FROM "character" WHERE 1 = 1"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "id" FROM "character" WHERE 1 = 1"# - /// ); - /// ``` - #[allow(clippy::wrong_self_convention)] - pub fn is_not_in(self, v: I) -> SimpleExpr - where - V: Into, - I: IntoIterator, - { - ExprTrait::is_not_in(self, v) - } - - /// Express a `IN` sub-query expression. - /// - /// This is equivalent to a newer [ExprTrait::in_subquery] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col(Char::SizeW).in_subquery( - /// Query::select() - /// .expr(Expr::cust("3 + 2 * 2")) - /// .take() - /// )) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `size_w` IN (SELECT 3 + 2 * 2)"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "size_w" IN (SELECT 3 + 2 * 2)"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "size_w" IN (SELECT 3 + 2 * 2)"# - /// ); - /// ``` - #[allow(clippy::wrong_self_convention)] - pub fn in_subquery(self, sel: SelectStatement) -> SimpleExpr { - ExprTrait::in_subquery(self, sel) - } - - /// Express a `NOT IN` sub-query expression. - /// - /// This is equivalent to a newer [ExprTrait::not_in_subquery] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col(Char::SizeW).not_in_subquery( - /// Query::select() - /// .expr(Expr::cust("3 + 2 * 2")) - /// .take() - /// )) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `size_w` NOT IN (SELECT 3 + 2 * 2)"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "size_w" NOT IN (SELECT 3 + 2 * 2)"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "size_w" NOT IN (SELECT 3 + 2 * 2)"# - /// ); - /// ``` - #[allow(clippy::wrong_self_convention)] - pub fn not_in_subquery(self, sel: SelectStatement) -> SimpleExpr { - ExprTrait::not_in_subquery(self, sel) - } - - /// Express a `EXISTS` sub-query expression. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .expr_as(Expr::exists(Query::select().column(Char::Id).from(Char::Table).take()), "character_exists") - /// .expr_as(Expr::exists(Query::select().column(Glyph::Id).from(Glyph::Table).take()), "glyph_exists") - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT EXISTS(SELECT `id` FROM `character`) AS `character_exists`, EXISTS(SELECT `id` FROM `glyph`) AS `glyph_exists`"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT EXISTS(SELECT "id" FROM "character") AS "character_exists", EXISTS(SELECT "id" FROM "glyph") AS "glyph_exists""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT EXISTS(SELECT "id" FROM "character") AS "character_exists", EXISTS(SELECT "id" FROM "glyph") AS "glyph_exists""# - /// ); - /// ``` - pub fn exists(sel: SelectStatement) -> SimpleExpr { - SimpleExpr::SubQuery( - Some(SubQueryOper::Exists), - Box::new(sel.into_sub_query_statement()), - ) - } - - /// Express a `ANY` sub-query expression. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .column(Char::Id) - /// .from(Char::Table) - /// .and_where(Expr::col(Char::Id).eq(Expr::any( - /// Query::select().column(Char::Id).from(Char::Table).take(), - /// ))) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `id` FROM `character` WHERE `id` = ANY(SELECT `id` FROM `character`)"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "id" FROM "character" WHERE "id" = ANY(SELECT "id" FROM "character")"# - /// ); - /// ``` - pub fn any(sel: SelectStatement) -> SimpleExpr { - SimpleExpr::SubQuery( - Some(SubQueryOper::Any), - Box::new(sel.into_sub_query_statement()), - ) - } - - /// Express a `SOME` sub-query expression. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .column(Char::Id) - /// .from(Char::Table) - /// .and_where(Expr::col(Char::Id).ne(Expr::some( - /// Query::select().column(Char::Id).from(Char::Table).take(), - /// ))) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `id` FROM `character` WHERE `id` <> SOME(SELECT `id` FROM `character`)"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "id" FROM "character" WHERE "id" <> SOME(SELECT "id" FROM "character")"# - /// ); - /// ``` - pub fn some(sel: SelectStatement) -> SimpleExpr { - SimpleExpr::SubQuery( - Some(SubQueryOper::Some), - Box::new(sel.into_sub_query_statement()), - ) - } - - /// Express a `ALL` sub-query expression. - pub fn all(sel: SelectStatement) -> SimpleExpr { - SimpleExpr::SubQuery( - Some(SubQueryOper::All), - Box::new(sel.into_sub_query_statement()), - ) - } - - /// Express a `AS enum` expression. - /// - /// This is equivalent to a newer [ExprTrait::as_enum] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .expr(Expr::col(Char::FontSize).as_enum("text")) - /// .from(Char::Table) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `font_size` FROM `character`"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT CAST("font_size" AS "text") FROM "character""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "font_size" FROM "character""# - /// ); - /// - /// struct TextArray; - /// - /// impl Iden for TextArray { - /// fn unquoted(&self, s: &mut dyn std::fmt::Write) { - /// write!(s, "text[]").unwrap(); - /// } - /// } - /// - /// let query = Query::select() - /// .expr(Expr::col(Char::FontSize).as_enum(TextArray)) - /// .from(Char::Table) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `font_size` FROM `character`"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT CAST("font_size" AS "text"[]) FROM "character""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "font_size" FROM "character""# - /// ); - /// - /// let query = Query::insert() - /// .into_table(Char::Table) - /// .columns([Char::FontSize]) - /// .values_panic([Expr::val("large").as_enum("FontSizeEnum")]) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"INSERT INTO `character` (`font_size`) VALUES ('large')"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"INSERT INTO "character" ("font_size") VALUES (CAST('large' AS "FontSizeEnum"))"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"INSERT INTO "character" ("font_size") VALUES ('large')"# - /// ); - /// ``` - pub fn as_enum(self, type_name: T) -> SimpleExpr - where - T: IntoIden, - { - ExprTrait::as_enum(self, type_name) - } - - /// Adds new `CASE WHEN` to existing case statement. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .expr_as( - /// Expr::case( - /// Expr::col((Glyph::Table, Glyph::Aspect)).is_in([2, 4]), - /// true - /// ) - /// .finally(false), - /// "is_even" - /// ) - /// .from(Glyph::Table) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT (CASE WHEN ("glyph"."aspect" IN (2, 4)) THEN TRUE ELSE FALSE END) AS "is_even" FROM "glyph""# - /// ); - /// ``` - pub fn case(cond: C, then: T) -> CaseStatement - where - C: IntoCondition, - T: Into, - { - CaseStatement::new().case(cond, then) - } - - /// Express a `CAST AS` expression. - /// - /// This is equivalent to a newer [ExprTrait::cast_as] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .expr(Expr::val("1").cast_as("integer")) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT CAST('1' AS integer)"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT CAST('1' AS integer)"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT CAST('1' AS integer)"# - /// ); - /// ``` - pub fn cast_as(self, type_name: T) -> SimpleExpr - where - T: IntoIden, - { - ExprTrait::cast_as(self, type_name) - } - - /// Keyword `CURRENT_DATE`. - /// - /// # Examples - /// - /// ``` - /// use sea_query::*; - /// - /// let query = Query::select().expr(Expr::current_date()).to_owned(); - /// - /// assert_eq!(query.to_string(MysqlQueryBuilder), r#"SELECT CURRENT_DATE"#); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT CURRENT_DATE"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT CURRENT_DATE"# - /// ); - /// ``` - pub fn current_date() -> Expr { - Expr::new_with_left(Keyword::CurrentDate) - } - - /// Keyword `CURRENT_TIMESTAMP`. - /// - /// # Examples - /// - /// ``` - /// use sea_query::*; - /// - /// let query = Query::select().expr(Expr::current_time()).to_owned(); - /// - /// assert_eq!(query.to_string(MysqlQueryBuilder), r#"SELECT CURRENT_TIME"#); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT CURRENT_TIME"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT CURRENT_TIME"# - /// ); - /// ``` - pub fn current_time() -> Expr { - Expr::new_with_left(Keyword::CurrentTime) - } - - /// Keyword `CURRENT_TIMESTAMP`. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{Expr, MysqlQueryBuilder, PostgresQueryBuilder, Query, SqliteQueryBuilder}; - /// - /// let query = Query::select().expr(Expr::current_timestamp()).to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT CURRENT_TIMESTAMP"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT CURRENT_TIMESTAMP"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT CURRENT_TIMESTAMP"# - /// ); - /// ``` - pub fn current_timestamp() -> Expr { - Expr::new_with_left(Keyword::CurrentTimestamp) - } - - /// Custom keyword. - /// - /// # Examples - /// - /// ``` - /// use sea_query::*; - /// - /// let query = Query::select() - /// .expr(Expr::custom_keyword("test")) - /// .to_owned(); - /// - /// assert_eq!(query.to_string(MysqlQueryBuilder), r#"SELECT test"#); - /// assert_eq!(query.to_string(PostgresQueryBuilder), r#"SELECT test"#); - /// assert_eq!(query.to_string(SqliteQueryBuilder), r#"SELECT test"#); - /// ``` - pub fn custom_keyword(i: T) -> Expr - where - T: IntoIden, - { - Expr::new_with_left(Keyword::Custom(i.into_iden())) - } -} - -impl From for SimpleExpr { - /// Convert into SimpleExpr - fn from(src: Expr) -> Self { - if let Some(uopr) = src.uopr { - SimpleExpr::Unary(uopr, Box::new(src.left)) - } else if let Some(bopr) = src.bopr { - SimpleExpr::Binary(Box::new(src.left), bopr, Box::new(src.right.unwrap())) - } else { - src.left - } - } -} - -impl From for SimpleExpr -where - T: Into, -{ - fn from(v: T) -> Self { - SimpleExpr::Value(v.into()) - } -} - -impl From for SimpleExpr { - fn from(func: FunctionCall) -> Self { - SimpleExpr::FunctionCall(func) - } -} - -impl From for SimpleExpr { - fn from(col: ColumnRef) -> Self { - SimpleExpr::Column(col) - } -} - -impl From for SimpleExpr { - fn from(k: Keyword) -> Self { - SimpleExpr::Keyword(k) - } -} - -impl From for SimpleExpr { - fn from(like: LikeExpr) -> Self { - match like.escape { - Some(escape) => SimpleExpr::Binary( - Box::new(like.pattern.into()), - BinOper::Escape, - Box::new(SimpleExpr::Constant(escape.into())), - ), - None => like.pattern.into(), - } - } -} - -impl SimpleExpr { - /// Negates an expression with `NOT`. - /// - /// This is equivalent to a newer [ExprTrait::not] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .column(Char::SizeW) - /// .from(Char::Table) - /// .and_where(Expr::col(Char::SizeW).eq(1).not()) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `size_w` FROM `character` WHERE NOT `size_w` = 1"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "size_w" FROM "character" WHERE NOT "size_w" = 1"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "size_w" FROM "character" WHERE NOT "size_w" = 1"# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn not(self) -> SimpleExpr { - ExprTrait::not(self) - } - - /// Express a logical `AND` operation. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .cond_where(any![ - /// Expr::col(Char::SizeW).eq(1).and(Expr::col(Char::SizeH).eq(2)), - /// Expr::col(Char::SizeW).eq(3).and(Expr::col(Char::SizeH).eq(4)), - /// ]) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE (`size_w` = 1 AND `size_h` = 2) OR (`size_w` = 3 AND `size_h` = 4)"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE ("size_w" = 1 AND "size_h" = 2) OR ("size_w" = 3 AND "size_h" = 4)"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE ("size_w" = 1 AND "size_h" = 2) OR ("size_w" = 3 AND "size_h" = 4)"# - /// ); - /// ``` - pub fn and(self, right: SimpleExpr) -> Self { - ExprTrait::and(self, right) - } - - /// Express a logical `OR` operation. - /// - /// This is equivalent to a newer [ExprTrait::or] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .column(Char::Id) /// .from(Char::Table) - /// .and_where(Expr::col(Char::SizeW).eq(1).or(Expr::col(Char::SizeH).eq(2))) - /// .and_where(Expr::col(Char::SizeW).eq(3).or(Expr::col(Char::SizeH).eq(4))) + /// .and_where(Expr::col(Char::Id).eq(Expr::any( + /// Query::select().column(Char::Id).from(Char::Table).take(), + /// ))) /// .to_owned(); /// /// assert_eq!( /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE (`size_w` = 1 OR `size_h` = 2) AND (`size_w` = 3 OR `size_h` = 4)"# + /// r#"SELECT `id` FROM `character` WHERE `id` = ANY(SELECT `id` FROM `character`)"# /// ); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE ("size_w" = 1 OR "size_h" = 2) AND ("size_w" = 3 OR "size_h" = 4)"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE ("size_w" = 1 OR "size_h" = 2) AND ("size_w" = 3 OR "size_h" = 4)"# + /// r#"SELECT "id" FROM "character" WHERE "id" = ANY(SELECT "id" FROM "character")"# /// ); /// ``` - pub fn or(self, right: SimpleExpr) -> Self { - ExprTrait::or(self, right) + pub fn any(sel: SelectStatement) -> Self { + Expr::SubQuery( + Some(SubQueryOper::Any), + Box::new(sel.into_sub_query_statement()), + ) } - /// Express an equal (`=`) expression. - /// - /// This is equivalent to a newer [ExprTrait::eq] and may require more some wrapping beforehand. + /// Express a `SOME` sub-query expression. /// /// # Examples /// @@ -3693,255 +1942,205 @@ impl SimpleExpr { /// use sea_query::{tests_cfg::*, *}; /// /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .column(Char::Id) /// .from(Char::Table) - /// .and_where(Expr::value("What!").eq("Nothing")) + /// .and_where(Expr::col(Char::Id).ne(Expr::some( + /// Query::select().column(Char::Id).from(Char::Table).take(), + /// ))) /// .to_owned(); /// /// assert_eq!( /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 'What!' = 'Nothing'"# + /// r#"SELECT `id` FROM `character` WHERE `id` <> SOME(SELECT `id` FROM `character`)"# /// ); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'What!' = 'Nothing'"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'What!' = 'Nothing'"# + /// r#"SELECT "id" FROM "character" WHERE "id" <> SOME(SELECT "id" FROM "character")"# /// ); /// ``` - pub fn eq(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::eq(self, v) + pub fn some(sel: SelectStatement) -> Self { + Self::SubQuery( + Some(SubQueryOper::Some), + Box::new(sel.into_sub_query_statement()), + ) } - /// Express a not equal (`<>`) expression. - /// - /// This is equivalent to a newer [ExprTrait::ne] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::value("Morning").ne("Good")) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 'Morning' <> 'Good'"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'Morning' <> 'Good'"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'Morning' <> 'Good'"# - /// ); - /// ``` - pub fn ne(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::ne(self, v) + /// Express a `ALL` sub-query expression. + pub fn all(sel: SelectStatement) -> Self { + Self::SubQuery( + Some(SubQueryOper::All), + Box::new(sel.into_sub_query_statement()), + ) } - /// Perform addition with another [`SimpleExpr`]. - /// - /// This is equivalent to a newer [ExprTrait::add] and may require more some wrapping beforehand. + /// Adds new `CASE WHEN` to existing case statement. /// /// # Examples /// /// ``` - /// use sea_query::{tests_cfg::*, *}; + /// use sea_query::{*, tests_cfg::*}; /// /// let query = Query::select() - /// .expr( - /// Expr::col(Char::SizeW) - /// .max() - /// .add(Expr::col(Char::SizeH).max()), + /// .expr_as( + /// Expr::case( + /// Expr::col((Glyph::Table, Glyph::Aspect)).is_in([2, 4]), + /// true + /// ) + /// .finally(false), + /// "is_even" /// ) - /// .from(Char::Table) + /// .from(Glyph::Table) /// .to_owned(); /// /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT MAX(`size_w`) + MAX(`size_h`) FROM `character`"# - /// ); - /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT MAX("size_w") + MAX("size_h") FROM "character""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT MAX("size_w") + MAX("size_h") FROM "character""# + /// r#"SELECT (CASE WHEN ("glyph"."aspect" IN (2, 4)) THEN TRUE ELSE FALSE END) AS "is_even" FROM "glyph""# /// ); /// ``` - #[allow(clippy::should_implement_trait)] - pub fn add(self, right: T) -> Self + pub fn case(cond: C, then: T) -> CaseStatement where - T: Into, + C: IntoCondition, + T: Into, { - ExprTrait::add(self, right) + CaseStatement::new().case(cond, then) } - /// Perform multiplication with another [`SimpleExpr`]. - /// - /// This is equivalent to a newer [ExprTrait::mul] and may require more some wrapping beforehand. + /// Keyword `CURRENT_DATE`. /// /// # Examples /// /// ``` - /// use sea_query::{tests_cfg::*, *}; + /// use sea_query::*; /// - /// let query = Query::select() - /// .expr( - /// Expr::col(Char::SizeW) - /// .max() - /// .mul(Expr::col(Char::SizeH).max()), - /// ) - /// .from(Char::Table) - /// .to_owned(); + /// let query = Query::select().expr(Expr::current_date()).to_owned(); /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT MAX(`size_w`) * MAX(`size_h`) FROM `character`"# - /// ); + /// assert_eq!(query.to_string(MysqlQueryBuilder), r#"SELECT CURRENT_DATE"#); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT MAX("size_w") * MAX("size_h") FROM "character""# + /// r#"SELECT CURRENT_DATE"# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT MAX("size_w") * MAX("size_h") FROM "character""# + /// r#"SELECT CURRENT_DATE"# /// ); /// ``` - #[allow(clippy::should_implement_trait)] - pub fn mul(self, right: T) -> Self - where - T: Into, - { - ExprTrait::mul(self, right) + pub fn current_date() -> Self { + Self::Keyword(Keyword::CurrentDate) } - /// Perform division with another [`SimpleExpr`]. - /// - /// This is equivalent to a newer [ExprTrait::div] and may require more some wrapping beforehand. + /// Keyword `CURRENT_TIMESTAMP`. /// /// # Examples /// /// ``` - /// use sea_query::{tests_cfg::*, *}; + /// use sea_query::*; /// - /// let query = Query::select() - /// .expr( - /// Expr::col(Char::SizeW) - /// .max() - /// .div(Expr::col(Char::SizeH).max()), - /// ) - /// .from(Char::Table) - /// .to_owned(); + /// let query = Query::select().expr(Expr::current_time()).to_owned(); /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT MAX(`size_w`) / MAX(`size_h`) FROM `character`"# - /// ); + /// assert_eq!(query.to_string(MysqlQueryBuilder), r#"SELECT CURRENT_TIME"#); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT MAX("size_w") / MAX("size_h") FROM "character""# + /// r#"SELECT CURRENT_TIME"# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT MAX("size_w") / MAX("size_h") FROM "character""# + /// r#"SELECT CURRENT_TIME"# /// ); /// ``` - #[allow(clippy::should_implement_trait)] - pub fn div(self, right: T) -> Self - where - T: Into, - { - ExprTrait::div(self, right) + pub fn current_time() -> Self { + Self::Keyword(Keyword::CurrentTime) } - /// Perform subtraction with another [`SimpleExpr`]. - /// - /// This is equivalent to a newer [ExprTrait::sub] and may require more some wrapping beforehand. + /// Keyword `CURRENT_TIMESTAMP`. /// /// # Examples /// /// ``` - /// use sea_query::{tests_cfg::*, *}; + /// use sea_query::{Expr, MysqlQueryBuilder, PostgresQueryBuilder, Query, SqliteQueryBuilder}; /// - /// let query = Query::select() - /// .expr( - /// Expr::col(Char::SizeW) - /// .max() - /// .sub(Expr::col(Char::SizeW).min()), - /// ) - /// .from(Char::Table) - /// .to_owned(); + /// let query = Query::select().expr(Expr::current_timestamp()).to_owned(); /// /// assert_eq!( /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT MAX(`size_w`) - MIN(`size_w`) FROM `character`"# + /// r#"SELECT CURRENT_TIMESTAMP"# /// ); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT MAX("size_w") - MIN("size_w") FROM "character""# + /// r#"SELECT CURRENT_TIMESTAMP"# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT MAX("size_w") - MIN("size_w") FROM "character""# + /// r#"SELECT CURRENT_TIMESTAMP"# /// ); /// ``` - #[allow(clippy::should_implement_trait)] - pub fn sub(self, right: T) -> Self - where - T: Into, - { - ExprTrait::sub(self, right) + pub fn current_timestamp() -> Self { + Self::Keyword(Keyword::CurrentTimestamp) } - /// Express a `CAST AS` expression. - /// - /// This is equivalent to a newer [ExprTrait::cast_as] and may require more some wrapping beforehand. + /// Custom keyword. /// /// # Examples /// /// ``` - /// use sea_query::{tests_cfg::*, *}; + /// use sea_query::*; /// /// let query = Query::select() - /// .expr(Expr::value("1").cast_as("integer")) + /// .expr(Expr::custom_keyword("test")) /// .to_owned(); /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT CAST('1' AS integer)"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT CAST('1' AS integer)"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT CAST('1' AS integer)"# - /// ); + /// assert_eq!(query.to_string(MysqlQueryBuilder), r#"SELECT test"#); + /// assert_eq!(query.to_string(PostgresQueryBuilder), r#"SELECT test"#); + /// assert_eq!(query.to_string(SqliteQueryBuilder), r#"SELECT test"#); /// ``` - pub fn cast_as(self, type_name: T) -> Self + pub fn custom_keyword(i: T) -> Self where T: IntoIden, { - ExprTrait::cast_as(self, type_name) + Self::Keyword(Keyword::Custom(i.into_iden())) + } +} + +impl From for Expr +where + T: Into, +{ + fn from(v: T) -> Self { + Expr::Value(v.into()) + } +} + +impl From for Expr { + fn from(func: FunctionCall) -> Self { + Expr::FunctionCall(func) + } +} + +impl From for Expr { + fn from(col: ColumnRef) -> Self { + Expr::Column(col) + } +} + +impl From for Expr { + fn from(k: Keyword) -> Self { + Expr::Keyword(k) + } +} + +impl From for Expr { + fn from(like: LikeExpr) -> Self { + match like.escape { + Some(escape) => Expr::Binary( + Box::new(like.pattern.into()), + BinOper::Escape, + Box::new(Expr::Constant(escape.into())), + ), + None => like.pattern.into(), + } } +} +impl Expr { /// Soft deprecated. This is not meant to be in the public API. #[doc(hidden)] pub fn cast_as_quoted(self, type_name: T, q: Quote) -> Self @@ -3952,81 +2151,6 @@ impl SimpleExpr { Self::FunctionCall(func) } - /// Create any binary operation - /// - /// This is equivalent to a newer [ExprTrait::add] and may require more some wrapping beforehand. - /// - /// # Examples - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .cond_where(all![ - /// Expr::value(10).binary(BinOper::SmallerThan, Expr::col(Char::SizeW)), - /// Expr::value(20).binary(BinOper::GreaterThan, Expr::col(Char::SizeH)) - /// ]) - /// .to_owned(); - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 10 < `size_w` AND 20 > `size_h`"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 10 < "size_w" AND 20 > "size_h""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 10 < "size_w" AND 20 > "size_h""# - /// ); - pub fn binary(self, op: O, right: T) -> Self - where - O: Into, - T: Into, - { - ExprTrait::binary(self, op, right) - } - - /// Express a `LIKE` expression. - /// - /// This is equivalent to a newer [ExprTrait::like] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{*, tests_cfg::*}; - /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::FontId)).cast_as("TEXT").like("a%")) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE CAST(`character`.`font_id` AS TEXT) LIKE 'a%'"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE CAST("character"."font_id" AS TEXT) LIKE 'a%'"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE CAST("character"."font_id" AS TEXT) LIKE 'a%'"# - /// ); - /// ``` - pub fn like(self, like: L) -> Self { - ExprTrait::like(self, like) - } - - /// Express a `NOT LIKE` expression. - /// - /// This is equivalent to a newer [ExprTrait::not_like] and may require more some wrapping beforehand. - pub fn not_like(self, like: L) -> Self { - ExprTrait::not_like(self, like) - } - pub(crate) fn is_binary(&self) -> bool { matches!(self, Self::Binary(_, _, _)) } diff --git a/src/extension/postgres/expr.rs b/src/extension/postgres/expr.rs index eccf3660a..db75faffe 100644 --- a/src/extension/postgres/expr.rs +++ b/src/extension/postgres/expr.rs @@ -1,7 +1,5 @@ use super::PgBinOper; -use crate::{ - ColumnRef, Expr, ExprTrait, FunctionCall, IntoLikeExpr, Keyword, LikeExpr, SimpleExpr, Value, -}; +use crate::{ColumnRef, Expr, ExprTrait, FunctionCall, IntoLikeExpr, Keyword, LikeExpr, Value}; /// Postgres-specific operator methods for building expressions. pub trait PgExpr: ExprTrait { @@ -23,16 +21,16 @@ pub trait PgExpr: ExprTrait { /// r#"SELECT "name", "variant", "language" FROM "font" WHERE 'a' || 'b' || 'c' || 'd'"# /// ); /// ``` - fn concatenate(self, right: T) -> SimpleExpr + fn concatenate(self, right: T) -> Expr where - T: Into, + T: Into, { self.binary(PgBinOper::Concatenate, right) } /// Alias of [`PgExpr::concatenate`] - fn concat(self, right: T) -> SimpleExpr + fn concat(self, right: T) -> Expr where - T: Into, + T: Into, { self.concatenate(right) } @@ -56,9 +54,9 @@ pub trait PgExpr: ExprTrait { /// r#"SELECT "name", "variant", "language" FROM "font" WHERE 'a & b' @@ 'a b' AND "name" @@ 'a b'"# /// ); /// ``` - fn matches(self, expr: T) -> SimpleExpr + fn matches(self, expr: T) -> Expr where - T: Into, + T: Into, { self.binary(PgBinOper::Matches, expr) } @@ -82,9 +80,9 @@ pub trait PgExpr: ExprTrait { /// r#"SELECT "name", "variant", "language" FROM "font" WHERE 'a & b' @> 'a b' AND "name" @> 'a b'"# /// ); /// ``` - fn contains(self, expr: T) -> SimpleExpr + fn contains(self, expr: T) -> Expr where - T: Into, + T: Into, { self.binary(PgBinOper::Contains, expr) } @@ -108,9 +106,9 @@ pub trait PgExpr: ExprTrait { /// r#"SELECT "name", "variant", "language" FROM "font" WHERE 'a & b' <@ 'a b' AND "name" <@ 'a b'"# /// ); /// ``` - fn contained(self, expr: T) -> SimpleExpr + fn contained(self, expr: T) -> Expr where - T: Into, + T: Into, { self.binary(PgBinOper::Contained, expr) } @@ -133,7 +131,7 @@ pub trait PgExpr: ExprTrait { /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."character" ILIKE E'Ours\'%'"# /// ); /// ``` - fn ilike(self, like: L) -> SimpleExpr + fn ilike(self, like: L) -> Expr where L: IntoLikeExpr, { @@ -141,7 +139,7 @@ pub trait PgExpr: ExprTrait { } /// Express a `NOT ILIKE` expression - fn not_ilike(self, like: L) -> SimpleExpr + fn not_ilike(self, like: L) -> Expr where L: IntoLikeExpr, { @@ -166,9 +164,9 @@ pub trait PgExpr: ExprTrait { /// r#"SELECT "variant" FROM "font" WHERE "variant" -> 'a'"# /// ); /// ``` - fn get_json_field(self, right: T) -> SimpleExpr + fn get_json_field(self, right: T) -> Expr where - T: Into, + T: Into, { self.binary(PgBinOper::GetJsonField, right) } @@ -191,9 +189,9 @@ pub trait PgExpr: ExprTrait { /// r#"SELECT "variant" FROM "font" WHERE "variant" ->> 'a'"# /// ); /// ``` - fn cast_json_field(self, right: T) -> SimpleExpr + fn cast_json_field(self, right: T) -> Expr where - T: Into, + T: Into, { self.binary(PgBinOper::CastJsonField, right) } @@ -203,7 +201,6 @@ pub trait PgExpr: ExprTrait { // replace all of this with `impl PgExpr for T where T: ExprTrait {}` // (breaking change) impl PgExpr for Expr {} -impl PgExpr for SimpleExpr {} impl PgExpr for FunctionCall {} impl PgExpr for ColumnRef {} impl PgExpr for Keyword {} diff --git a/src/extension/postgres/func.rs b/src/extension/postgres/func.rs index 0780c0520..95fdcb904 100644 --- a/src/extension/postgres/func.rs +++ b/src/extension/postgres/func.rs @@ -56,11 +56,11 @@ impl PgFunc { /// ``` pub fn to_tsquery(expr: T, regconfig: Option) -> FunctionCall where - T: Into, + T: Into, { match regconfig { Some(config) => { - let config = SimpleExpr::Value(config.into()); + let config = Expr::Value(config.into()); FunctionCall::new(Function::PgFunction(PgFunction::ToTsquery)) .args([config, expr.into()]) } @@ -89,11 +89,11 @@ impl PgFunc { /// ``` pub fn to_tsvector(expr: T, regconfig: Option) -> FunctionCall where - T: Into, + T: Into, { match regconfig { Some(config) => { - let config = SimpleExpr::Value(config.into()); + let config = Expr::Value(config.into()); FunctionCall::new(Function::PgFunction(PgFunction::ToTsvector)) .args([config, expr.into()]) } @@ -122,11 +122,11 @@ impl PgFunc { /// ``` pub fn phraseto_tsquery(expr: T, regconfig: Option) -> FunctionCall where - T: Into, + T: Into, { match regconfig { Some(config) => { - let config = SimpleExpr::Value(config.into()); + let config = Expr::Value(config.into()); FunctionCall::new(Function::PgFunction(PgFunction::PhrasetoTsquery)) .args([config, expr.into()]) } @@ -155,11 +155,11 @@ impl PgFunc { /// ``` pub fn plainto_tsquery(expr: T, regconfig: Option) -> FunctionCall where - T: Into, + T: Into, { match regconfig { Some(config) => { - let config = SimpleExpr::Value(config.into()); + let config = Expr::Value(config.into()); FunctionCall::new(Function::PgFunction(PgFunction::PlaintoTsquery)) .args([config, expr.into()]) } @@ -188,11 +188,11 @@ impl PgFunc { /// ``` pub fn websearch_to_tsquery(expr: T, regconfig: Option) -> FunctionCall where - T: Into, + T: Into, { match regconfig { Some(config) => { - let config = SimpleExpr::Value(config.into()); + let config = Expr::Value(config.into()); FunctionCall::new(Function::PgFunction(PgFunction::WebsearchToTsquery)) .args([config, expr.into()]) } @@ -220,7 +220,7 @@ impl PgFunc { /// ``` pub fn ts_rank(vector: T, query: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::PgFunction(PgFunction::TsRank)) .args([vector.into(), query.into()]) @@ -244,7 +244,7 @@ impl PgFunc { /// ``` pub fn ts_rank_cd(vector: T, query: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::PgFunction(PgFunction::TsRankCd)) .args([vector.into(), query.into()]) @@ -267,7 +267,7 @@ impl PgFunc { #[cfg(feature = "postgres-array")] pub fn any(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::PgFunction(PgFunction::Any)).arg(expr) } @@ -289,7 +289,7 @@ impl PgFunc { #[cfg(feature = "postgres-array")] pub fn some(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::PgFunction(PgFunction::Some)).arg(expr) } @@ -311,7 +311,7 @@ impl PgFunc { #[cfg(feature = "postgres-array")] pub fn all(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::PgFunction(PgFunction::All)).arg(expr) } @@ -334,8 +334,8 @@ impl PgFunc { /// ``` pub fn starts_with(text: T, prefix: P) -> FunctionCall where - T: Into, - P: Into, + T: Into, + P: Into, { FunctionCall::new(Function::PgFunction(PgFunction::StartsWith)) .args([text.into(), prefix.into()]) @@ -380,7 +380,7 @@ impl PgFunc { /// ``` pub fn json_build_object(pairs: Vec<(T, T)>) -> FunctionCall where - T: Into, + T: Into, { let mut args = vec![]; for (key, value) in pairs { @@ -423,7 +423,7 @@ impl PgFunc { /// ``` pub fn date_trunc(unit: PgDateTruncUnit, expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::PgFunction(PgFunction::DateTrunc)) .args([Expr::val(unit.to_string()).into(), expr.into()]) @@ -448,7 +448,7 @@ impl PgFunc { /// ``` pub fn json_agg(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::PgFunction(PgFunction::JsonAgg)).arg(expr) } @@ -473,7 +473,7 @@ impl PgFunc { /// ``` pub fn array_agg(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::PgFunction(PgFunction::ArrayAgg)).arg(expr) } @@ -498,7 +498,7 @@ impl PgFunc { /// ``` pub fn array_agg_distinct(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::PgFunction(PgFunction::ArrayAgg)) .arg_with(expr, FuncArgMod { distinct: true }) diff --git a/src/extension/sqlite/expr.rs b/src/extension/sqlite/expr.rs index 8826f6875..eaca0e32d 100644 --- a/src/extension/sqlite/expr.rs +++ b/src/extension/sqlite/expr.rs @@ -1,4 +1,4 @@ -use crate::{ColumnRef, Expr, ExprTrait, FunctionCall, Keyword, LikeExpr, SimpleExpr, Value}; +use crate::{ColumnRef, Expr, ExprTrait, FunctionCall, Keyword, LikeExpr, Value}; use super::SqliteBinOper; @@ -22,9 +22,9 @@ pub trait SqliteExpr: ExprTrait { /// r#"SELECT "name" FROM "font" WHERE "name" GLOB 'a'"# /// ); /// ``` - fn glob(self, right: T) -> SimpleExpr + fn glob(self, right: T) -> Expr where - T: Into, + T: Into, { self.binary(SqliteBinOper::Glob, right) } @@ -47,9 +47,9 @@ pub trait SqliteExpr: ExprTrait { /// r#"SELECT "name" FROM "font" WHERE "name" MATCH 'a'"# /// ); /// ``` - fn matches(self, right: T) -> SimpleExpr + fn matches(self, right: T) -> Expr where - T: Into, + T: Into, { self.binary(SqliteBinOper::Match, right) } @@ -72,9 +72,9 @@ pub trait SqliteExpr: ExprTrait { /// r#"SELECT "variant" FROM "font" WHERE "variant" -> 'a'"# /// ); /// ``` - fn get_json_field(self, right: T) -> SimpleExpr + fn get_json_field(self, right: T) -> Expr where - T: Into, + T: Into, { self.binary(SqliteBinOper::GetJsonField, right) } @@ -97,9 +97,9 @@ pub trait SqliteExpr: ExprTrait { /// r#"SELECT "variant" FROM "font" WHERE "variant" ->> 'a'"# /// ); /// ``` - fn cast_json_field(self, right: T) -> SimpleExpr + fn cast_json_field(self, right: T) -> Expr where - T: Into, + T: Into, { self.binary(SqliteBinOper::CastJsonField, right) } @@ -109,7 +109,6 @@ pub trait SqliteExpr: ExprTrait { // replace all of this with `impl SqliteExpr for T where T: ExprTrait {}` // (breaking change) impl SqliteExpr for Expr {} -impl SqliteExpr for SimpleExpr {} impl SqliteExpr for FunctionCall {} impl SqliteExpr for ColumnRef {} impl SqliteExpr for Keyword {} diff --git a/src/func.rs b/src/func.rs index f98fbb24a..524e4232a 100644 --- a/src/func.rs +++ b/src/func.rs @@ -38,7 +38,7 @@ pub enum Function { #[derive(Debug, Clone, PartialEq)] pub struct FunctionCall { pub(crate) func: Function, - pub(crate) args: Vec, + pub(crate) args: Vec, pub(crate) mods: Vec, } @@ -59,14 +59,14 @@ impl FunctionCall { /// Append an argument to the function call pub fn arg(self, arg: T) -> Self where - T: Into, + T: Into, { self.arg_with(arg, Default::default()) } pub(crate) fn arg_with(mut self, arg: T, mod_: FuncArgMod) -> Self where - T: Into, + T: Into, { self.args.push(arg.into()); self.mods.push(mod_); @@ -76,7 +76,7 @@ impl FunctionCall { /// Replace the arguments of the function call pub fn args(mut self, args: I) -> Self where - I: IntoIterator, + I: IntoIterator, { self.args = args.into_iter().collect(); self.mods = vec![Default::default(); self.args.len()]; @@ -87,7 +87,7 @@ impl FunctionCall { &self.func } - pub fn get_args(&self) -> &[SimpleExpr] { + pub fn get_args(&self) -> &[Expr] { &self.args } @@ -167,7 +167,7 @@ impl Func { /// ``` pub fn max(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::Max).arg(expr) } @@ -199,7 +199,7 @@ impl Func { /// ``` pub fn min(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::Min).arg(expr) } @@ -231,7 +231,7 @@ impl Func { /// ``` pub fn sum(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::Sum).arg(expr) } @@ -263,7 +263,7 @@ impl Func { /// ``` pub fn avg(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::Avg).arg(expr) } @@ -295,7 +295,7 @@ impl Func { /// ``` pub fn abs(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::Abs).arg(expr) } @@ -327,7 +327,7 @@ impl Func { /// ``` pub fn count(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::Count).arg(expr) } @@ -359,7 +359,7 @@ impl Func { /// ``` pub fn count_distinct(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::Count).arg_with(expr, FuncArgMod { distinct: true }) } @@ -391,7 +391,7 @@ impl Func { /// ``` pub fn char_length(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::CharLength).arg(expr) } @@ -426,7 +426,7 @@ impl Func { /// ``` pub fn greatest(args: I) -> FunctionCall where - I: IntoIterator, + I: IntoIterator, { FunctionCall::new(Function::Greatest).args(args) } @@ -461,7 +461,7 @@ impl Func { /// ``` pub fn least(args: I) -> FunctionCall where - I: IntoIterator, + I: IntoIterator, { FunctionCall::new(Function::Least).args(args) } @@ -496,8 +496,8 @@ impl Func { /// ``` pub fn if_null(a: A, b: B) -> FunctionCall where - A: Into, - B: Into, + A: Into, + B: Into, { FunctionCall::new(Function::IfNull).args([a.into(), b.into()]) } @@ -528,10 +528,10 @@ impl Func { /// ``` pub fn cast_as(expr: V, iden: I) -> FunctionCall where - V: Into, + V: Into, I: IntoIden, { - let expr: SimpleExpr = expr.into(); + let expr: Expr = expr.into(); FunctionCall::new(Function::Cast).arg(expr.binary( BinOper::As, Expr::cust(iden.into_iden().to_string().as_str()), @@ -564,10 +564,10 @@ impl Func { /// ``` pub fn cast_as_quoted(expr: V, iden: I, q: Quote) -> FunctionCall where - V: Into, + V: Into, I: IntoIden, { - let expr: SimpleExpr = expr.into(); + let expr: Expr = expr.into(); let mut quoted_type = String::new(); iden.into_iden().prepare(&mut quoted_type, q); FunctionCall::new(Function::Cast) @@ -605,7 +605,7 @@ impl Func { /// ``` pub fn coalesce(args: I) -> FunctionCall where - I: IntoIterator, + I: IntoIterator, { FunctionCall::new(Function::Coalesce).args(args) } @@ -660,7 +660,7 @@ impl Func { /// ``` pub fn lower(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::Lower).arg(expr) } @@ -692,7 +692,7 @@ impl Func { /// ``` pub fn upper(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::Upper).arg(expr) } @@ -720,7 +720,7 @@ impl Func { /// ``` pub fn bit_and(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::BitAnd).arg(expr) } @@ -748,7 +748,7 @@ impl Func { /// ``` pub fn bit_or(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::BitOr).arg(expr) } @@ -777,7 +777,7 @@ impl Func { /// ``` pub fn round(expr: A) -> FunctionCall where - A: Into, + A: Into, { FunctionCall::new(Function::Round).arg(expr) } @@ -811,8 +811,8 @@ impl Func { /// ``` pub fn round_with_precision(a: A, b: B) -> FunctionCall where - A: Into, - B: Into, + A: Into, + B: Into, { FunctionCall::new(Function::Round).args([a.into(), b.into()]) } @@ -861,7 +861,7 @@ impl Func { /// ``` pub fn md5(expr: T) -> FunctionCall where - T: Into, + T: Into, { FunctionCall::new(Function::Md5).arg(expr) } diff --git a/src/index/common.rs b/src/index/common.rs index e6597a49d..a87166e3d 100644 --- a/src/index/common.rs +++ b/src/index/common.rs @@ -1,4 +1,4 @@ -use crate::expr::SimpleExpr; +use crate::expr::Expr; use crate::{types::*, FunctionCall}; /// Specification of a table index @@ -23,7 +23,7 @@ pub struct IndexColumnTableColumn { #[derive(Debug, Clone)] pub struct IndexColumnExpr { - pub(crate) expr: SimpleExpr, + pub(crate) expr: Expr, pub(crate) order: Option, } @@ -122,7 +122,7 @@ impl IntoIndexColumn for (FunctionCall, IndexOrder) { } } -impl IntoIndexColumn for SimpleExpr { +impl IntoIndexColumn for Expr { fn into_index_column(self) -> IndexColumn { IndexColumn::Expr(IndexColumnExpr { expr: self, @@ -131,7 +131,7 @@ impl IntoIndexColumn for SimpleExpr { } } -impl IntoIndexColumn for (SimpleExpr, IndexOrder) { +impl IntoIndexColumn for (Expr, IndexOrder) { fn into_index_column(self) -> IndexColumn { IndexColumn::Expr(IndexColumnExpr { expr: self.0, diff --git a/src/query/case.rs b/src/query/case.rs index 9831bc6f2..6069b800b 100644 --- a/src/query/case.rs +++ b/src/query/case.rs @@ -1,15 +1,15 @@ -use crate::{Condition, IntoCondition, SimpleExpr}; +use crate::{Condition, Expr, IntoCondition}; #[derive(Debug, Clone, PartialEq)] pub(crate) struct CaseStatementCondition { pub(crate) condition: Condition, - pub(crate) result: SimpleExpr, + pub(crate) result: Expr, } #[derive(Debug, Clone, Default, PartialEq)] pub struct CaseStatement { pub(crate) when: Vec, - pub(crate) r#else: Option, + pub(crate) r#else: Option, } impl CaseStatement { @@ -70,7 +70,7 @@ impl CaseStatement { pub fn case(mut self, cond: C, then: T) -> Self where C: IntoCondition, - T: Into, + T: Into, { self.when.push(CaseStatementCondition { condition: cond.into_condition(), @@ -119,7 +119,7 @@ impl CaseStatement { /// ``` pub fn finally(mut self, r#else: E) -> Self where - E: Into, + E: Into, { self.r#else = Some(r#else.into()); self @@ -127,9 +127,9 @@ impl CaseStatement { } #[allow(clippy::from_over_into)] -impl Into for CaseStatement { - fn into(self) -> SimpleExpr { - SimpleExpr::Case(Box::new(self)) +impl Into for CaseStatement { + fn into(self) -> Expr { + Expr::Case(Box::new(self)) } } @@ -140,7 +140,7 @@ mod test { #[test] #[cfg(feature = "backend-postgres")] fn test_where_case_eq() { - let case_statement: SimpleExpr = Expr::case(Expr::col("col").lt(5), Expr::col("othercol")) + let case_statement: Expr = Expr::case(Expr::col("col").lt(5), Expr::col("othercol")) .finally(Expr::col("finalcol")) .into(); diff --git a/src/query/condition.rs b/src/query/condition.rs index 5b8d54a6a..c3219b68a 100644 --- a/src/query/condition.rs +++ b/src/query/condition.rs @@ -1,4 +1,4 @@ -use crate::{expr::SimpleExpr, types::LogicalChainOper}; +use crate::{expr::Expr, types::LogicalChainOper, ExprTrait}; #[derive(Debug, Clone, PartialEq, Eq)] pub enum ConditionType { @@ -26,7 +26,7 @@ pub type Cond = Condition; #[derive(Debug, Clone, PartialEq)] pub enum ConditionExpression { Condition(Condition), - SimpleExpr(SimpleExpr), + Expr(Expr), } #[derive(Default, Debug, Clone, PartialEq)] @@ -96,7 +96,7 @@ impl Condition { /// .cond_where( /// Cond::all() /// .add_option(Some(Expr::col((Glyph::Table, Glyph::Image)).like("A%"))) - /// .add_option(None::), + /// .add_option(None::), /// ) /// .to_owned(); /// @@ -262,13 +262,13 @@ impl Condition { } } -impl From for SimpleExpr { +impl From for Expr { fn from(cond: Condition) -> Self { let mut inner_exprs = vec![]; for ce in cond.conditions { inner_exprs.push(match ce { ConditionExpression::Condition(c) => c.into(), - ConditionExpression::SimpleExpr(e) => e, + ConditionExpression::Expr(e) => e, }); } let mut inner_exprs_into_iter = inner_exprs.into_iter(); @@ -282,7 +282,7 @@ impl From for SimpleExpr { } out_expr } else { - SimpleExpr::Constant(match cond.condition_type { + Expr::Constant(match cond.condition_type { ConditionType::Any => false.into(), ConditionType::All => true.into(), }) @@ -295,11 +295,11 @@ impl From for SimpleExpr { } } -impl From for SimpleExpr { +impl From for Expr { fn from(ce: ConditionExpression) -> Self { match ce { ConditionExpression::Condition(c) => c.into(), - ConditionExpression::SimpleExpr(e) => e, + ConditionExpression::Expr(e) => e, } } } @@ -310,9 +310,9 @@ impl From for ConditionExpression { } } -impl From for ConditionExpression { - fn from(condition: SimpleExpr) -> Self { - ConditionExpression::SimpleExpr(condition) +impl From for ConditionExpression { + fn from(condition: Expr) -> Self { + ConditionExpression::Expr(condition) } } @@ -408,7 +408,7 @@ pub trait ConditionalStatement { /// r#"SELECT `image` FROM `glyph` WHERE `glyph`.`aspect` IN (3, 4) AND `glyph`.`image` LIKE 'A%'"# /// ); /// ``` - fn and_where(&mut self, other: SimpleExpr) -> &mut Self { + fn and_where(&mut self, other: Expr) -> &mut Self { self.cond_where(other) } @@ -430,7 +430,7 @@ pub trait ConditionalStatement { /// r#"SELECT `image` FROM `glyph` WHERE `aspect` IN (3, 4) AND `image` LIKE 'A%'"# /// ); /// ``` - fn and_where_option(&mut self, other: Option) -> &mut Self { + fn and_where_option(&mut self, other: Option) -> &mut Self { if let Some(other) = other { self.and_where(other); } @@ -599,7 +599,7 @@ pub trait ConditionalStatement { C: IntoCondition; } -impl IntoCondition for SimpleExpr { +impl IntoCondition for Expr { fn into_condition(self) -> Condition { Condition::all().add(self) } @@ -694,7 +694,7 @@ mod test { assert_eq!( query.to_string(MysqlQueryBuilder), - "SELECT `image` FROM `glyph` WHERE 1 = 1 AND 2 = 2 AND (3 = 3 OR 4 = 4)" + "SELECT `image` FROM `glyph` WHERE (1 = 1) AND (2 = 2) AND ((3 = 3) OR (4 = 4))" ); } } diff --git a/src/query/delete.rs b/src/query/delete.rs index 2d908429a..858daa960 100644 --- a/src/query/delete.rs +++ b/src/query/delete.rs @@ -4,7 +4,7 @@ use crate::{ query::{condition::*, OrderedStatement}, types::*, value::*, - QueryStatementBuilder, QueryStatementWriter, ReturningClause, SimpleExpr, SubQueryStatement, + QueryStatementBuilder, QueryStatementWriter, ReturningClause, Expr, SubQueryStatement, WithClause, WithQuery, }; use inherent::inherent; @@ -324,7 +324,7 @@ impl OrderedStatement for DeleteStatement { where T: IntoColumnRef; - pub fn order_by_expr(&mut self, expr: SimpleExpr, order: Order) -> &mut Self; + pub fn order_by_expr(&mut self, expr: Expr, order: Order) -> &mut Self; pub fn order_by_customs(&mut self, cols: I) -> &mut Self where T: ToString, @@ -343,7 +343,7 @@ impl OrderedStatement for DeleteStatement { T: IntoColumnRef; pub fn order_by_expr_with_nulls( &mut self, - expr: SimpleExpr, + expr: Expr, order: Order, nulls: NullOrdering, ) -> &mut Self; @@ -372,6 +372,6 @@ impl ConditionalStatement for DeleteStatement { self } - pub fn and_where_option(&mut self, other: Option) -> &mut Self; - pub fn and_where(&mut self, other: SimpleExpr) -> &mut Self; + pub fn and_where_option(&mut self, other: Option) -> &mut Self; + pub fn and_where(&mut self, other: Expr) -> &mut Self; } diff --git a/src/query/insert.rs b/src/query/insert.rs index 240615c26..e91f9d4be 100644 --- a/src/query/insert.rs +++ b/src/query/insert.rs @@ -1,6 +1,6 @@ use crate::{ backend::QueryBuilder, error::*, prepare::*, types::*, OnConflict, QueryStatementBuilder, - QueryStatementWriter, ReturningClause, SelectStatement, SimpleExpr, SubQueryStatement, Values, + QueryStatementWriter, ReturningClause, SelectStatement, Expr, SubQueryStatement, Values, WithClause, WithQuery, }; use inherent::inherent; @@ -11,7 +11,7 @@ use inherent::inherent; /// ('VALUES') or a select query. #[derive(Debug, Clone, PartialEq)] pub(crate) enum InsertValueSource { - Values(Vec>), + Values(Vec>), Select(Box), } @@ -220,9 +220,9 @@ impl InsertStatement { /// ``` pub fn values(&mut self, values: I) -> Result<&mut Self> where - I: IntoIterator, + I: IntoIterator, { - let values = values.into_iter().collect::>(); + let values = values.into_iter().collect::>(); if self.columns.len() != values.len() { return Err(Error::ColValNumMismatch { col_len: self.columns.len(), @@ -274,7 +274,7 @@ impl InsertStatement { /// ``` pub fn values_panic(&mut self, values: I) -> &mut Self where - I: IntoIterator, + I: IntoIterator, { self.values(values).unwrap() } @@ -309,7 +309,7 @@ impl InsertStatement { /// ``` pub fn values_from_panic(&mut self, values_iter: impl IntoIterator) -> &mut Self where - I: IntoIterator, + I: IntoIterator, { values_iter.into_iter().for_each(|values| { self.values_panic(values); diff --git a/src/query/on_conflict.rs b/src/query/on_conflict.rs index aee8fb791..05992426c 100644 --- a/src/query/on_conflict.rs +++ b/src/query/on_conflict.rs @@ -1,4 +1,4 @@ -use crate::{ConditionHolder, DynIden, IntoCondition, IntoIden, SimpleExpr}; +use crate::{ConditionHolder, DynIden, Expr, IntoCondition, IntoIden}; #[derive(Debug, Clone, Default, PartialEq)] pub struct OnConflict { @@ -14,7 +14,7 @@ pub enum OnConflictTarget { /// A column ConflictColumn(DynIden), /// An expression `(LOWER(column), ...)` - ConflictExpr(SimpleExpr), + ConflictExpr(Expr), } /// Represents ON CONFLICT (upsert) actions @@ -32,7 +32,7 @@ pub enum OnConflictUpdate { /// Update column value of existing row with inserting value Column(DynIden), /// Update column value of existing row with expression - Expr(DynIden, SimpleExpr), + Expr(DynIden, Expr), } impl OnConflict { @@ -117,7 +117,7 @@ impl OnConflict { /// ``` pub fn expr(&mut self, expr: T) -> &mut Self where - T: Into, + T: Into, { Self::exprs(self, [expr]) } @@ -125,7 +125,7 @@ impl OnConflict { /// Set multiple target expressions for ON CONFLICT. See [`OnConflict::expr`] pub fn exprs(&mut self, exprs: I) -> &mut Self where - T: Into, + T: Into, I: IntoIterator, { self.targets.append( @@ -397,7 +397,7 @@ impl OnConflict { pub fn values(&mut self, values: I) -> &mut Self where C: IntoIden, - I: IntoIterator, + I: IntoIterator, { let mut update_exprs: Vec = values .into_iter() @@ -419,7 +419,7 @@ impl OnConflict { pub fn value(&mut self, col: C, value: T) -> &mut Self where C: IntoIden, - T: Into, + T: Into, { self.values([(col, value.into())]) } @@ -459,12 +459,12 @@ impl OnConflict { /// r#"INSERT INTO "glyph" ("aspect", "image") VALUES (2, 3) ON CONFLICT ("id") WHERE "glyph"."aspect" IS NULL DO UPDATE SET "image" = 1 + 2"# /// ); /// ``` - pub fn target_and_where(&mut self, other: SimpleExpr) -> &mut Self { + pub fn target_and_where(&mut self, other: Expr) -> &mut Self { self.target_cond_where(other) } /// Set target WHERE - pub fn target_and_where_option(&mut self, other: Option) -> &mut Self { + pub fn target_and_where_option(&mut self, other: Option) -> &mut Self { if let Some(other) = other { self.target_cond_where(other); } @@ -515,12 +515,12 @@ impl OnConflict { /// r#"INSERT INTO "glyph" ("aspect", "image") VALUES (2, 3) ON CONFLICT ("id") DO UPDATE SET "image" = 1 + 2 WHERE "glyph"."aspect" IS NULL"# /// ); /// ``` - pub fn action_and_where(&mut self, other: SimpleExpr) -> &mut Self { + pub fn action_and_where(&mut self, other: Expr) -> &mut Self { self.action_cond_where(other) } /// Set action WHERE - pub fn action_and_where_option(&mut self, other: Option) -> &mut Self { + pub fn action_and_where_option(&mut self, other: Option) -> &mut Self { if let Some(other) = other { self.action_cond_where(other); } diff --git a/src/query/ordered.rs b/src/query/ordered.rs index 68e85ff6c..0f37ab626 100644 --- a/src/query/ordered.rs +++ b/src/query/ordered.rs @@ -93,14 +93,14 @@ pub trait OrderedStatement { T: IntoColumnRef, { self.add_order_by(OrderExpr { - expr: SimpleExpr::Column(col.into_column_ref()), + expr: Expr::Column(col.into_column_ref()), order, nulls: None, }) } - /// Order by [`SimpleExpr`]. - fn order_by_expr(&mut self, expr: SimpleExpr, order: Order) -> &mut Self { + /// Order by [`Expr`]. + fn order_by_expr(&mut self, expr: Expr, order: Order) -> &mut Self { self.add_order_by(OrderExpr { expr, order, @@ -116,7 +116,7 @@ pub trait OrderedStatement { { cols.into_iter().for_each(|(c, order)| { self.add_order_by(OrderExpr { - expr: SimpleExpr::Custom(c.to_string()), + expr: Expr::Custom(c.to_string()), order, nulls: None, }); @@ -132,7 +132,7 @@ pub trait OrderedStatement { { cols.into_iter().for_each(|(c, order)| { self.add_order_by(OrderExpr { - expr: SimpleExpr::Column(c.into_column_ref()), + expr: Expr::Column(c.into_column_ref()), order, nulls: None, }); @@ -168,16 +168,16 @@ pub trait OrderedStatement { T: IntoColumnRef, { self.add_order_by(OrderExpr { - expr: SimpleExpr::Column(col.into_column_ref()), + expr: Expr::Column(col.into_column_ref()), order, nulls: Some(nulls), }) } - /// Order by [`SimpleExpr`] with nulls order option. + /// Order by [`Expr`] with nulls order option. fn order_by_expr_with_nulls( &mut self, - expr: SimpleExpr, + expr: Expr, order: Order, nulls: NullOrdering, ) -> &mut Self { @@ -196,7 +196,7 @@ pub trait OrderedStatement { { cols.into_iter().for_each(|(c, order, nulls)| { self.add_order_by(OrderExpr { - expr: SimpleExpr::Custom(c.to_string()), + expr: Expr::Custom(c.to_string()), order, nulls: Some(nulls), }); @@ -212,7 +212,7 @@ pub trait OrderedStatement { { cols.into_iter().for_each(|(c, order, nulls)| { self.add_order_by(OrderExpr { - expr: SimpleExpr::Column(c.into_column_ref()), + expr: Expr::Column(c.into_column_ref()), order, nulls: Some(nulls), }); diff --git a/src/query/returning.rs b/src/query/returning.rs index 60ddfd1b8..fe527b89f 100644 --- a/src/query/returning.rs +++ b/src/query/returning.rs @@ -1,4 +1,4 @@ -use crate::{ColumnRef, IntoColumnRef, SimpleExpr}; +use crate::{ColumnRef, IntoColumnRef, Expr}; /// RETURNING clause. /// ## Note: @@ -11,7 +11,7 @@ use crate::{ColumnRef, IntoColumnRef, SimpleExpr}; pub enum ReturningClause { All, Columns(Vec), - Exprs(Vec), + Exprs(Vec), } /// Shorthand for constructing [`ReturningClause`] @@ -134,7 +134,7 @@ impl Returning { /// ``` pub fn expr(&self, expr: T) -> ReturningClause where - T: Into, + T: Into, { ReturningClause::Exprs(vec![expr.into()]) } @@ -163,7 +163,7 @@ impl Returning { /// ``` pub fn exprs(self, exprs: I) -> ReturningClause where - T: Into, + T: Into, I: IntoIterator, { ReturningClause::Exprs(exprs.into_iter().map(Into::into).collect()) diff --git a/src/query/select.rs b/src/query/select.rs index 400509cf0..5db2ba9b9 100644 --- a/src/query/select.rs +++ b/src/query/select.rs @@ -46,7 +46,7 @@ pub struct SelectStatement { pub(crate) from: Vec, pub(crate) join: Vec, pub(crate) r#where: ConditionHolder, - pub(crate) groups: Vec, + pub(crate) groups: Vec, pub(crate) having: ConditionHolder, pub(crate) unions: Vec<(UnionType, SelectStatement)>, pub(crate) orders: Vec, @@ -82,7 +82,7 @@ pub enum WindowSelectType { /// Select expression used in select statement #[derive(Debug, Clone, PartialEq)] pub struct SelectExpr { - pub expr: SimpleExpr, + pub expr: Expr, pub alias: Option, pub window: Option, } @@ -132,7 +132,7 @@ pub enum UnionType { impl From for SelectExpr where - T: Into, + T: Into, { fn from(expr: T) -> Self { SelectExpr { @@ -306,7 +306,7 @@ impl SelectStatement { /// .from(Char::Table) /// .expr(Expr::val(42)) /// .expr(Expr::col(Char::Id).max()) - /// .expr((1..10_i32).fold(Expr::value(0), |expr, i| expr.add(i))) + /// .expr((1..10_i32).fold(Expr::val(0), |expr, i| expr.add(i))) /// .to_owned(); /// /// assert_eq!( @@ -341,7 +341,7 @@ impl SelectStatement { /// .from(Char::Table) /// .exprs([ /// Expr::col(Char::Id).max(), - /// (1..10_i32).fold(Expr::value(0), |expr, i| expr.add(i)), + /// (1..10_i32).fold(Expr::val(0), |expr, i| expr.add(i)), /// ]) /// .to_owned(); /// @@ -528,7 +528,7 @@ impl SelectStatement { where C: IntoColumnRef, { - self.expr(SimpleExpr::Column(col.into_column_ref())) + self.expr(Expr::Column(col.into_column_ref())) } /// Select columns. @@ -589,8 +589,8 @@ impl SelectStatement { { self.exprs( cols.into_iter() - .map(|c| SimpleExpr::Column(c.into_column_ref())) - .collect::>(), + .map(|c| Expr::Column(c.into_column_ref())) + .collect::>(), ) } @@ -621,7 +621,7 @@ impl SelectStatement { /// ``` pub fn expr_as(&mut self, expr: T, alias: A) -> &mut Self where - T: Into, + T: Into, A: IntoIden, { self.expr(SelectExpr { @@ -662,7 +662,7 @@ impl SelectStatement { /// ``` pub fn expr_window(&mut self, expr: T, window: WindowStatement) -> &mut Self where - T: Into, + T: Into, { self.expr(SelectExpr { expr: expr.into(), @@ -703,7 +703,7 @@ impl SelectStatement { /// ``` pub fn expr_window_as(&mut self, expr: T, window: WindowStatement, alias: A) -> &mut Self where - T: Into, + T: Into, A: IntoIden, { self.expr(SelectExpr { @@ -742,7 +742,7 @@ impl SelectStatement { /// ``` pub fn expr_window_name(&mut self, expr: T, window: W) -> &mut Self where - T: Into, + T: Into, W: IntoIden, { self.expr(SelectExpr { @@ -781,7 +781,7 @@ impl SelectStatement { /// ``` pub fn expr_window_name_as(&mut self, expr: T, window: W, alias: A) -> &mut Self where - T: Into, + T: Into, A: IntoIden, W: IntoIden, { @@ -1761,7 +1761,7 @@ impl SelectStatement { { self.add_group_by( cols.into_iter() - .map(|c| SimpleExpr::Column(c.into_column_ref())) + .map(|c| Expr::Column(c.into_column_ref())) .collect::>(), ) } @@ -1827,7 +1827,7 @@ impl SelectStatement { /// ``` pub fn add_group_by(&mut self, expr: I) -> &mut Self where - I: IntoIterator, + I: IntoIterator, { self.groups.append(&mut expr.into_iter().collect()); self @@ -1902,7 +1902,7 @@ impl SelectStatement { /// r#"SELECT "aspect", MAX("image") FROM "glyph" GROUP BY "aspect" HAVING "aspect" > 2 AND "aspect" < 8"# /// ); /// ``` - pub fn and_having(&mut self, other: SimpleExpr) -> &mut Self { + pub fn and_having(&mut self, other: Expr) -> &mut Self { self.cond_having(other) } @@ -2327,7 +2327,7 @@ impl SelectStatement { /// let with_clause = WithClause::new() /// .recursive(true) /// .cte(common_table_expression) - /// .cycle(Cycle::new_from_expr_set_using(SimpleExpr::Column(ColumnRef::Column("id".into_iden())), "looped", "traversal_path")) + /// .cycle(Cycle::new_from_expr_set_using(Expr::Column(ColumnRef::Column("id".into_iden())), "looped", "traversal_path")) /// .to_owned(); /// /// let query = select.with(with_clause).to_owned(); @@ -2388,7 +2388,7 @@ impl SelectStatement { /// let with_clause = WithClause::new() /// .recursive(true) /// .cte(common_table_expression) - /// .cycle(Cycle::new_from_expr_set_using(SimpleExpr::Column(ColumnRef::Column("id".into_iden())), "looped", "traversal_path")) + /// .cycle(Cycle::new_from_expr_set_using(Expr::Column(ColumnRef::Column("id".into_iden())), "looped", "traversal_path")) /// .to_owned(); /// /// let query = SelectStatement::new() @@ -2503,7 +2503,7 @@ impl OrderedStatement for SelectStatement { where T: IntoColumnRef; - pub fn order_by_expr(&mut self, expr: SimpleExpr, order: Order) -> &mut Self; + pub fn order_by_expr(&mut self, expr: Expr, order: Order) -> &mut Self; pub fn order_by_customs(&mut self, cols: I) -> &mut Self where T: ToString, @@ -2522,7 +2522,7 @@ impl OrderedStatement for SelectStatement { T: IntoColumnRef; pub fn order_by_expr_with_nulls( &mut self, - expr: SimpleExpr, + expr: Expr, order: Order, nulls: NullOrdering, ) -> &mut Self; @@ -2551,6 +2551,6 @@ impl ConditionalStatement for SelectStatement { self } - pub fn and_where_option(&mut self, other: Option) -> &mut Self; - pub fn and_where(&mut self, other: SimpleExpr) -> &mut Self; + pub fn and_where_option(&mut self, other: Option) -> &mut Self; + pub fn and_where(&mut self, other: Expr) -> &mut Self; } diff --git a/src/query/update.rs b/src/query/update.rs index 6e9c9385d..416ee2590 100644 --- a/src/query/update.rs +++ b/src/query/update.rs @@ -41,7 +41,7 @@ use crate::{ pub struct UpdateStatement { pub(crate) table: Option>, pub(crate) from: Vec, - pub(crate) values: Vec<(DynIden, Box)>, + pub(crate) values: Vec<(DynIden, Box)>, pub(crate) r#where: ConditionHolder, pub(crate) orders: Vec, pub(crate) limit: Option, @@ -83,7 +83,7 @@ impl UpdateStatement { /// /// let query = Query::update() /// .table(Glyph::Table) - /// .value(Glyph::Tokens, Expr::column((Char::Table, Char::Character))) + /// .value(Glyph::Tokens, Expr::col((Char::Table, Char::Character))) /// .from(Char::Table) /// .cond_where( /// Expr::col((Glyph::Table, Glyph::Image)) @@ -148,7 +148,7 @@ impl UpdateStatement { pub fn values(&mut self, values: I) -> &mut Self where T: IntoIden, - I: IntoIterator, + I: IntoIterator, { for (k, v) in values.into_iter() { self.values.push((k.into_iden(), Box::new(v))); @@ -156,7 +156,7 @@ impl UpdateStatement { self } - /// Update column value by [`SimpleExpr`]. + /// Update column value by [`Expr`]. /// /// # Examples /// @@ -186,7 +186,7 @@ impl UpdateStatement { /// /// let query = Query::update() /// .table(Glyph::Table) - /// .value(Glyph::Aspect, Expr::value(Value::Int(None))) + /// .value(Glyph::Aspect, Expr::val(Value::Int(None))) /// .to_owned(); /// /// assert_eq!( @@ -205,7 +205,7 @@ impl UpdateStatement { pub fn value(&mut self, col: C, value: T) -> &mut Self where C: IntoIden, - T: Into, + T: Into, { self.values.push((col.into_iden(), Box::new(value.into()))); self @@ -402,7 +402,7 @@ impl UpdateStatement { } /// Get column values - pub fn get_values(&self) -> &[(DynIden, Box)] { + pub fn get_values(&self) -> &[(DynIden, Box)] { &self.values } } @@ -459,7 +459,7 @@ impl OrderedStatement for UpdateStatement { where T: IntoColumnRef; - pub fn order_by_expr(&mut self, expr: SimpleExpr, order: Order) -> &mut Self; + pub fn order_by_expr(&mut self, expr: Expr, order: Order) -> &mut Self; pub fn order_by_customs(&mut self, cols: I) -> &mut Self where T: ToString, @@ -478,7 +478,7 @@ impl OrderedStatement for UpdateStatement { T: IntoColumnRef; pub fn order_by_expr_with_nulls( &mut self, - expr: SimpleExpr, + expr: Expr, order: Order, nulls: NullOrdering, ) -> &mut Self; @@ -507,6 +507,6 @@ impl ConditionalStatement for UpdateStatement { self } - pub fn and_where_option(&mut self, other: Option) -> &mut Self; - pub fn and_where(&mut self, other: SimpleExpr) -> &mut Self; + pub fn and_where_option(&mut self, other: Option) -> &mut Self; + pub fn and_where(&mut self, other: Expr) -> &mut Self; } diff --git a/src/query/window.rs b/src/query/window.rs index 3825c756d..c69078d21 100644 --- a/src/query/window.rs +++ b/src/query/window.rs @@ -4,14 +4,14 @@ use inherent::inherent; pub trait OverStatement { #[doc(hidden)] // Implementation for the trait. - fn add_partition_by(&mut self, partition: SimpleExpr) -> &mut Self; + fn add_partition_by(&mut self, partition: Expr) -> &mut Self; /// Partition by column. fn partition_by(&mut self, col: T) -> &mut Self where T: IntoColumnRef, { - self.add_partition_by(SimpleExpr::Column(col.into_column_ref())) + self.add_partition_by(Expr::Column(col.into_column_ref())) } /// Partition by custom string. @@ -21,7 +21,7 @@ pub trait OverStatement { I: IntoIterator, { cols.into_iter().for_each(|c| { - self.add_partition_by(SimpleExpr::Custom(c.to_string())); + self.add_partition_by(Expr::Custom(c.to_string())); }); self } @@ -33,7 +33,7 @@ pub trait OverStatement { I: IntoIterator, { cols.into_iter().for_each(|c| { - self.add_partition_by(SimpleExpr::Column(c.into_column_ref())); + self.add_partition_by(Expr::Column(c.into_column_ref())); }); self } @@ -73,7 +73,7 @@ pub struct FrameClause { /// 3. #[derive(Default, Debug, Clone, PartialEq)] pub struct WindowStatement { - pub(crate) partition_by: Vec, + pub(crate) partition_by: Vec, pub(crate) order_by: Vec, pub(crate) frame: Option, } @@ -98,7 +98,7 @@ impl WindowStatement { T: IntoColumnRef, { let mut window = Self::new(); - window.add_partition_by(SimpleExpr::Column(col.into_column_ref())); + window.add_partition_by(Expr::Column(col.into_column_ref())); window } @@ -108,7 +108,7 @@ impl WindowStatement { T: ToString, { let mut window = Self::new(); - window.add_partition_by(SimpleExpr::Custom(col.to_string())); + window.add_partition_by(Expr::Custom(col.to_string())); window } @@ -188,7 +188,7 @@ impl WindowStatement { } impl OverStatement for WindowStatement { - fn add_partition_by(&mut self, partition: SimpleExpr) -> &mut Self { + fn add_partition_by(&mut self, partition: Expr) -> &mut Self { self.partition_by.push(partition); self } @@ -210,7 +210,7 @@ impl OrderedStatement for WindowStatement { where T: IntoColumnRef; - pub fn order_by_expr(&mut self, expr: SimpleExpr, order: Order) -> &mut Self; + pub fn order_by_expr(&mut self, expr: Expr, order: Order) -> &mut Self; pub fn order_by_customs(&mut self, cols: I) -> &mut Self where T: ToString, @@ -229,7 +229,7 @@ impl OrderedStatement for WindowStatement { T: IntoColumnRef; pub fn order_by_expr_with_nulls( &mut self, - expr: SimpleExpr, + expr: Expr, order: Order, nulls: NullOrdering, ) -> &mut Self; diff --git a/src/query/with.rs b/src/query/with.rs index 8fc4d13fd..955de79f3 100644 --- a/src/query/with.rs +++ b/src/query/with.rs @@ -1,7 +1,6 @@ use crate::{ - ColumnRef, DynIden, IntoIden, QueryStatementBuilder, QueryStatementWriter, SelectExpr, - SelectStatement, SimpleExpr, SqlWriter, SubQueryStatement, TableRef, Values, - {Alias, QueryBuilder}, + ColumnRef, DynIden, Expr, IntoIden, QueryStatementBuilder, QueryStatementWriter, SelectExpr, + SelectStatement, SqlWriter, SubQueryStatement, TableRef, Values, {Alias, QueryBuilder}, }; use inherent::inherent; @@ -152,7 +151,7 @@ impl CommonTableExpression { Some(ident.clone()) } else { match &select.expr { - SimpleExpr::Column(column) => match column { + Expr::Column(column) => match column { ColumnRef::Column(iden) => Some(iden.clone()), ColumnRef::TableColumn(table, column) => Some( Alias::new(format!("{}_{}", table.to_string(), column.to_string())) @@ -264,7 +263,7 @@ impl Search { /// Setting [Self::set], [Self::expr] and [Self::using] is mandatory. #[derive(Debug, Clone, Default, PartialEq)] pub struct Cycle { - pub(crate) expr: Option, + pub(crate) expr: Option, pub(crate) set_as: Option, pub(crate) using: Option, } @@ -274,7 +273,7 @@ impl Cycle { /// given [SelectExpr] must have an alias specified. pub fn new_from_expr_set_using(expr: EXPR, set: ID1, using: ID2) -> Self where - EXPR: Into, + EXPR: Into, ID1: IntoIden, ID2: IntoIden, { @@ -293,7 +292,7 @@ impl Cycle { /// The expression identifying nodes. pub fn expr(&mut self, expr: EXPR) -> &mut Self where - EXPR: Into, + EXPR: Into, { self.expr = Some(expr.into()); self @@ -408,7 +407,7 @@ impl Cycle { /// let with_clause = WithClause::new() /// .recursive(true) /// .cte(common_table_expression) -/// .cycle(Cycle::new_from_expr_set_using(SimpleExpr::Column(ColumnRef::Column("id".into_iden())), "looped", "traversal_path")) +/// .cycle(Cycle::new_from_expr_set_using(Expr::Column(ColumnRef::Column("id".into_iden())), "looped", "traversal_path")) /// .to_owned(); /// /// let query = select.with(with_clause).to_owned(); diff --git a/src/table/column.rs b/src/table/column.rs index 97677c524..7bd1d8d52 100644 --- a/src/table/column.rs +++ b/src/table/column.rs @@ -174,15 +174,15 @@ impl ColumnType { pub enum ColumnSpec { Null, NotNull, - Default(SimpleExpr), + Default(Expr), AutoIncrement, UniqueKey, PrimaryKey, - Check(SimpleExpr), - Generated { expr: SimpleExpr, stored: bool }, + Check(Expr), + Generated { expr: Expr, stored: bool }, Extra(String), Comment(String), - Using(SimpleExpr), + Using(Expr), } // All interval fields @@ -321,7 +321,7 @@ impl ColumnDef { /// ``` pub fn default(&mut self, value: T) -> &mut Self where - T: Into, + T: Into, { self.spec.push(ColumnSpec::Default(value.into())); self @@ -680,7 +680,7 @@ impl ColumnDef { self } - /// Set constraints as SimpleExpr + /// Set constraints as Expr /// /// ``` /// use sea_query::{tests_cfg::*, *}; @@ -699,16 +699,16 @@ impl ColumnDef { /// ``` pub fn check(&mut self, value: T) -> &mut Self where - T: Into, + T: Into, { self.spec.push(ColumnSpec::Check(value.into())); self } - /// Sets the column as generated with SimpleExpr + /// Sets the column as generated with Expr pub fn generated(&mut self, expr: T, stored: bool) -> &mut Self where - T: Into, + T: Into, { self.spec.push(ColumnSpec::Generated { expr: expr.into(), @@ -777,7 +777,7 @@ impl ColumnDef { /// ``` pub fn using(&mut self, value: T) -> &mut Self where - T: Into, + T: Into, { self.spec.push(ColumnSpec::Using(value.into())); self diff --git a/src/table/create.rs b/src/table/create.rs index 7a2f51115..ed1a3fefb 100644 --- a/src/table/create.rs +++ b/src/table/create.rs @@ -2,7 +2,7 @@ use inherent::inherent; use crate::{ backend::SchemaBuilder, foreign_key::*, index::*, types::*, ColumnDef, IntoColumnDef, - SchemaStatementBuilder, SimpleExpr, + SchemaStatementBuilder, Expr, }; /// Create a table @@ -88,7 +88,7 @@ pub struct TableCreateStatement { pub(crate) indexes: Vec, pub(crate) foreign_keys: Vec, pub(crate) if_not_exists: bool, - pub(crate) check: Vec, + pub(crate) check: Vec, pub(crate) comment: Option, pub(crate) extra: Option, pub(crate) temporary: bool, @@ -144,7 +144,7 @@ impl TableCreateStatement { self } - pub fn check(&mut self, value: SimpleExpr) -> &mut Self { + pub fn check(&mut self, value: Expr) -> &mut Self { self.check.push(value); self } diff --git a/src/types.rs b/src/types.rs index 9fcb0b5ff..89a5dc7a2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -219,8 +219,8 @@ pub enum BinOper { /// Logical chain operator: conjunction or disjunction. #[derive(Debug, Clone, PartialEq)] pub enum LogicalChainOper { - And(SimpleExpr), - Or(SimpleExpr), + And(Expr), + Or(Expr), } /// Join types @@ -244,7 +244,7 @@ pub enum NullOrdering { /// Order expression #[derive(Debug, Clone, PartialEq)] pub struct OrderExpr { - pub(crate) expr: SimpleExpr, + pub(crate) expr: Expr, pub(crate) order: Order, pub(crate) nulls: Option, } @@ -253,7 +253,7 @@ pub struct OrderExpr { #[derive(Debug, Clone, PartialEq)] pub enum JoinOn { Condition(Box), - Columns(Vec), + Columns(Vec), } /// Ordering options diff --git a/tests/more-parentheses.rs b/tests/more-parentheses.rs index 5d4668c68..47062b3a8 100644 --- a/tests/more-parentheses.rs +++ b/tests/more-parentheses.rs @@ -1,4 +1,4 @@ -use sea_query::{tests_cfg::Glyph, Cond, Expr, MysqlQueryBuilder, Query}; +use sea_query::{tests_cfg::Glyph, Cond, Expr, ExprTrait, MysqlQueryBuilder, Query}; #[test] fn test_more_parentheses() { diff --git a/tests/mysql/query.rs b/tests/mysql/query.rs index bd03ca2d4..4e1e67ed2 100644 --- a/tests/mysql/query.rs +++ b/tests/mysql/query.rs @@ -449,7 +449,7 @@ fn select_30() { fn select_31() { assert_eq!( Query::select() - .expr((1..10_i32).fold(Expr::value(0), |expr, i| { expr.add(i) })) + .expr((1..10_i32).fold(Expr::val(0), |expr, i| { expr.add(i) })) .to_string(MysqlQueryBuilder), "SELECT 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9" ); @@ -666,7 +666,7 @@ fn select_43() { let statement = Query::select() .column(Glyph::Id) .from(Glyph::Table) - .cond_where(Cond::all().add_option::(None)) + .cond_where(Cond::all().add_option::(None)) .to_string(MysqlQueryBuilder); assert_eq!(statement, "SELECT `id` FROM `glyph` WHERE TRUE"); @@ -752,9 +752,9 @@ fn select_48() { .column(Glyph::Id) .from(Glyph::Table) .cond_where( - Cond::all().add_option(Some(ConditionExpression::SimpleExpr( - Expr::tuple([Expr::col(Glyph::Aspect).into(), Expr::value(100)]) - .lt(Expr::tuple([Expr::value(8), Expr::value(100)])), + Cond::all().add_option(Some(ConditionExpression::Expr( + Expr::tuple([Expr::col(Glyph::Aspect).into(), Expr::val(100)]) + .lt(Expr::tuple([Expr::val(8), Expr::val(100)])), ))), ) .to_string(MysqlQueryBuilder); @@ -771,10 +771,10 @@ fn select_48a() { .column(Glyph::Id) .from(Glyph::Table) .cond_where( - Cond::all().add_option(Some(ConditionExpression::SimpleExpr( + Cond::all().add_option(Some(ConditionExpression::Expr( Expr::tuple([ Expr::col(Glyph::Aspect).into(), - Expr::value(String::from("100")), + Expr::val(String::from("100")), ]) .in_tuples([(8, String::from("100"))]), ))), @@ -1567,7 +1567,7 @@ fn sub_query_with_fn() { .to_owned(); let select = Query::select() - .expr(Func::cust(ArrayFunc).arg(SimpleExpr::SubQuery( + .expr(Func::cust(ArrayFunc).arg(Expr::SubQuery( None, Box::new(sub_select.into_sub_query_statement()), ))) diff --git a/tests/postgres/query.rs b/tests/postgres/query.rs index 94a09c1a8..d75fb0ad6 100644 --- a/tests/postgres/query.rs +++ b/tests/postgres/query.rs @@ -433,7 +433,7 @@ fn select_30() { fn select_31() { assert_eq!( Query::select() - .expr((1..10_i32).fold(Expr::value(0), |expr, i| { expr.add(i) })) + .expr((1..10_i32).fold(Expr::val(0), |expr, i| { expr.add(i) })) .to_string(PostgresQueryBuilder), r#"SELECT 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9"# ); @@ -650,7 +650,7 @@ fn select_43() { let statement = Query::select() .column(Glyph::Id) .from(Glyph::Table) - .cond_where(Cond::all().add_option::(None)) + .cond_where(Cond::all().add_option::(None)) .to_string(PostgresQueryBuilder); assert_eq!(statement, r#"SELECT "id" FROM "glyph" WHERE TRUE"#); @@ -736,9 +736,9 @@ fn select_48() { .column(Glyph::Id) .from(Glyph::Table) .cond_where( - Cond::all().add_option(Some(ConditionExpression::SimpleExpr( - Expr::tuple([Expr::col(Glyph::Aspect).into(), Expr::value(100)]) - .lt(Expr::tuple([Expr::value(8), Expr::value(100)])), + Cond::all().add_option(Some(ConditionExpression::Expr( + Expr::tuple([Expr::col(Glyph::Aspect).into(), Expr::val(100)]) + .lt(Expr::tuple([Expr::val(8), Expr::val(100)])), ))), ) .to_string(PostgresQueryBuilder); @@ -755,10 +755,10 @@ fn select_48a() { .column(Glyph::Id) .from(Glyph::Table) .cond_where( - Cond::all().add_option(Some(ConditionExpression::SimpleExpr( + Cond::all().add_option(Some(ConditionExpression::Expr( Expr::tuple([ Expr::col(Glyph::Aspect).into(), - Expr::value(String::from("100")), + Expr::val(String::from("100")), ]) .in_tuples([(8, String::from("100"))]), ))), @@ -1862,7 +1862,7 @@ fn delete_returning_specific_exprs() { fn select_pgtrgm_similarity() { assert_eq!( Query::select() - .expr(Expr::col(Font::Name).binary(PgBinOper::Similarity, Expr::value("serif"))) + .expr(Expr::col(Font::Name).binary(PgBinOper::Similarity, Expr::val("serif"))) .from(Font::Table) .to_string(PostgresQueryBuilder), r#"SELECT "name" % 'serif' FROM "font""# @@ -1873,7 +1873,7 @@ fn select_pgtrgm_similarity() { fn select_pgtrgm_word_similarity() { assert_eq!( Query::select() - .expr(Expr::col(Font::Name).binary(PgBinOper::WordSimilarity, Expr::value("serif"))) + .expr(Expr::col(Font::Name).binary(PgBinOper::WordSimilarity, Expr::val("serif"))) .from(Font::Table) .to_string(PostgresQueryBuilder), r#"SELECT "name" <% 'serif' FROM "font""# @@ -1884,9 +1884,7 @@ fn select_pgtrgm_word_similarity() { fn select_pgtrgm_strict_word_similarity() { assert_eq!( Query::select() - .expr( - Expr::col(Font::Name).binary(PgBinOper::StrictWordSimilarity, Expr::value("serif")) - ) + .expr(Expr::col(Font::Name).binary(PgBinOper::StrictWordSimilarity, Expr::val("serif"))) .from(Font::Table) .to_string(PostgresQueryBuilder), r#"SELECT "name" <<% 'serif' FROM "font""# @@ -1897,7 +1895,7 @@ fn select_pgtrgm_strict_word_similarity() { fn select_pgtrgm_similarity_distance() { assert_eq!( Query::select() - .expr(Expr::col(Font::Name).binary(PgBinOper::SimilarityDistance, Expr::value("serif"))) + .expr(Expr::col(Font::Name).binary(PgBinOper::SimilarityDistance, Expr::val("serif"))) .from(Font::Table) .to_string(PostgresQueryBuilder), r#"SELECT "name" <-> 'serif' FROM "font""# @@ -1909,8 +1907,7 @@ fn select_pgtrgm_word_similarity_distance() { assert_eq!( Query::select() .expr( - Expr::col(Font::Name) - .binary(PgBinOper::WordSimilarityDistance, Expr::value("serif")) + Expr::col(Font::Name).binary(PgBinOper::WordSimilarityDistance, Expr::val("serif")) ) .from(Font::Table) .to_string(PostgresQueryBuilder), @@ -1922,10 +1919,10 @@ fn select_pgtrgm_word_similarity_distance() { fn select_pgtrgm_strict_word_similarity_distance() { assert_eq!( Query::select() - .expr(Expr::col(Font::Name).binary( - PgBinOper::StrictWordSimilarityDistance, - Expr::value("serif") - )) + .expr( + Expr::col(Font::Name) + .binary(PgBinOper::StrictWordSimilarityDistance, Expr::val("serif")) + ) .from(Font::Table) .to_string(PostgresQueryBuilder), r#"SELECT "name" <<<-> 'serif' FROM "font""# @@ -1936,14 +1933,14 @@ fn select_pgtrgm_strict_word_similarity_distance() { fn select_custom_operator() { assert_eq!( Query::select() - .expr(Expr::col(Font::Name).binary(BinOper::Custom("~*"), Expr::value("serif"))) + .expr(Expr::col(Font::Name).binary(BinOper::Custom("~*"), Expr::val("serif"))) .from(Font::Table) .to_string(PostgresQueryBuilder), r#"SELECT "name" ~* 'serif' FROM "font""# ); assert_eq!( Query::select() - .expr(Expr::col(Font::Name).binary(BinOper::Custom("~"), Expr::value("serif"))) + .expr(Expr::col(Font::Name).binary(BinOper::Custom("~"), Expr::val("serif"))) .from(Font::Table) .to_string(PostgresQueryBuilder), r#"SELECT "name" ~ 'serif' FROM "font""# @@ -1989,7 +1986,7 @@ fn sub_query_with_fn() { .to_owned(); let select = Query::select() - .expr(Func::cust(ArrayFunc).arg(SimpleExpr::SubQuery( + .expr(Func::cust(ArrayFunc).arg(Expr::SubQuery( None, Box::new(sub_select.into_sub_query_statement()), ))) @@ -2125,10 +2122,10 @@ fn regex_case_insensitive_bin_oper() { #[test] fn test_issue_674_nested_logical() { - let t = SimpleExpr::Value(true.into()); - let f = SimpleExpr::Value(false.into()); + let t = Expr::Value(true.into()); + let f = Expr::Value(false.into()); - let x_op_y = |x, op, y| SimpleExpr::Binary(Box::new(x), op, Box::new(y)); + let x_op_y = |x, op, y| Expr::Binary(Box::new(x), op, Box::new(y)); let t_or_t = x_op_y(t.clone(), BinOper::Or, t.clone()); let t_or_t_or_f = x_op_y(t_or_t, BinOper::Or, f); let t_or_t_or_f_and_t = x_op_y(t_or_t_or_f.clone(), BinOper::And, t); @@ -2145,11 +2142,11 @@ fn test_issue_674_nested_logical() { #[test] fn test_issue_674_nested_comparison() { - let int100 = SimpleExpr::Value(100i32.into()); - let int0 = SimpleExpr::Value(0i32.into()); - let int1 = SimpleExpr::Value(1i32.into()); + let int100 = Expr::Value(100i32.into()); + let int0 = Expr::Value(0i32.into()); + let int1 = Expr::Value(1i32.into()); - let x_op_y = |x, op, y| SimpleExpr::Binary(Box::new(x), op, Box::new(y)); + let x_op_y = |x, op, y| Expr::Binary(Box::new(x), op, Box::new(y)); let t_smaller_than_t = x_op_y(int100, BinOper::SmallerThan, int0); let t_smaller_than_t_smaller_than_f = x_op_y(t_smaller_than_t, BinOper::SmallerThan, int1); @@ -2165,11 +2162,11 @@ fn test_issue_674_nested_comparison() { #[test] fn test_issue_674_and_inside_not() { - let t = SimpleExpr::Value(true.into()); - let f = SimpleExpr::Value(false.into()); + let t = Expr::Value(true.into()); + let f = Expr::Value(false.into()); - let op_x = |op, x| SimpleExpr::Unary(op, Box::new(x)); - let x_op_y = |x, op, y| SimpleExpr::Binary(Box::new(x), op, Box::new(y)); + let op_x = |op, x| Expr::Unary(op, Box::new(x)); + let x_op_y = |x, op, y| Expr::Binary(Box::new(x), op, Box::new(y)); let f_and_t = x_op_y(f, BinOper::And, t); let not_f_and_t = op_x(UnOper::Not, f_and_t); @@ -2185,7 +2182,7 @@ fn test_issue_674_and_inside_not() { #[test] fn test_issue_674_nested_logical_panic() { - let e = SimpleExpr::from(true).and(SimpleExpr::from(true).and(true.into()).and(true.into())); + let e = Expr::from(true).and(Expr::from(true).and(true).and(true)); assert_eq!( Query::select() diff --git a/tests/sqlite/query.rs b/tests/sqlite/query.rs index a86d63e7a..06fa46a6f 100644 --- a/tests/sqlite/query.rs +++ b/tests/sqlite/query.rs @@ -433,7 +433,7 @@ fn select_30() { fn select_31() { assert_eq!( Query::select() - .expr((1..10_i32).fold(Expr::value(0), |expr, i| { expr.add(i) })) + .expr((1..10_i32).fold(Expr::val(0), |expr, i| { expr.add(i) })) .to_string(SqliteQueryBuilder), r"SELECT 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9" ); @@ -650,7 +650,7 @@ fn select_43() { let statement = Query::select() .column(Glyph::Id) .from(Glyph::Table) - .cond_where(Cond::all().add_option::(None)) + .cond_where(Cond::all().add_option::(None)) .to_string(SqliteQueryBuilder); assert_eq!(statement, r#"SELECT "id" FROM "glyph" WHERE TRUE"#); @@ -736,9 +736,9 @@ fn select_48() { .column(Glyph::Id) .from(Glyph::Table) .cond_where( - Cond::all().add_option(Some(ConditionExpression::SimpleExpr( - Expr::tuple([Expr::col(Glyph::Aspect).into(), Expr::value(100)]) - .lt(Expr::tuple([Expr::value(8), Expr::value(100)])), + Cond::all().add_option(Some(ConditionExpression::Expr( + Expr::tuple([Expr::col(Glyph::Aspect).into(), Expr::val(100)]) + .lt(Expr::tuple([Expr::val(8), Expr::val(100)])), ))), ) .to_string(SqliteQueryBuilder); @@ -755,12 +755,9 @@ fn select_48a() { .column(Glyph::Id) .from(Glyph::Table) .cond_where( - Cond::all().add_option(Some(ConditionExpression::SimpleExpr( - Expr::tuple([ - Expr::col(Glyph::Aspect).into(), - Expr::value(String::from("100")), - ]) - .in_tuples([(8, String::from("100"))]), + Cond::all().add_option(Some(ConditionExpression::Expr( + Expr::tuple([Expr::col(Glyph::Aspect), Expr::val(String::from("100"))]) + .in_tuples([(8, String::from("100"))]), ))), ) .to_string(SqliteQueryBuilder); @@ -1782,7 +1779,7 @@ fn sub_query_with_fn() { .to_owned(); let select = Query::select() - .expr(Func::cust(ArrayFunc).arg(SimpleExpr::SubQuery( + .expr(Func::cust(ArrayFunc).arg(Expr::SubQuery( None, Box::new(sub_select.into_sub_query_statement()), )))