SeaQL
Posted on January 3, 2023
🎉 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::Array
definition changed fromArray(SeaRc<Box<ColumnType>>)
toArray(SeaRc<ColumnType>)
- [#475]
Func::*
now returnsFunctionCall
instead ofSimpleExpr
- [#475]
Func::coalesce
now acceptsIntoIterator<Item = SimpleExpr>
instead ofIntoIterator<Item = Into<SimpleExpr>
- [#475] Removed
Expr::arg
andExpr::args
- these functions are no longer needed - [#507] Moved all Postgres specific operators to
PgBinOper
- [#476]
Expr
methods used to acceptsInto<Value>
now acceptsInto<SimpleExpr>
- [#476]
Expr::is_in
,Expr::is_not_in
now acceptsInto<SimpleExpr>
instead ofInto<Value>
and convert it toSimpleExpr::Tuple
instead ofSimpleExpr::Values
- [#475]
Expr::expr
now acceptsInto<SimpleExpr>
instead ofSimpleExpr
- [#519] Moved Postgres specific
Expr
methods to new traitPgExpr
- [#528]
Expr::equals
now acceptsC: IntoColumnRef
instead 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_trgm
extension
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
ILIKE
andNOT ILIKE
operators - [#510] Added the
mul
anddiv
methods 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_keyword
andSimpleExpr::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_like
andExpr::cast_as
- [#532] Added support for
NULLS NOT DISTINCT
clause for Postgres - [#531] Added
Expr::cust_with_expr
andExpr::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
&String
to Value
Miscellaneous Enhancements
- [#475] New struct
FunctionCall
which hold function and arguments - [#503] Support
BigDecimal
,IpNetwork
andMacAddress
forsea-query-postgres
- [#511] Made
value::with_array
module public and therefore makingNotU8
trait public - [#524] Drop the
Sized
requirement 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.
Posted on January 3, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.