π We are pleased to release SeaQuery 0.28.0! Here are some feature highlights π:
  
  
  New IdenStatic trait for static identifier
[#508] Representing a identifier with &'static str. The IdenStatic trait looks like this:
pub trait IdenStatic: Iden + Copy + 'static {
    fn as_str(&self) -> &'static str;
}
You can derive it easily for your existing Iden. Just changing the #[derive(Iden)] into #[derive(IdenStatic)].
#[derive(IdenStatic)]
enum User {
    Table,
    Id,
    FirstName,
    LastName,
    #[iden = "_email"]
    Email,
}
assert_eq!(User::Email.as_str(), "_email");
  
  
  New PgExpr and SqliteExpr traits for backend specific expressions
[#519] Postgres specific and SQLite specific expressions are being moved into its corresponding trait. You need to import the trait into scope before construct the expression with those backend specific methods.
// Importing `PgExpr` trait before constructing Postgres expression
use sea_query::{extension::postgres::PgExpr, tests_cfg::*, *};
let query = Query::select()
    .columns([Font::Name, Font::Variant, Font::Language])
    .from(Font::Table)
    .and_where(Expr::val("a").concatenate("b").concat("c").concat("d"))
    .to_owned();
assert_eq!(
    query.to_string(PostgresQueryBuilder),
    r#"SELECT "name", "variant", "language" FROM "font" WHERE 'a' || 'b' || 'c' || 'd'"#
);
// Importing `SqliteExpr` trait before constructing SQLite expression
 use sea_query::{extension::sqlite::SqliteExpr, tests_cfg::*, *};
 let query = Query::select()
    .column(Font::Name)
    .from(Font::Table)
    .and_where(Expr::col(Font::Name).matches("a"))
    .to_owned();
 assert_eq!(
    query.to_string(SqliteQueryBuilder),
    r#"SELECT "name" FROM "font" WHERE "name" MATCH 'a'"#
 );
Bug Fixes
- Wrap unions into parenthesis https://github.com/SeaQL/sea-query/pull/498
 - Syntax error on empty condition https://github.com/SeaQL/sea-query/pull/505
 
// given
let (statement, values) = sea_query::Query::select()
    .column(Glyph::Id)
    .from(Glyph::Table)
    .cond_where(Cond::any()
        .add(Cond::all()) // empty all() => TRUE
        .add(Cond::any()) // empty any() => FALSE
    )
    .build(sea_query::MysqlQueryBuilder);
// old behavior
assert_eq!(statement, r#"SELECT `id` FROM `glyph`"#);
// new behavior
assert_eq!(
    statement,
    r#"SELECT `id` FROM `glyph` WHERE (TRUE) OR (FALSE)"#
);
// a complex example
let (statement, values) = Query::select()
    .column(Glyph::Id)
    .from(Glyph::Table)
    .cond_where(
        Cond::all()
            .add(Cond::all().not())
            .add(Cond::any().not())
            .not(),
    )
    .build(MysqlQueryBuilder);
assert_eq!(
    statement,
    r#"SELECT `id` FROM `glyph` WHERE NOT ((NOT TRUE) AND (NOT FALSE))"#
);
Breaking Changes
- [#535] MSRV is up to 1.62
 
# Make sure you're running SeaQuery with Rust 1.62+ π¦
$ rustup update
- [#492] 
ColumnType::Arraydefinition changed fromArray(SeaRc<Box<ColumnType>>)toArray(SeaRc<ColumnType>) - [#475] 
Func::*now returnsFunctionCallinstead ofSimpleExpr - [#475] 
Func::coalescenow acceptsIntoIterator<Item = SimpleExpr>instead ofIntoIterator<Item = Into<SimpleExpr> - [#475] Removed 
Expr::argandExpr::args- these functions are no longer needed - [#507] Moved all Postgres specific operators to 
PgBinOper - [#476] 
Exprmethods used to acceptsInto<Value>now acceptsInto<SimpleExpr> - [#476] 
Expr::is_in,Expr::is_not_innow acceptsInto<SimpleExpr>instead ofInto<Value>and convert it toSimpleExpr::Tupleinstead ofSimpleExpr::Values - [#475] 
Expr::exprnow acceptsInto<SimpleExpr>instead ofSimpleExpr - [#519] Moved Postgres specific 
Exprmethods to new traitPgExpr - [#528] 
Expr::equalsnow acceptsC: IntoColumnRefinstead ofT: IntoIden, C: IntoIden 
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))
-           .equals(Font::Table, Font::Id)
+           .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`"#
);
- [#525] Removed integer and date time column types' display length / precision option
 
API Additions
- [#475] Added 
SelectStatement::from_function 
use sea_query::{tests_cfg::*, *};
let query = Query::select()
    .column(ColumnRef::Asterisk)
    .from_function(Func::random(), Alias::new("func"))
    .to_owned();
assert_eq!(
    query.to_string(MysqlQueryBuilder),
    r#"SELECT * FROM RAND() AS `func`"#
);
- [#486] Added binary operators from the Postgres 
pg_trgmextension 
use sea_query::extension::postgres::PgBinOper;
assert_eq!(
    Query::select()
        .expr(Expr::col(Font::Name).binary(PgBinOper::WordSimilarity, Expr::value("serif")))
        .from(Font::Table)
        .to_string(PostgresQueryBuilder),
    r#"SELECT "name" <% 'serif' FROM "font""#
);
- [#473] Added 
ILIKEandNOT ILIKEoperators - [#510] Added the 
mulanddivmethods forSimpleExpr - [#513] Added the 
MATCH,->and->>operators for SQLite 
use sea_query::extension::sqlite::SqliteBinOper;
assert_eq!(
    Query::select()
        .column(Char::Character)
        .from(Char::Table)
        .and_where(Expr::col(Char::Character).binary(SqliteBinOper::Match, Expr::val("test")))
        .build(SqliteQueryBuilder),
    (
        r#"SELECT "character" FROM "character" WHERE "character" MATCH ?"#.to_owned(),
        Values(vec!["test".into()])
    )
);
- [#497] Added the 
FULL OUTER JOIN - [#530] Added 
PgFunc::get_random_uuid - [#528] Added 
SimpleExpr::eq,SimpleExpr::ne,Expr::not_equals - [#529] Added 
PgFunc::starts_with - [#535] Added 
Expr::custom_keywordandSimpleExpr::not 
use sea_query::*;
let query = Query::select()
    .expr(Expr::custom_keyword(Alias::new("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"#);
- [#539] Added 
SimpleExpr::like,SimpleExpr::not_likeandExpr::cast_as - [#532] Added support for 
NULLS NOT DISTINCTclause for Postgres - [#531] Added 
Expr::cust_with_exprandExpr::cust_with_exprs 
use sea_query::{tests_cfg::*, *};
let query = Query::select()
    .expr(Expr::cust_with_expr("data @? ($1::JSONPATH)", "hello"))
    .to_owned();
assert_eq!(
    query.to_string(PostgresQueryBuilder),
    r#"SELECT data @? ('hello'::JSONPATH)"#
);
- [#538] Added support for converting 
&Stringto Value 
Miscellaneous Enhancements
- [#475] New struct 
FunctionCallwhich hold function and arguments - [#503] Support 
BigDecimal,IpNetworkandMacAddressforsea-query-postgres - [#511] Made 
value::with_arraymodule public and therefore makingNotU8trait public - [#524] Drop the 
Sizedrequirement on implementers ofSchemaBuilders 
Integration Examples
SeaQuery plays well with the other crates in the rust ecosystem.
- Postgres Example
 - Rusqlite Example
 - SQLx Any Example
 - SQLx Postgres Example
 - SQLx MySql Example
 - SQLx Sqlite Example
 
Community
SeaQL is a community driven project. We welcome you to participate, contribute and together build for Rust's future.
    
Top comments (0)