diff --git a/examples/rusqlite/src/main.rs b/examples/rusqlite/src/main.rs index 92f9ee5de..45e791d70 100644 --- a/examples/rusqlite/src/main.rs +++ b/examples/rusqlite/src/main.rs @@ -1,6 +1,6 @@ use chrono::{NaiveDate, NaiveDateTime}; use rusqlite::{Connection, Result, Row}; -use sea_query::{ColumnDef, Expr, Func, Iden, Order, Query, SqliteQueryBuilder, Table}; +use sea_query::{ColumnDef, Expr, ExprTrait, Func, Iden, Order, Query, SqliteQueryBuilder, Table}; use sea_query_rusqlite::RusqliteBinder; use serde_json::{Value as Json, json}; diff --git a/examples/sqlx_any/src/main.rs b/examples/sqlx_any/src/main.rs index f88df0bc9..4e574fd35 100644 --- a/examples/sqlx_any/src/main.rs +++ b/examples/sqlx_any/src/main.rs @@ -1,7 +1,7 @@ use chrono::NaiveDate; use sea_query::{ - ColumnDef, Expr, Func, Iden, MysqlQueryBuilder, OnConflict, Order, PostgresQueryBuilder, Query, - QueryBuilder, SchemaBuilder, SqliteQueryBuilder, Table, + ColumnDef, Expr, ExprTrait, Func, Iden, MysqlQueryBuilder, OnConflict, Order, + PostgresQueryBuilder, Query, QueryBuilder, SchemaBuilder, SqliteQueryBuilder, Table, }; use sqlx::{AnyPool, Row}; use std::env; diff --git a/examples/sqlx_mysql/src/main.rs b/examples/sqlx_mysql/src/main.rs index 655b86f36..39c12220b 100644 --- a/examples/sqlx_mysql/src/main.rs +++ b/examples/sqlx_mysql/src/main.rs @@ -1,7 +1,9 @@ use bigdecimal::{BigDecimal, FromPrimitive}; use chrono::NaiveDate; use rust_decimal::Decimal; -use sea_query::{ColumnDef, Expr, Func, Iden, MysqlQueryBuilder, OnConflict, Order, Query, Table}; +use sea_query::{ + ColumnDef, Expr, ExprTrait, Func, Iden, MysqlQueryBuilder, OnConflict, Order, Query, Table, +}; use sea_query_binder::SqlxBinder; use sqlx::{MySqlPool, Row, types::chrono::NaiveDateTime}; use time::{ diff --git a/examples/sqlx_postgres/src/main.rs b/examples/sqlx_postgres/src/main.rs index 6f600eec7..3d30e631a 100644 --- a/examples/sqlx_postgres/src/main.rs +++ b/examples/sqlx_postgres/src/main.rs @@ -2,7 +2,7 @@ use bigdecimal::{BigDecimal, FromPrimitive}; use chrono::{NaiveDate, NaiveDateTime}; use rust_decimal::Decimal; use sea_query::{ - ColumnDef, Expr, Func, Iden, OnConflict, Order, PostgresQueryBuilder, Query, Table, + ColumnDef, Expr, ExprTrait, Func, Iden, OnConflict, Order, PostgresQueryBuilder, Query, Table, }; use sea_query_binder::SqlxBinder; use sqlx::{PgPool, Row}; diff --git a/examples/sqlx_sqlite/src/main.rs b/examples/sqlx_sqlite/src/main.rs index 607ea0638..439e9ae65 100644 --- a/examples/sqlx_sqlite/src/main.rs +++ b/examples/sqlx_sqlite/src/main.rs @@ -1,5 +1,7 @@ use chrono::{NaiveDate, NaiveDateTime}; -use sea_query::{ColumnDef, Expr, Func, Iden, OnConflict, Order, Query, SqliteQueryBuilder, Table}; +use sea_query::{ + ColumnDef, Expr, ExprTrait, Func, Iden, OnConflict, Order, Query, SqliteQueryBuilder, Table, +}; use sea_query_binder::SqlxBinder; use serde_json::{Value as Json, json}; use sqlx::{Row, SqlitePool}; diff --git a/src/expr.rs b/src/expr.rs index c10b97aee..206109086 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1879,81 +1879,65 @@ impl SimpleExpr { Self::CustomWithExpr(s.into(), v.into_iter().collect()) } - /// 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 `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::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 MAX(`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 MAX("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 MAX("character"."size_w") FROM "character""# /// ); /// ``` - pub fn equals(self, col: C) -> Self - where - C: IntoColumnRef, - { - ExprTrait::equals(self, col) + pub fn max(self) -> Self { + Func::max(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 `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::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 MIN(`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 MIN("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 MIN("character"."size_w") FROM "character""# /// ); /// ``` - pub fn not_equals(self, col: C) -> Self - where - C: IntoColumnRef, - { - ExprTrait::not_equals(self, col) + pub fn min(self) -> Self { + Func::min(self).into() } - /// Express a greater than (`>`) expression. - /// - /// This is equivalent to a newer [ExprTrait::gt] and may require more some wrapping beforehand. + /// Express a `SUM` function. /// /// # Examples /// @@ -1961,34 +1945,28 @@ impl SimpleExpr { /// 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::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 SUM(`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 SUM("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 SUM("character"."size_w") FROM "character""# /// ); /// ``` - pub fn gt(self, v: V) -> Self - where - V: Into, - { - ExprTrait::gt(self, v) + pub fn sum(self) -> Self { + Func::sum(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 `COUNT` function. /// /// # Examples /// @@ -1996,34 +1974,28 @@ impl SimpleExpr { /// 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::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 COUNT(`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("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("character"."size_w") FROM "character""# /// ); /// ``` - pub fn gte(self, v: V) -> Self - where - V: Into, - { - ExprTrait::gte(self, v) + pub fn count(self) -> Self { + Func::count(self).into() } - /// Express a less than (`<`) expression. - /// - /// This is equivalent to a newer [ExprTrait::lt] and may require more some wrapping beforehand. + /// Express a `COUNT` function with the DISTINCT modifier. /// /// # Examples /// @@ -2031,34 +2003,28 @@ impl SimpleExpr { /// 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)).lt(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 lt(self, v: V) -> Self - where - V: Into, - { - ExprTrait::lt(self, v) + pub fn count_distinct(self) -> Self { + Func::count_distinct(self).into() } - /// Express a less than or equal (`<=`) expression. - /// - /// This is equivalent to a newer [ExprTrait::lte] and may require more some wrapping beforehand. + /// Express a `IF NULL` function. /// /// # Examples /// @@ -2066,70 +2032,63 @@ impl SimpleExpr { /// 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)).lte(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 lte(self, v: V) -> Self + pub fn if_null(self, v: V) -> Self where V: Into, { - ExprTrait::lte(self, v) + Func::if_null(self, v).into() } - /// Express an arithmetic modulo operation. - /// - /// This is equivalent to a newer [ExprTrait::modulo] 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::val(1).modulo(1).eq(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 1 % 1 = 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 1 % 1 = 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 1 % 1 = 2"# + /// r#"SELECT EXISTS(SELECT "id" FROM "character") AS "character_exists", EXISTS(SELECT "id" FROM "glyph") AS "glyph_exists""# /// ); /// ``` - #[allow(clippy::should_implement_trait)] - pub fn modulo(self, v: V) -> Self - where - V: Into, - { - ExprTrait::modulo(self, v) + pub fn exists(sel: SelectStatement) -> Self { + Self::SubQuery( + Some(SubQueryOper::Exists), + Box::new(sel.into_sub_query_statement()), + ) } - /// Express a bitwise left shift. - /// - /// This is equivalent to a newer [ExprTrait::left_shift] and may require more some wrapping beforehand. + /// Express a `ANY` sub-query expression. /// /// # Examples /// @@ -2137,35 +2096,30 @@ 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::val(1).left_shift(1).eq(2)) + /// .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 1 << 1 = 2"# + /// 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 1 << 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 << 1 = 2"# + /// r#"SELECT "id" FROM "character" WHERE "id" = ANY(SELECT "id" FROM "character")"# /// ); /// ``` - #[allow(clippy::should_implement_trait)] - pub fn left_shift(self, v: V) -> Self - where - V: Into, - { - ExprTrait::left_shift(self, v) + pub fn any(sel: SelectStatement) -> Self { + Self::SubQuery( + Some(SubQueryOper::Any), + Box::new(sel.into_sub_query_statement()), + ) } - /// Express a bitwise right shift. - /// - /// This is equivalent to a newer [ExprTrait::right_shift] and may require more some wrapping beforehand. + /// Express a `SOME` sub-query expression. /// /// # Examples /// @@ -2173,35 +2127,38 @@ 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::val(1).right_shift(1).eq(2)) + /// .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 1 >> 1 = 2"# + /// 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 1 >> 1 = 2"# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 1 >> 1 = 2"# + /// r#"SELECT "id" FROM "character" WHERE "id" <> SOME(SELECT "id" FROM "character")"# /// ); /// ``` - #[allow(clippy::should_implement_trait)] - pub fn right_shift(self, v: V) -> Self - where - V: Into, - { - ExprTrait::right_shift(self, v) + pub fn some(sel: SelectStatement) -> Self { + Self::SubQuery( + Some(SubQueryOper::Some), + Box::new(sel.into_sub_query_statement()), + ) } - /// Express a `BETWEEN` expression. - /// - /// This is equivalent to a newer [ExprTrait::between] and may require more some wrapping beforehand. + /// Express a `ALL` sub-query expression. + pub fn all(sel: SelectStatement) -> Self { + Self::SubQuery( + Some(SubQueryOper::All), + Box::new(sel.into_sub_query_statement()), + ) + } + + /// Adds new `CASE WHEN` to existing case statement. /// /// # Examples /// @@ -2209,1324 +2166,166 @@ impl SimpleExpr { /// 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)) + /// .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(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"# + /// r#"SELECT (CASE WHEN ("glyph"."aspect" IN (2, 4)) THEN TRUE ELSE FALSE END) AS "is_even" FROM "glyph""# /// ); /// ``` - pub fn between(self, a: V, b: V) -> Self + pub fn case(cond: C, then: T) -> CaseStatement where - V: Into, + C: IntoCondition, + T: Into, { - ExprTrait::between(self, a, b) + CaseStatement::new().case(cond, then) } - /// Express a `NOT BETWEEN` expression. - /// - /// This is equivalent to a newer [ExprTrait::not_between] and may require more some wrapping beforehand. + /// Keyword `CURRENT_DATE`. /// /// # Examples /// /// ``` - /// use sea_query::{*, tests_cfg::*}; + /// use sea_query::*; /// - /// 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(); + /// let query = Query::select().expr(Expr::current_date()).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(MysqlQueryBuilder), r#"SELECT CURRENT_DATE"#); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" NOT BETWEEN 1 AND 10"# + /// r#"SELECT CURRENT_DATE"# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" NOT BETWEEN 1 AND 10"# + /// r#"SELECT CURRENT_DATE"# /// ); /// ``` - pub fn not_between(self, a: V, b: V) -> Self - where - V: Into, - { - ExprTrait::not_between(self, a, b) + pub fn current_date() -> Self { + Self::Keyword(Keyword::CurrentDate) } - /// Express a `IS NULL` expression. - /// - /// This is equivalent to a newer [ExprTrait::is_null] and may require more some wrapping beforehand. + /// Keyword `CURRENT_TIMESTAMP`. /// /// # Examples /// /// ``` - /// use sea_query::{*, tests_cfg::*}; + /// use sea_query::*; /// - /// 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(); + /// let query = Query::select().expr(Expr::current_time()).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(MysqlQueryBuilder), r#"SELECT CURRENT_TIME"#); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" IS NULL"# + /// r#"SELECT CURRENT_TIME"# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."size_w" IS NULL"# + /// r#"SELECT CURRENT_TIME"# /// ); /// ``` - #[allow(clippy::wrong_self_convention)] - pub fn is_null(self) -> Self { - ExprTrait::is_null(self) + pub fn current_time() -> Self { + Self::Keyword(Keyword::CurrentTime) } - /// Express a `IS` expression. - /// - /// This is equivalent to a newer [ExprTrait::is] and may require more some wrapping beforehand. + /// Keyword `CURRENT_TIMESTAMP`. /// /// # 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) -> Self - 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) -> Self { - 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) -> Self - where - V: Into, - { - ExprTrait::is_not(self, v) - } - - /// 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) -> Self { - Func::max(self).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) -> Self { - Func::min(self).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) -> Self { - Func::sum(self).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) -> Self { - Func::count(self).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) -> Self { - Func::count_distinct(self).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) -> Self - where - V: Into, - { - Func::if_null(self, 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) -> Self - 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) -> Self - 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) -> Self - 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) -> Self { - 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) -> Self { - 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) -> Self { - Self::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) -> Self { - Self::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) -> Self { - Self::SubQuery( - Some(SubQueryOper::Some), - Box::new(sel.into_sub_query_statement()), - ) - } - - /// Express a `ALL` sub-query expression. - pub fn all(sel: SelectStatement) -> Self { - Self::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) -> Self - 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) - } - - /// 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() -> Self { - Self::Keyword(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() -> Self { - Self::Keyword(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() -> Self { - Self::Keyword(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) -> Self - where - T: IntoIden, - { - Self::Keyword(Keyword::Custom(i.into_iden())) - } -} - -impl From for SimpleExpr -where - T: Into, -{ - fn from(v: T) -> Self { - Self::Value(v.into()) - } -} - -impl From for SimpleExpr { - fn from(func: FunctionCall) -> Self { - Self::FunctionCall(func) - } -} - -impl From for SimpleExpr { - fn from(col: ColumnRef) -> Self { - Self::Column(col) - } -} - -impl From for SimpleExpr { - fn from(k: Keyword) -> Self { - Self::Keyword(k) - } -} - -impl From for SimpleExpr { - fn from(like: LikeExpr) -> Self { - match like.escape { - Some(escape) => Self::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]) - /// .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))) - /// .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)"# - /// ); - /// 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)"# - /// ); - /// ``` - pub fn or(self, right: SimpleExpr) -> Self { - ExprTrait::or(self, right) - } - - /// Express an equal (`=`) expression. - /// - /// This is equivalent to a newer [ExprTrait::eq] and may require more some wrapping beforehand. - /// - /// # Examples - /// - /// ``` - /// use sea_query::{tests_cfg::*, *}; + /// use sea_query::{Expr, MysqlQueryBuilder, PostgresQueryBuilder, Query, SqliteQueryBuilder}; /// - /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::value("What!").eq("Nothing")) - /// .to_owned(); + /// let query = Query::select().expr(Expr::current_timestamp()).to_owned(); /// /// assert_eq!( /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE 'What!' = 'Nothing'"# + /// r#"SELECT CURRENT_TIMESTAMP"# /// ); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'What!' = 'Nothing'"# + /// r#"SELECT CURRENT_TIMESTAMP"# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE 'What!' = 'Nothing'"# + /// r#"SELECT CURRENT_TIMESTAMP"# /// ); /// ``` - pub fn eq(self, v: V) -> SimpleExpr - where - V: Into, - { - ExprTrait::eq(self, v) + pub fn current_timestamp() -> Self { + Self::Keyword(Keyword::CurrentTimestamp) } - /// Express a not equal (`<>`) expression. - /// - /// This is equivalent to a newer [ExprTrait::ne] and may require more some wrapping beforehand. + /// Custom keyword. /// /// # Examples /// /// ``` - /// use sea_query::{tests_cfg::*, *}; + /// use sea_query::*; /// /// let query = Query::select() - /// .columns([Char::Character, Char::SizeW, Char::SizeH]) - /// .from(Char::Table) - /// .and_where(Expr::value("Morning").ne("Good")) + /// .expr(Expr::custom_keyword("test")) /// .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'"# - /// ); + /// 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 ne(self, v: V) -> SimpleExpr + pub fn custom_keyword(i: T) -> Self where - V: Into, + T: IntoIden, { - ExprTrait::ne(self, v) + Self::Keyword(Keyword::Custom(i.into_iden())) } +} - /// Perform addition with another [`SimpleExpr`]. - /// - /// 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() - /// .expr( - /// Expr::col(Char::SizeW) - /// .max() - /// .add(Expr::col(Char::SizeH).max()), - /// ) - /// .from(Char::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""# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn add(self, right: T) -> Self - where - T: Into, - { - ExprTrait::add(self, right) +impl From for SimpleExpr +where + T: Into, +{ + fn from(v: T) -> Self { + Self::Value(v.into()) } +} - /// Perform multiplication with another [`SimpleExpr`]. - /// - /// 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() - /// .expr( - /// Expr::col(Char::SizeW) - /// .max() - /// .mul(Expr::col(Char::SizeH).max()), - /// ) - /// .from(Char::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""# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn mul(self, right: T) -> Self - where - T: Into, - { - ExprTrait::mul(self, right) +impl From for SimpleExpr { + fn from(func: FunctionCall) -> Self { + Self::FunctionCall(func) } +} - /// Perform division with another [`SimpleExpr`]. - /// - /// 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() - /// .expr( - /// Expr::col(Char::SizeW) - /// .max() - /// .div(Expr::col(Char::SizeH).max()), - /// ) - /// .from(Char::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""# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn div(self, right: T) -> Self - where - T: Into, - { - ExprTrait::div(self, right) +impl From for SimpleExpr { + fn from(col: ColumnRef) -> Self { + Self::Column(col) } +} - /// Perform subtraction with another [`SimpleExpr`]. - /// - /// 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() - /// .expr( - /// Expr::col(Char::SizeW) - /// .max() - /// .sub(Expr::col(Char::SizeW).min()), - /// ) - /// .from(Char::Table) - /// .to_owned(); - /// - /// assert_eq!( - /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT MAX(`size_w`) - MIN(`size_w`) FROM `character`"# - /// ); - /// assert_eq!( - /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT MAX("size_w") - MIN("size_w") FROM "character""# - /// ); - /// assert_eq!( - /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT MAX("size_w") - MIN("size_w") FROM "character""# - /// ); - /// ``` - #[allow(clippy::should_implement_trait)] - pub fn sub(self, right: T) -> Self - where - T: Into, - { - ExprTrait::sub(self, right) +impl From for SimpleExpr { + fn from(k: Keyword) -> Self { + Self::Keyword(k) } +} - /// 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::value("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) -> Self - where - T: IntoIden, - { - ExprTrait::cast_as(self, type_name) +impl From for SimpleExpr { + fn from(like: LikeExpr) -> Self { + match like.escape { + Some(escape) => Self::Binary( + Box::new(like.pattern.into()), + BinOper::Escape, + Box::new(SimpleExpr::Constant(escape.into())), + ), + None => like.pattern.into(), + } } +} +impl SimpleExpr { /// 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 @@ -3537,81 +2336,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/query/condition.rs b/src/query/condition.rs index 31f4135c0..e47239422 100644 --- a/src/query/condition.rs +++ b/src/query/condition.rs @@ -1,4 +1,4 @@ -use crate::{expr::SimpleExpr, types::LogicalChainOper}; +use crate::{ExprTrait, expr::SimpleExpr, types::LogicalChainOper}; #[derive(Debug, Clone, PartialEq, Eq)] pub enum ConditionType { diff --git a/tests/more-parentheses.rs b/tests/more-parentheses.rs index 90dab790e..3cbe04be0 100644 --- a/tests/more-parentheses.rs +++ b/tests/more-parentheses.rs @@ -1,4 +1,4 @@ -use sea_query::{Cond, Expr, MysqlQueryBuilder, Query, tests_cfg::Glyph}; +use sea_query::{Cond, Expr, ExprTrait, MysqlQueryBuilder, Query, tests_cfg::Glyph}; #[test] fn test_more_parentheses() { diff --git a/tests/postgres/query.rs b/tests/postgres/query.rs index 94a09c1a8..a2883a445 100644 --- a/tests/postgres/query.rs +++ b/tests/postgres/query.rs @@ -2185,7 +2185,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 = SimpleExpr::from(true).and(SimpleExpr::from(true).and(true).and(true)); assert_eq!( Query::select()