From 55565dbfeeacf79fa8aeb1f555683d320e52725b Mon Sep 17 00:00:00 2001 From: Dmitrii Aleksandrov Date: Sun, 7 Jul 2024 21:13:47 +0400 Subject: [PATCH 1/3] Add `ExprTrait` (#771) --- src/expr.rs | 483 ++++++++++++++++++++++++--------- src/extension/postgres/expr.rs | 24 +- src/extension/sqlite/expr.rs | 16 +- 3 files changed, 370 insertions(+), 153 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index 165fb09c9..a5ce96cc9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -37,52 +37,306 @@ pub enum SimpleExpr { Constant(Value), } -pub(crate) mod private { - use crate::{BinOper, LikeExpr, SimpleExpr, UnOper}; - - pub trait Expression: Sized { - fn un_op(self, o: UnOper) -> SimpleExpr; - - fn bin_op(self, op: O, right: T) -> SimpleExpr - where - O: Into, - T: Into; - - fn like_like(self, op: O, like: LikeExpr) -> SimpleExpr - where - O: Into, - { - self.bin_op( - op, - match like.escape { - Some(escape) => SimpleExpr::Binary( - Box::new(like.pattern.into()), - BinOper::Escape, - Box::new(SimpleExpr::Constant(escape.into())), - ), - None => like.pattern.into(), - }, - ) - } +/// "Operator" methods for building complex expressions. +/// +/// ## Examples +/// +/// ```no_run +/// use sea_query::*; +/// +/// let expr = 1_i32.cast_as(Alias::new("REAL")); +/// +/// let expr = Func::char_length("abc").eq(3_i32); +/// +/// let expr = Expr::current_date() +/// .cast_as(Alias::new("TEXT")) +/// .like("2024%"); +/// ``` +pub trait ExprTrait: Sized { + fn add(self, right: R) -> SimpleExpr + where + R: Into, + { + ExprTrait::binary(self, BinOper::Add, right) } -} -use private::Expression; + #[allow(clippy::wrong_self_convention)] + fn as_enum(self, type_name: N) -> SimpleExpr + where + N: IntoIden; -impl Expression for Expr { - fn un_op(mut self, o: UnOper) -> SimpleExpr { - self.uopr = Some(o); - self.into() + fn and(self, right: R) -> SimpleExpr + where + R: Into, + { + ExprTrait::binary(self, BinOper::And, right) } - fn bin_op(mut self, op: O, right: T) -> SimpleExpr + fn between(self, a: A, b: B) -> SimpleExpr + where + A: Into, + B: Into, + { + self.binary( + BinOper::Between, + SimpleExpr::Binary(Box::new(a.into()), BinOper::And, Box::new(b.into())), + ) + } + + fn binary(self, op: O, right: R) -> SimpleExpr where O: Into, - T: Into, + R: Into; + + fn cast_as(self, type_name: N) -> SimpleExpr + where + N: IntoIden; + + fn div(self, right: R) -> SimpleExpr + where + R: Into, + { + ExprTrait::binary(self, BinOper::Div, right) + } + + fn eq(self, right: R) -> SimpleExpr + where + R: Into, + { + ExprTrait::binary(self, BinOper::Equal, right) + } + + fn equals(self, col: C) -> SimpleExpr + where + C: IntoColumnRef, + { + self.binary(BinOper::Equal, col.into_column_ref()) + } + + fn gt(self, right: R) -> SimpleExpr + where + R: Into, + { + ExprTrait::binary(self, BinOper::GreaterThan, right) + } + + fn gte(self, right: R) -> SimpleExpr + where + R: Into, + { + ExprTrait::binary(self, BinOper::GreaterThanOrEqual, right) + } + + fn in_subquery(self, sel: SelectStatement) -> SimpleExpr { + self.binary( + BinOper::In, + SimpleExpr::SubQuery(None, Box::new(sel.into_sub_query_statement())), + ) + } + + fn in_tuples(self, v: I) -> SimpleExpr + where + V: IntoValueTuple, + I: IntoIterator, + { + self.binary( + BinOper::In, + SimpleExpr::Tuple( + v.into_iter() + .map(|m| SimpleExpr::Values(m.into_value_tuple().into_iter().collect())) + .collect(), + ), + ) + } + + fn is(self, right: R) -> SimpleExpr + where + R: Into, + { + self.binary(BinOper::Is, right) + } + + #[allow(clippy::wrong_self_convention)] + fn is_in(self, v: I) -> SimpleExpr + where + V: Into, + I: IntoIterator, + { + self.binary( + BinOper::In, + SimpleExpr::Tuple(v.into_iter().map(|v| v.into()).collect()), + ) + } + + #[allow(clippy::wrong_self_convention)] + fn is_not(self, right: R) -> SimpleExpr + where + R: Into, + { + self.binary(BinOper::IsNot, right) + } + + #[allow(clippy::wrong_self_convention)] + fn is_not_in(self, v: I) -> SimpleExpr + where + V: Into, + I: IntoIterator, + { + self.binary( + BinOper::NotIn, + SimpleExpr::Tuple(v.into_iter().map(|v| v.into()).collect()), + ) + } + + #[allow(clippy::wrong_self_convention)] + fn is_not_null(self) -> SimpleExpr { + self.binary(BinOper::IsNot, Keyword::Null) + } + + #[allow(clippy::wrong_self_convention)] + fn is_null(self) -> SimpleExpr { + self.binary(BinOper::Is, Keyword::Null) + } + + fn left_shift(self, right: R) -> SimpleExpr + where + R: Into, + { + self.binary(BinOper::LShift, right) + } + + fn like(self, like: L) -> SimpleExpr + where + L: IntoLikeExpr, + { + ExprTrait::binary(self, BinOper::Like, like.into_like_expr()) + } + + fn lt(self, right: R) -> SimpleExpr + where + R: Into, + { + ExprTrait::binary(self, BinOper::SmallerThan, right) + } + + fn lte(self, right: R) -> SimpleExpr + where + R: Into, + { + ExprTrait::binary(self, BinOper::SmallerThanOrEqual, right) + } + + fn modulo(self, right: R) -> SimpleExpr + where + R: Into, + { + self.binary(BinOper::Mod, right) + } + + fn mul(self, right: R) -> SimpleExpr + where + R: Into, + { + ExprTrait::binary(self, BinOper::Mul, right) + } + + fn ne(self, right: R) -> SimpleExpr + where + R: Into, + { + ExprTrait::binary(self, BinOper::NotEqual, right) + } + + fn not(self) -> SimpleExpr { + self.unary(UnOper::Not) + } + + fn not_between(self, a: A, b: B) -> SimpleExpr + where + A: Into, + B: Into, + { + self.binary( + BinOper::NotBetween, + SimpleExpr::Binary(Box::new(a.into()), BinOper::And, Box::new(b.into())), + ) + } + + fn not_equals(self, col: C) -> SimpleExpr + where + C: IntoColumnRef, + { + self.binary(BinOper::NotEqual, col.into_column_ref()) + } + + fn not_in_subquery(self, sel: SelectStatement) -> SimpleExpr { + self.binary( + BinOper::NotIn, + SimpleExpr::SubQuery(None, Box::new(sel.into_sub_query_statement())), + ) + } + + fn not_like(self, like: L) -> SimpleExpr + where + L: IntoLikeExpr, + { + ExprTrait::binary(self, BinOper::NotLike, like.into_like_expr()) + } + + fn or(self, right: R) -> SimpleExpr + where + R: Into, + { + ExprTrait::binary(self, BinOper::Or, right) + } + + fn right_shift(self, right: R) -> SimpleExpr + where + R: Into, { - self.bopr = Some(op.into()); - self.right = Some(right.into()); - self.into() + self.binary(BinOper::RShift, right) + } + + fn sub(self, right: R) -> SimpleExpr + where + R: Into, + { + ExprTrait::binary(self, BinOper::Sub, right) + } + + fn unary(self, o: UnOper) -> SimpleExpr; +} + +/// This generic implementation covers all expression types, +/// including [ColumnRef], [Value], [FunctionCall], [SimpleExpr]... +impl ExprTrait for T +where + T: Into, +{ + fn as_enum(self, type_name: N) -> SimpleExpr + where + N: IntoIden, + { + SimpleExpr::AsEnum(type_name.into_iden(), Box::new(self.into())) + } + + fn binary(self, op: O, right: R) -> SimpleExpr + where + O: Into, + R: Into, + { + SimpleExpr::Binary(Box::new(self.into()), op.into(), Box::new(right.into())) + } + + fn cast_as(self, type_name: N) -> SimpleExpr + where + N: IntoIden, + { + SimpleExpr::FunctionCall(Func::cast_as(self, type_name)) + } + + fn unary(self, op: UnOper) -> SimpleExpr { + SimpleExpr::Unary(op, Box::new(self.into())) } } @@ -532,7 +786,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::Equal, v) + ExprTrait::eq(self, v) } /// Express a not equal (`<>`) expression. @@ -566,7 +820,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::NotEqual, v) + ExprTrait::ne(self, v) } /// Express a equal expression between two table columns, @@ -600,7 +854,7 @@ impl Expr { where C: IntoColumnRef, { - self.binary(BinOper::Equal, col.into_column_ref()) + ExprTrait::equals(self, col) } /// Express a not equal expression between two table columns, @@ -634,7 +888,7 @@ impl Expr { where C: IntoColumnRef, { - self.binary(BinOper::NotEqual, col.into_column_ref()) + ExprTrait::not_equals(self, col) } /// Express a greater than (`>`) expression. @@ -667,7 +921,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::GreaterThan, v.into()) + ExprTrait::gt(self, v) } /// Express a greater than or equal (`>=`) expression. @@ -700,7 +954,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::GreaterThanOrEqual, v) + ExprTrait::gte(self, v) } /// Express a less than (`<`) expression. @@ -733,7 +987,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::SmallerThan, v) + ExprTrait::lt(self, v) } /// Express a less than or equal (`<=`) expression. @@ -766,7 +1020,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::SmallerThanOrEqual, v) + ExprTrait::lte(self, v) } /// Express an arithmetic addition operation. @@ -800,7 +1054,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::Add, v) + ExprTrait::add(self, v) } /// Express an arithmetic subtraction operation. @@ -834,7 +1088,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::Sub, v) + ExprTrait::sub(self, v) } /// Express an arithmetic multiplication operation. @@ -868,7 +1122,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::Mul, v) + ExprTrait::mul(self, v) } /// Express an arithmetic division operation. @@ -902,7 +1156,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::Div, v) + ExprTrait::div(self, v) } /// Express an arithmetic modulo operation. @@ -936,7 +1190,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::Mod, v) + ExprTrait::modulo(self, v) } /// Express a bitwise left shift. @@ -970,7 +1224,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::LShift, v) + ExprTrait::left_shift(self, v) } /// Express a bitwise right shift. @@ -1004,7 +1258,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::RShift, v) + ExprTrait::right_shift(self, v) } /// Express a `BETWEEN` expression. @@ -1037,7 +1291,7 @@ impl Expr { where V: Into, { - self.between_or_not_between(BinOper::Between, a, b) + ExprTrait::between(self, a, b) } /// Express a `NOT BETWEEN` expression. @@ -1070,17 +1324,7 @@ impl Expr { where V: Into, { - self.between_or_not_between(BinOper::NotBetween, a, b) - } - - fn between_or_not_between(self, op: BinOper, a: V, b: V) -> SimpleExpr - where - V: Into, - { - self.binary( - op, - SimpleExpr::Binary(Box::new(a.into()), BinOper::And, Box::new(b.into())), - ) + ExprTrait::not_between(self, a, b) } /// Express a `LIKE` expression. @@ -1135,12 +1379,12 @@ impl Expr { /// ); /// ``` pub fn like(self, like: L) -> SimpleExpr { - self.like_like(BinOper::Like, like.into_like_expr()) + ExprTrait::like(self, like) } /// Express a `NOT LIKE` expression pub fn not_like(self, like: L) -> SimpleExpr { - self.like_like(BinOper::NotLike, like.into_like_expr()) + ExprTrait::not_like(self, like) } /// Express a `IS NULL` expression. @@ -1171,7 +1415,7 @@ impl Expr { /// ``` #[allow(clippy::wrong_self_convention)] pub fn is_null(self) -> SimpleExpr { - self.binary(BinOper::Is, Keyword::Null) + ExprTrait::is_null(self) } /// Express a `IS` expression. @@ -1204,7 +1448,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::Is, v) + ExprTrait::is(self, v) } /// Express a `IS NOT NULL` expression. @@ -1235,7 +1479,7 @@ impl Expr { /// ``` #[allow(clippy::wrong_self_convention)] pub fn is_not_null(self) -> SimpleExpr { - self.binary(BinOper::IsNot, Keyword::Null) + ExprTrait::is_not_null(self) } /// Express a `IS NOT` expression. @@ -1268,7 +1512,7 @@ impl Expr { where V: Into, { - self.binary(BinOper::IsNot, v) + ExprTrait::is_not(self, v) } /// Create any binary operation @@ -1303,7 +1547,7 @@ impl Expr { O: Into, T: Into, { - self.bin_op(op, right) + ExprTrait::binary(self, op, right) } /// Negates an expression with `NOT`. @@ -1334,7 +1578,7 @@ impl Expr { /// ``` #[allow(clippy::should_implement_trait)] pub fn not(self) -> SimpleExpr { - self.un_op(UnOper::Not) + ExprTrait::not(self) } /// Express a `MAX` function. @@ -1564,14 +1808,12 @@ impl Expr { /// ); /// ``` #[allow(clippy::wrong_self_convention)] - pub fn is_in(mut self, v: I) -> SimpleExpr + pub fn is_in(self, v: I) -> SimpleExpr where V: Into, I: IntoIterator, { - self.bopr = Some(BinOper::In); - self.right = Some(SimpleExpr::Tuple(v.into_iter().map(|v| v.into()).collect())); - self.into() + ExprTrait::is_in(self, v) } /// Express a `IN` sub expression. @@ -1609,18 +1851,12 @@ impl Expr { /// ); /// ``` #[allow(clippy::wrong_self_convention)] - pub fn in_tuples(mut self, v: I) -> SimpleExpr + pub fn in_tuples(self, v: I) -> SimpleExpr where V: IntoValueTuple, I: IntoIterator, { - self.bopr = Some(BinOper::In); - self.right = Some(SimpleExpr::Tuple( - v.into_iter() - .map(|m| SimpleExpr::Values(m.into_value_tuple().into_iter().collect())) - .collect(), - )); - self.into() + ExprTrait::in_tuples(self, v) } /// Express a `NOT IN` expression. @@ -1673,14 +1909,12 @@ impl Expr { /// ); /// ``` #[allow(clippy::wrong_self_convention)] - pub fn is_not_in(mut self, v: I) -> SimpleExpr + pub fn is_not_in(self, v: I) -> SimpleExpr where V: Into, I: IntoIterator, { - self.bopr = Some(BinOper::NotIn); - self.right = Some(SimpleExpr::Tuple(v.into_iter().map(|v| v.into()).collect())); - self.into() + ExprTrait::is_not_in(self, v) } /// Express a `IN` sub-query expression. @@ -1714,13 +1948,8 @@ impl Expr { /// ); /// ``` #[allow(clippy::wrong_self_convention)] - pub fn in_subquery(mut self, sel: SelectStatement) -> SimpleExpr { - self.bopr = Some(BinOper::In); - self.right = Some(SimpleExpr::SubQuery( - None, - Box::new(sel.into_sub_query_statement()), - )); - self.into() + pub fn in_subquery(self, sel: SelectStatement) -> SimpleExpr { + ExprTrait::in_subquery(self, sel) } /// Express a `NOT IN` sub-query expression. @@ -1754,13 +1983,8 @@ impl Expr { /// ); /// ``` #[allow(clippy::wrong_self_convention)] - pub fn not_in_subquery(mut self, sel: SelectStatement) -> SimpleExpr { - self.bopr = Some(BinOper::NotIn); - self.right = Some(SimpleExpr::SubQuery( - None, - Box::new(sel.into_sub_query_statement()), - )); - self.into() + pub fn not_in_subquery(self, sel: SelectStatement) -> SimpleExpr { + ExprTrait::not_in_subquery(self, sel) } /// Express a `EXISTS` sub-query expression. @@ -1913,7 +2137,7 @@ impl Expr { where T: IntoIden, { - SimpleExpr::AsEnum(type_name.into_iden(), Box::new(self.into())) + ExprTrait::as_enum(self, type_name) } /// Adds new `CASE WHEN` to existing case statement. @@ -1976,8 +2200,7 @@ impl Expr { where T: IntoIden, { - let func = Func::cast_as(self, type_name); - SimpleExpr::FunctionCall(func) + ExprTrait::cast_as(self, type_name) } /// Keyword `CURRENT_TIMESTAMP`. @@ -2115,17 +2338,16 @@ impl From for SimpleExpr { } } -impl Expression for SimpleExpr { - fn un_op(self, op: UnOper) -> SimpleExpr { - SimpleExpr::Unary(op, Box::new(self)) - } - - fn bin_op(self, op: O, right: T) -> SimpleExpr - where - O: Into, - T: Into, - { - SimpleExpr::Binary(Box::new(self), op.into(), Box::new(right.into())) +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(), + } } } @@ -2158,7 +2380,7 @@ impl SimpleExpr { /// ``` #[allow(clippy::should_implement_trait)] pub fn not(self) -> SimpleExpr { - self.un_op(UnOper::Not) + ExprTrait::not(self) } /// Express a logical `AND` operation. @@ -2191,7 +2413,7 @@ impl SimpleExpr { /// ); /// ``` pub fn and(self, right: SimpleExpr) -> Self { - self.binary(BinOper::And, right) + ExprTrait::and(self, right) } /// Express a logical `OR` operation. @@ -2222,7 +2444,7 @@ impl SimpleExpr { /// ); /// ``` pub fn or(self, right: SimpleExpr) -> Self { - self.binary(BinOper::Or, right) + ExprTrait::or(self, right) } /// Express an equal (`=`) expression. @@ -2255,7 +2477,7 @@ impl SimpleExpr { where V: Into, { - self.binary(BinOper::Equal, v) + ExprTrait::eq(self, v) } /// Express a not equal (`<>`) expression. @@ -2288,7 +2510,7 @@ impl SimpleExpr { where V: Into, { - self.binary(BinOper::NotEqual, v) + ExprTrait::ne(self, v) } /// Perform addition with another [`SimpleExpr`]. @@ -2325,7 +2547,7 @@ impl SimpleExpr { where T: Into, { - self.binary(BinOper::Add, right) + ExprTrait::add(self, right) } /// Perform multiplication with another [`SimpleExpr`]. @@ -2362,7 +2584,7 @@ impl SimpleExpr { where T: Into, { - self.binary(BinOper::Mul, right.into()) + ExprTrait::mul(self, right) } /// Perform division with another [`SimpleExpr`]. @@ -2399,7 +2621,7 @@ impl SimpleExpr { where T: Into, { - self.binary(BinOper::Div, right.into()) + ExprTrait::div(self, right) } /// Perform subtraction with another [`SimpleExpr`]. @@ -2436,7 +2658,7 @@ impl SimpleExpr { where T: Into, { - self.binary(BinOper::Sub, right) + ExprTrait::sub(self, right) } /// Express a `CAST AS` expression. @@ -2467,8 +2689,7 @@ impl SimpleExpr { where T: IntoIden, { - let func = Func::cast_as(self, type_name); - Self::FunctionCall(func) + ExprTrait::cast_as(self, type_name) } /// Create any binary operation @@ -2502,7 +2723,7 @@ impl SimpleExpr { O: Into, T: Into, { - self.bin_op(op, right) + ExprTrait::binary(self, op, right) } /// Express a `LIKE` expression. @@ -2532,12 +2753,12 @@ impl SimpleExpr { /// ); /// ``` pub fn like(self, like: L) -> Self { - self.like_like(BinOper::Like, like.into_like_expr()) + ExprTrait::like(self, like) } /// Express a `NOT LIKE` expression pub fn not_like(self, like: L) -> Self { - self.like_like(BinOper::NotLike, like.into_like_expr()) + ExprTrait::not_like(self, like) } pub(crate) fn is_binary(&self) -> bool { diff --git a/src/extension/postgres/expr.rs b/src/extension/postgres/expr.rs index a8ca29282..4e2ca6639 100644 --- a/src/extension/postgres/expr.rs +++ b/src/extension/postgres/expr.rs @@ -1,7 +1,7 @@ use super::PgBinOper; -use crate::{expr::private::Expression, Expr, IntoLikeExpr, SimpleExpr}; +use crate::{expr::ExprTrait, IntoLikeExpr, SimpleExpr}; -pub trait PgExpr: Expression { +pub trait PgExpr: ExprTrait { /// Express an postgres concatenate (`||`) expression. /// /// # Examples @@ -24,7 +24,7 @@ pub trait PgExpr: Expression { where T: Into, { - self.bin_op(PgBinOper::Concatenate, right) + self.binary(PgBinOper::Concatenate, right) } /// Alias of [`PgExpr::concatenate`] fn concat(self, right: T) -> SimpleExpr @@ -57,7 +57,7 @@ pub trait PgExpr: Expression { where T: Into, { - self.bin_op(PgBinOper::Matches, expr) + self.binary(PgBinOper::Matches, expr) } /// Express an postgres fulltext search contains (`@>`) expression. @@ -83,7 +83,7 @@ pub trait PgExpr: Expression { where T: Into, { - self.bin_op(PgBinOper::Contains, expr) + self.binary(PgBinOper::Contains, expr) } /// Express an postgres fulltext search contained (`<@`) expression. @@ -109,7 +109,7 @@ pub trait PgExpr: Expression { where T: Into, { - self.bin_op(PgBinOper::Contained, expr) + self.binary(PgBinOper::Contained, expr) } /// Express a `ILIKE` expression. @@ -134,7 +134,7 @@ pub trait PgExpr: Expression { where L: IntoLikeExpr, { - self.like_like(PgBinOper::ILike, like.into_like_expr()) + self.binary(PgBinOper::ILike, like.into_like_expr()) } /// Express a `NOT ILIKE` expression @@ -142,7 +142,7 @@ pub trait PgExpr: Expression { where L: IntoLikeExpr, { - self.like_like(PgBinOper::NotILike, like.into_like_expr()) + self.binary(PgBinOper::NotILike, like.into_like_expr()) } /// Express a postgres retrieves JSON field as JSON value (`->`). @@ -167,7 +167,7 @@ pub trait PgExpr: Expression { where T: Into, { - self.bin_op(PgBinOper::GetJsonField, right) + self.binary(PgBinOper::GetJsonField, right) } /// Express a postgres retrieves JSON field and casts it to an appropriate SQL type (`->>`). @@ -192,10 +192,8 @@ pub trait PgExpr: Expression { where T: Into, { - self.bin_op(PgBinOper::CastJsonField, right) + self.binary(PgBinOper::CastJsonField, right) } } -impl PgExpr for Expr {} - -impl PgExpr for SimpleExpr {} +impl PgExpr for T where T: ExprTrait {} diff --git a/src/extension/sqlite/expr.rs b/src/extension/sqlite/expr.rs index 1623f5c59..70d8e3bf6 100644 --- a/src/extension/sqlite/expr.rs +++ b/src/extension/sqlite/expr.rs @@ -1,8 +1,8 @@ -use crate::{expr::private::Expression, Expr, SimpleExpr}; +use crate::{expr::ExprTrait, SimpleExpr}; use super::SqliteBinOper; -pub trait SqliteExpr: Expression { +pub trait SqliteExpr: ExprTrait { /// Express an sqlite `GLOB` operator. /// /// # Examples @@ -25,7 +25,7 @@ pub trait SqliteExpr: Expression { where T: Into, { - self.bin_op(SqliteBinOper::Glob, right) + self.binary(SqliteBinOper::Glob, right) } /// Express an sqlite `MATCH` operator. @@ -50,7 +50,7 @@ pub trait SqliteExpr: Expression { where T: Into, { - self.bin_op(SqliteBinOper::Match, right) + self.binary(SqliteBinOper::Match, right) } /// Express an sqlite retrieves JSON field as JSON value (`->`). @@ -75,7 +75,7 @@ pub trait SqliteExpr: Expression { where T: Into, { - self.bin_op(SqliteBinOper::GetJsonField, right) + self.binary(SqliteBinOper::GetJsonField, right) } /// Express an sqlite retrieves JSON field and casts it to an appropriate SQL type (`->>`). @@ -100,10 +100,8 @@ pub trait SqliteExpr: Expression { where T: Into, { - self.bin_op(SqliteBinOper::CastJsonField, right) + self.binary(SqliteBinOper::CastJsonField, right) } } -impl SqliteExpr for Expr {} - -impl SqliteExpr for SimpleExpr {} +impl SqliteExpr for T where T: ExprTrait {} From d9e03fd08813b79bbd30007ea6354b23f9b11cae Mon Sep 17 00:00:00 2001 From: Dmitrii Aleksandrov Date: Fri, 19 Jul 2024 01:58:55 +0400 Subject: [PATCH 2/3] Revert breaking changes to `PgExpr` and `SqliteExpr` impls --- src/extension/postgres/expr.rs | 14 ++++++++++++-- src/extension/sqlite/expr.rs | 12 ++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/extension/postgres/expr.rs b/src/extension/postgres/expr.rs index 4e2ca6639..8c4e89421 100644 --- a/src/extension/postgres/expr.rs +++ b/src/extension/postgres/expr.rs @@ -1,5 +1,7 @@ use super::PgBinOper; -use crate::{expr::ExprTrait, IntoLikeExpr, SimpleExpr}; +use crate::{ + ColumnRef, Expr, ExprTrait, FunctionCall, IntoLikeExpr, Keyword, LikeExpr, SimpleExpr, Value, +}; pub trait PgExpr: ExprTrait { /// Express an postgres concatenate (`||`) expression. @@ -196,4 +198,12 @@ pub trait PgExpr: ExprTrait { } } -impl PgExpr for T where T: ExprTrait {} +// TODO: https://github.com/SeaQL/sea-query/discussions/795: +// replace all of this with `impl PgExpr for T where T: ExprTrait {}` +impl PgExpr for Expr {} +impl PgExpr for SimpleExpr {} +impl PgExpr for FunctionCall {} +impl PgExpr for ColumnRef {} +impl PgExpr for Keyword {} +impl PgExpr for LikeExpr {} +impl PgExpr for Value {} diff --git a/src/extension/sqlite/expr.rs b/src/extension/sqlite/expr.rs index 70d8e3bf6..738fff4f5 100644 --- a/src/extension/sqlite/expr.rs +++ b/src/extension/sqlite/expr.rs @@ -1,4 +1,4 @@ -use crate::{expr::ExprTrait, SimpleExpr}; +use crate::{ColumnRef, Expr, ExprTrait, FunctionCall, Keyword, LikeExpr, SimpleExpr, Value}; use super::SqliteBinOper; @@ -104,4 +104,12 @@ pub trait SqliteExpr: ExprTrait { } } -impl SqliteExpr for T where T: ExprTrait {} +// TODO: https://github.com/SeaQL/sea-query/discussions/795: +// replace all of this with `impl PgExpr for T where T: ExprTrait {}` +impl SqliteExpr for Expr {} +impl SqliteExpr for SimpleExpr {} +impl SqliteExpr for FunctionCall {} +impl SqliteExpr for ColumnRef {} +impl SqliteExpr for Keyword {} +impl SqliteExpr for LikeExpr {} +impl SqliteExpr for Value {} From 98f7d34b91cb528873d4261c17cc257f72986786 Mon Sep 17 00:00:00 2001 From: Dmitrii Aleksandrov Date: Mon, 22 Jul 2024 17:56:56 +0400 Subject: [PATCH 3/3] Add docs/doctests --- src/expr.rs | 1084 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1075 insertions(+), 9 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index a5ce96cc9..f6b33635c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -53,6 +53,32 @@ pub enum SimpleExpr { /// .like("2024%"); /// ``` pub trait ExprTrait: Sized { + /// Express an arithmetic addition operation. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where(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"# + /// ); + /// ``` fn add(self, right: R) -> SimpleExpr where R: Into, @@ -60,6 +86,32 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::Add, right) } + /// Express a `AS enum` expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::insert() + /// .into_table(Char::Table) + /// .columns([Char::FontSize]) + /// .values_panic(["large".as_enum(Alias::new("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')"# + /// ); + /// ``` #[allow(clippy::wrong_self_convention)] fn as_enum(self, type_name: N) -> SimpleExpr where @@ -72,6 +124,32 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::And, right) } + /// Express a `BETWEEN` expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::SizeW).into_column_ref().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"# + /// ); + /// ``` fn between(self, a: A, b: B) -> SimpleExpr where A: Into, @@ -83,15 +161,92 @@ pub trait ExprTrait: Sized { ) } + /// Create any binary operation + /// + /// # Examples + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .cond_where(all![ + /// Char::SizeW.into_column_ref().binary(BinOper::SmallerThan, 10), + /// Char::SizeW.into_column_ref().binary(BinOper::GreaterThan, Char::SizeH.into_column_ref()) + /// ]) + /// .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""# + /// ); + /// ``` fn binary(self, op: O, right: R) -> SimpleExpr where O: Into, R: Into; + /// Express a `CAST AS` expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr("1".cast_as(Alias::new("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)"# + /// ); + /// ``` fn cast_as(self, type_name: N) -> SimpleExpr where N: IntoIden; + /// Express an arithmetic division operation. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where(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"# + /// ); + /// ``` fn div(self, right: R) -> SimpleExpr where R: Into, @@ -99,6 +254,34 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::Div, right) } + /// Express an equal (`=`) expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// // Sometimes, you'll have to qualify the call because of conflicting std traits. + /// .and_where(ExprTrait::eq("What!", "Nothing")) + /// .and_where(Char::Id.into_column_ref().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"# + /// ); + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'What!' = 'Nothing' AND "id" = 1"# + /// ); + /// assert_eq!( + /// query.to_string(SqliteQueryBuilder), + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'What!' = 'Nothing' AND "id" = 1"# + /// ); + /// ``` fn eq(self, right: R) -> SimpleExpr where R: Into, @@ -106,6 +289,33 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::Equal, right) } + /// Express a equal expression between two table columns, + /// you will mainly use this to relate identical value between two table columns. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::FontId).into_column_ref().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`"# + /// ); + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" = "font"."id""# + /// ); + /// assert_eq!( + /// query.to_string(SqliteQueryBuilder), + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" = "font"."id""# + /// ); + /// ``` fn equals(self, col: C) -> SimpleExpr where C: IntoColumnRef, @@ -113,6 +323,32 @@ pub trait ExprTrait: Sized { self.binary(BinOper::Equal, col.into_column_ref()) } + /// Express a greater than (`>`) expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::SizeW).into_column_ref().gt(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"# + /// ); + /// ``` fn gt(self, right: R) -> SimpleExpr where R: Into, @@ -120,6 +356,32 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::GreaterThan, right) } + /// Express a greater than or equal (`>=`) expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::SizeW).into_column_ref().gte(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"# + /// ); + /// ``` fn gte(self, right: R) -> SimpleExpr where R: Into, @@ -127,13 +389,79 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::GreaterThanOrEqual, right) } - fn in_subquery(self, sel: SelectStatement) -> SimpleExpr { - self.binary( - BinOper::In, - SimpleExpr::SubQuery(None, Box::new(sel.into_sub_query_statement())), - ) - } - + /// Express a `IN` sub-query expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where(Char::SizeW.into_column_ref().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)"# + /// ); + /// ``` + fn in_subquery(self, sel: SelectStatement) -> SimpleExpr { + self.binary( + BinOper::In, + SimpleExpr::SubQuery(None, Box::new(sel.into_sub_query_statement())), + ) + } + + /// Express a `IN` sub expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::FontId]) + /// .from(Char::Table) + /// .and_where( + /// ExprTrait::in_tuples( + /// Expr::tuple([ + /// Expr::col(Char::Character).into(), + /// Expr::col(Char::FontId).into(), + /// ]), + /// [(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'))"# + /// ); + /// ``` fn in_tuples(self, v: I) -> SimpleExpr where V: IntoValueTuple, @@ -149,6 +477,32 @@ pub trait ExprTrait: Sized { ) } + /// Express a `IS` expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::Ascii).into_column_ref().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"# + /// ); + /// ``` fn is(self, right: R) -> SimpleExpr where R: Into, @@ -156,6 +510,55 @@ pub trait ExprTrait: Sized { self.binary(BinOper::Is, right) } + /// Express a `IN` expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Id]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::SizeW).into_column_ref().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((Char::Table, Char::SizeW).into_column_ref().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)] fn is_in(self, v: I) -> SimpleExpr where @@ -168,6 +571,32 @@ pub trait ExprTrait: Sized { ) } + /// Express a `IS NOT` expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::Ascii).into_column_ref().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"# + /// ); + /// ``` #[allow(clippy::wrong_self_convention)] fn is_not(self, right: R) -> SimpleExpr where @@ -176,6 +605,55 @@ pub trait ExprTrait: Sized { self.binary(BinOper::IsNot, right) } + /// Express a `NOT IN` expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Id]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::SizeW).into_column_ref().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((Char::Table, Char::SizeW).into_column_ref().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)] fn is_not_in(self, v: I) -> SimpleExpr where @@ -188,16 +666,94 @@ pub trait ExprTrait: Sized { ) } + /// Express a `IS NOT NULL` expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::SizeW).into_column_ref().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)] fn is_not_null(self) -> SimpleExpr { self.binary(BinOper::IsNot, Keyword::Null) } + /// Express a `IS NULL` expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::SizeW).into_column_ref().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)] fn is_null(self) -> SimpleExpr { self.binary(BinOper::Is, Keyword::Null) } + /// Express a bitwise left shift. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where(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"# + /// ); + /// ``` fn left_shift(self, right: R) -> SimpleExpr where R: Into, @@ -205,6 +761,57 @@ pub trait ExprTrait: Sized { self.binary(BinOper::LShift, right) } + /// Express a `LIKE` expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::Character).into_column_ref().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((Char::Table, Char::Character).into_column_ref().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 '|'"# + /// ); + /// ``` fn like(self, like: L) -> SimpleExpr where L: IntoLikeExpr, @@ -212,6 +819,32 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::Like, like.into_like_expr()) } + /// Express a less than (`<`) expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::SizeW).into_column_ref().lt(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"# + /// ); + /// ``` fn lt(self, right: R) -> SimpleExpr where R: Into, @@ -219,6 +852,32 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::SmallerThan, right) } + /// Express a less than or equal (`<=`) expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::SizeW).into_column_ref().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"# + /// ); + /// ``` fn lte(self, right: R) -> SimpleExpr where R: Into, @@ -226,6 +885,32 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::SmallerThanOrEqual, right) } + /// Express an arithmetic modulo operation. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where(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"# + /// ); + /// ``` fn modulo(self, right: R) -> SimpleExpr where R: Into, @@ -233,6 +918,32 @@ pub trait ExprTrait: Sized { self.binary(BinOper::Mod, right) } + /// Express an arithmetic multiplication operation. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where(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"# + /// ); + /// ``` fn mul(self, right: R) -> SimpleExpr where R: Into, @@ -240,6 +951,34 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::Mul, right) } + /// Express a not equal (`<>`) expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// // Sometimes, you'll have to qualify the call because of conflicting std traits. + /// .and_where(ExprTrait::ne("Morning", "Good")) + /// .and_where(Char::Id.into_column_ref().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"# + /// ); + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'Morning' <> 'Good' AND "id" <> 1"# + /// ); + /// assert_eq!( + /// query.to_string(SqliteQueryBuilder), + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'Morning' <> 'Good' AND "id" <> 1"# + /// ); + /// ``` fn ne(self, right: R) -> SimpleExpr where R: Into, @@ -247,10 +986,62 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::NotEqual, right) } + /// Negates an expression with `NOT`. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where(ExprTrait::not(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 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"# + /// ); + /// ``` fn not(self) -> SimpleExpr { self.unary(UnOper::Not) } + /// Express a `NOT BETWEEN` expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::SizeW).into_column_ref().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"# + /// ); + /// ``` fn not_between(self, a: A, b: B) -> SimpleExpr where A: Into, @@ -262,6 +1053,33 @@ pub trait ExprTrait: Sized { ) } + /// Express a not equal expression between two table columns, + /// you will mainly use this to relate identical value between two table columns. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::FontId).into_column_ref().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`"# + /// ); + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" <> "font"."id""# + /// ); + /// assert_eq!( + /// query.to_string(SqliteQueryBuilder), + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" <> "font"."id""# + /// ); + /// ``` fn not_equals(self, col: C) -> SimpleExpr where C: IntoColumnRef, @@ -269,6 +1087,36 @@ pub trait ExprTrait: Sized { self.binary(BinOper::NotEqual, col.into_column_ref()) } + /// Express a `NOT IN` sub-query expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where(Char::SizeW.into_column_ref().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)"# + /// ); + /// ``` fn not_in_subquery(self, sel: SelectStatement) -> SimpleExpr { self.binary( BinOper::NotIn, @@ -276,6 +1124,32 @@ pub trait ExprTrait: Sized { ) } + /// Express a `NOT LIKE` expression. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where((Char::Table, Char::Character).into_column_ref().not_like("Ours'%")) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(MysqlQueryBuilder), + /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`character` NOT LIKE 'Ours\'%'"# + /// ); + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."character" NOT LIKE E'Ours\'%'"# + /// ); + /// assert_eq!( + /// query.to_string(SqliteQueryBuilder), + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."character" NOT LIKE 'Ours''%'"# + /// ); + /// ``` fn not_like(self, like: L) -> SimpleExpr where L: IntoLikeExpr, @@ -283,6 +1157,32 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::NotLike, like.into_like_expr()) } + /// Express a logical `OR` operation. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{*, tests_cfg::*}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where(false.or(true)) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(MysqlQueryBuilder), + /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE FALSE OR TRUE"# + /// ); + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE FALSE OR TRUE"# + /// ); + /// assert_eq!( + /// query.to_string(SqliteQueryBuilder), + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE FALSE OR TRUE"# + /// ); + /// ``` fn or(self, right: R) -> SimpleExpr where R: Into, @@ -290,6 +1190,32 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::Or, right) } + /// Express a bitwise right shift. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where(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"# + /// ); + /// ``` fn right_shift(self, right: R) -> SimpleExpr where R: Into, @@ -297,6 +1223,32 @@ pub trait ExprTrait: Sized { self.binary(BinOper::RShift, right) } + /// Express an arithmetic subtraction operation. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .columns([Char::Character, Char::SizeW, Char::SizeH]) + /// .from(Char::Table) + /// .and_where(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"# + /// ); + /// ``` fn sub(self, right: R) -> SimpleExpr where R: Into, @@ -304,6 +1256,32 @@ pub trait ExprTrait: Sized { ExprTrait::binary(self, BinOper::Sub, right) } + /// Apply any unary operator to the expression. + /// + /// # 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().unary(UnOper::Not)) + /// .to_owned(); + /// + /// 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"# + /// ); + /// ``` fn unary(self, o: UnOper) -> SimpleExpr; } @@ -757,6 +1735,8 @@ impl Expr { /// Express an equal (`=`) expression. /// + /// This is equivalent to a newer [ExprTrait::eq] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -791,6 +1771,8 @@ impl Expr { /// Express a not equal (`<>`) expression. /// + /// This is equivalent to a newer [ExprTrait::ne] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -826,6 +1808,8 @@ impl Expr { /// 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. + /// /// # Examples /// /// ``` @@ -860,6 +1844,8 @@ impl Expr { /// 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. + /// /// # Examples /// /// ``` @@ -893,6 +1879,8 @@ impl Expr { /// Express a greater than (`>`) expression. /// + /// This is equivalent to a newer [ExprTrait::gt] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -926,6 +1914,8 @@ impl Expr { /// Express a greater than or equal (`>=`) expression. /// + /// This is equivalent to a newer [ExprTrait::gte] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -959,6 +1949,8 @@ impl Expr { /// Express a less than (`<`) expression. /// + /// This is equivalent to a newer [ExprTrait::lt] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -992,6 +1984,8 @@ impl Expr { /// Express a less than or equal (`<=`) expression. /// + /// This is equivalent to a newer [ExprTrait::lte] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1025,6 +2019,8 @@ impl Expr { /// Express an arithmetic addition operation. /// + /// This is equivalent to a newer [ExprTrait::add] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1059,6 +2055,8 @@ impl Expr { /// Express an arithmetic subtraction operation. /// + /// This is equivalent to a newer [ExprTrait::sub] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1093,6 +2091,8 @@ impl Expr { /// Express an arithmetic multiplication operation. /// + /// This is equivalent to a newer [ExprTrait::mul] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1127,6 +2127,8 @@ impl Expr { /// Express an arithmetic division operation. /// + /// This is equivalent to a newer [ExprTrait::div] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1161,6 +2163,8 @@ impl Expr { /// Express an arithmetic modulo operation. /// + /// This is equivalent to a newer [ExprTrait::modulo] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1195,6 +2199,8 @@ impl Expr { /// Express a bitwise left shift. /// + /// This is equivalent to a newer [ExprTrait::left_shift] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1229,6 +2235,8 @@ impl Expr { /// Express a bitwise right shift. /// + /// This is equivalent to a newer [ExprTrait::right_shift] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1263,6 +2271,8 @@ impl Expr { /// Express a `BETWEEN` expression. /// + /// This is equivalent to a newer [ExprTrait::between] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1296,6 +2306,8 @@ impl Expr { /// Express a `NOT BETWEEN` expression. /// + /// This is equivalent to a newer [ExprTrait::not_between] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1329,6 +2341,8 @@ impl Expr { /// Express a `LIKE` expression. /// + /// This is equivalent to a newer [ExprTrait::like] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1382,13 +2396,17 @@ impl Expr { ExprTrait::like(self, like) } - /// Express a `NOT LIKE` expression + /// 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 /// /// ``` @@ -1420,6 +2438,8 @@ impl Expr { /// Express a `IS` expression. /// + /// This is equivalent to a newer [ExprTrait::is] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1453,6 +2473,8 @@ impl Expr { /// Express a `IS NOT NULL` expression. /// + /// This is equivalent to a newer [ExprTrait::is_not_null] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1484,6 +2506,8 @@ impl Expr { /// Express a `IS NOT` expression. /// + /// This is equivalent to a newer [ExprTrait::is_not] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1517,6 +2541,8 @@ impl Expr { /// 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::*}; @@ -1552,6 +2578,8 @@ impl Expr { /// Negates an expression with `NOT`. /// + /// This is equivalent to a newer [ExprTrait::not] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1760,6 +2788,8 @@ impl Expr { /// Express a `IN` expression. /// + /// This is equivalent to a newer [ExprTrait::is_in] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1818,6 +2848,8 @@ impl Expr { /// Express a `IN` sub expression. /// + /// This is equivalent to a newer [ExprTrait::in_tuples] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1861,6 +2893,8 @@ impl Expr { /// Express a `NOT IN` expression. /// + /// This is equivalent to a newer [ExprTrait::is_not_in] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1919,6 +2953,8 @@ impl Expr { /// Express a `IN` sub-query expression. /// + /// This is equivalent to a newer [ExprTrait::in_subquery] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -1954,6 +2990,8 @@ impl Expr { /// 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 /// /// ``` @@ -2091,6 +3129,8 @@ impl Expr { /// Express a `AS enum` expression. /// + /// This is equivalent to a newer [ExprTrait::as_enum] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -2174,6 +3214,8 @@ impl Expr { /// Express a `CAST AS` expression. /// + /// This is equivalent to a newer [ExprTrait::cast_as] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -2354,6 +3396,8 @@ impl From for SimpleExpr { impl SimpleExpr { /// Negates an expression with `NOT`. /// + /// This is equivalent to a newer [ExprTrait::not] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -2418,6 +3462,8 @@ impl SimpleExpr { /// Express a logical `OR` operation. /// + /// This is equivalent to a newer [ExprTrait::or] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -2449,6 +3495,8 @@ impl SimpleExpr { /// Express an equal (`=`) expression. /// + /// This is equivalent to a newer [ExprTrait::eq] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -2482,6 +3530,8 @@ impl SimpleExpr { /// Express a not equal (`<>`) expression. /// + /// This is equivalent to a newer [ExprTrait::ne] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -2515,6 +3565,8 @@ impl SimpleExpr { /// Perform addition with another [`SimpleExpr`]. /// + /// This is equivalent to a newer [ExprTrait::add] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -2552,6 +3604,8 @@ impl SimpleExpr { /// Perform multiplication with another [`SimpleExpr`]. /// + /// This is equivalent to a newer [ExprTrait::mul] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -2589,6 +3643,8 @@ impl SimpleExpr { /// Perform division with another [`SimpleExpr`]. /// + /// This is equivalent to a newer [ExprTrait::div] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -2626,6 +3682,8 @@ impl SimpleExpr { /// Perform subtraction with another [`SimpleExpr`]. /// + /// This is equivalent to a newer [ExprTrait::sub] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -2663,6 +3721,8 @@ impl SimpleExpr { /// Express a `CAST AS` expression. /// + /// This is equivalent to a newer [ExprTrait::cast_as] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -2694,6 +3754,8 @@ impl SimpleExpr { /// 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::*}; @@ -2728,6 +3790,8 @@ impl SimpleExpr { /// Express a `LIKE` expression. /// + /// This is equivalent to a newer [ExprTrait::like] and may require more some wrapping beforehand. + /// /// # Examples /// /// ``` @@ -2756,7 +3820,9 @@ impl SimpleExpr { ExprTrait::like(self, like) } - /// Express a `NOT LIKE` expression + /// 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) }