From 7ed4f649f40ac7a49c03e490724aa1ce9f10e10a Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 24 Aug 2025 19:58:47 +0100 Subject: [PATCH 01/19] [SeaORM] Edit --- SeaORM/docs/10-graph-ql/02-getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SeaORM/docs/10-graph-ql/02-getting-started.md b/SeaORM/docs/10-graph-ql/02-getting-started.md index 21d92ce20b..8d29169876 100644 --- a/SeaORM/docs/10-graph-ql/02-getting-started.md +++ b/SeaORM/docs/10-graph-ql/02-getting-started.md @@ -89,7 +89,7 @@ impl ActiveModelBehavior for ActiveModel {} Generating a fresh project is the easiest way to launch a GraphQL server. However, Seaography can easily be integrated to an existing web server built with any web framework. -Seaography supports Actix, Poem and Axum out of the box. +Seaography supports Poem, Actix, and Axum out of the box. Run the following command: From c916319a2a7b8e833ef9318ee3bd8064e23bdf65 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 17 Aug 2025 15:17:45 +0100 Subject: [PATCH 02/19] Draft --- Blog/blog/2025-08-20-sea-query-1.0.md | 148 ++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 Blog/blog/2025-08-20-sea-query-1.0.md diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md new file mode 100644 index 0000000000..43a4ace7ea --- /dev/null +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -0,0 +1,148 @@ +--- +slug: 2025-08-20-sea-query-1.0 +title: The road to SeaQuery 1.0 +author: SeaQL Team +author_title: Chris Tsang +author_url: https://github.com/SeaQL +author_image_url: https://www.sea-ql.org/blog/img/SeaQL.png +image: https://www.sea-ql.org/blog/img/SeaQuery%201.0%20Banner.png +tags: [news] +--- + +SeaQuery 1.0 Banner + +SeaQuery 0.1.0 was first released on 2020-12-16 - it's been a few years! Since then, there have been 32 releases, each introducing a set of new features. As with many software projects, the organic evolution driven by a diverse community of open source contributors has led to occasional inconsistencies across the codebase. It's a good problem to have, and a testament to our vibrant community. But now, it's time to stabilize SeaQuery and address some of these issues. + +## Architectural changes + +There are a few architectural changes that can only be made by breaking the API, so let's go through them one by one: + +### Forbid unsafe code + +#![forbid(unsafe_code)] has been added to all workspace crates, ensuring that SeaQuery no longer contains any unsafe code. While only one instance of unsafe was previously used, and has now been removed, this change reinforces our commitment to maintaining code quality. + +### Unify `Expr` and `SimpleExpr` as one type + +[#890](https://github.com/SeaQL/sea-query/pull/890) Previously, a lot of operator methods (e.g. `eq`) are duplicated across `Expr` and `SimpleExpr`, but the list of methods is slightly different for each. The type conversions between the two are also sometimes non-obvious. It complicates the type system and made writing generic code difficult. + +In 1.0, `SimpleExpr` is "merged into" `Expr`. Actually `SimpleExpr` is now just a type alias `type SimpleExpr = Expr;`. So a lot of redundant `.into()` can now be removed. In addition, now all methods are defined by `ExprTrait`, and the inherent methods were removed. If you encounter the following error, please add `use sea_query::ExprTrait` in scope. +```rust +error[E0599]: no method named `like` found for enum `sea_query::Expr` in the current scope + | + | Expr::col((self.entity_name(), *self)).like(s) + | + | fn like(self, like: L) -> Expr + | ---- the method is available for `sea_query::Expr` here + | + = help: items from traits can only be used if the trait is in scope +help: trait `ExprTrait` which provides `like` is implemented but not in scope; perhaps you want to import it + | + -> + use sea_query::ExprTrait; +``` +```rust +error[E0308]: mismatched types + --> src/sqlite/discovery.rs:27:57 + | + | .and_where(Expr::col(Alias::new("type")).eq("table")) + | -- ^^^^^^^ expected `&Expr`, found `&str` + | | + | arguments to this method are incorrect + | + = note: expected reference `&sea_query::Expr` + found reference `&'static str` +``` + +### Revamp `Iden` type system. + +[#909](https://github.com/SeaQL/sea-query/pull/909) Previously, `DynIden` is lazily rendered, i.e. the identifier is only constructed while serializing the AST. Now, it's an eagerly rendered string `Cow<'static, str>`, constructed while constructing the AST. `SeaRc` is no longer an alias to `Rc` / `Arc`, as such, `Send` / `Sync` is removed from the trait `Iden`. + +```rust +pub type DynIden = SeaRc; // old +pub struct DynIden(pub(crate) Cow<'static, str>); // new + +pub struct SeaRc(pub(crate) RcOrArc); // old +pub struct SeaRc; // new +``` + +### `Alias::new` is no longer needed + +[#882](https://github.com/SeaQL/sea-query/pull/882) SeaQuery encourages you to define all column / table identifiers in one place and use them throughout the project. But there are places where an alias is needed once off. Now `&'static str` is an `Iden`, so it can be used in all places where `Alias` are needed. The `Alias` type remains for backwards compatibility, so existing code should still compile. This can reduce the verbosity of code pieces, for example: + +```rust +let query = Query::select() + .from(Character::Table) + - .expr_as(Func::count(Expr::col(Character::Id)), Alias::new("count")) + + .expr_as(Func::count(Expr::col(Character::Id)), "count") + .to_owned(); +``` + +### Unbox `Value` variants + +[#925](https://github.com/SeaQL/sea-query/pull/925) Most `Value` variants are now unboxed (except `BigDecimal` and `Array`). Previously the size is 24 bytes, now it's 32. +```rust +assert_eq!(std::mem::size_of::(), 32); +``` + +If you were constructing / pattern matching `Value` variants manually, `Box::new` can now be removed and pattern matching is simpler. + +### `non_exhaustive` AST enums + +[#891](https://github.com/SeaQL/sea-query/pull/891) `#[non_exhaustive]` are added to all AST enums. It allows us to add new features and extend the AST without breaking the API. If you encounter the following error, +please add a wildcard match `_ => {..}` https://github.com/SeaQL/sea-query/pull/891 +```rust +error[E0004]: non-exhaustive patterns: `&_` not covered + | + | match table_ref { + | ^^^^^^^^^ pattern `&_` not covered + | +note: `TableRef` defined here + | + | pub enum TableRef { + | ^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `&TableRef` + = note: `TableRef` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | + | TableRef::FunctionCall(_, tbl) => SeaRc::clone(tbl), + -> | &_ => todo!(), +``` + +## Release Plan + +This is just one of many new features we've added while preparing [SeaQuery 1.0](https://github.com/SeaQL/sea-query/blob/master/CHANGELOG.md#100---pending). This is currently an `rc` release, if you have ideas please [join the discussion](https://github.com/SeaQL/sea-query/discussions/795). + +## Sponsor + +If you feel generous, a small donation will be greatly appreciated, and goes a long way towards sustaining the organization. + +A big shout out to our [GitHub sponsors](https://github.com/sponsors/SeaQL) 😇: + + + + +#### Gold Sponsor + + + + + +[QDX](https://qdx.co/) pioneers quantum dynamics–powered drug discovery, leveraging AI and supercomputing to accelerate molecular modeling. +We're grateful to QDX for sponsoring the development of SeaORM, the SQL toolkit that powers their data engineering workflows. + +## Rustacean Sticker Pack 🦀 + +The Rustacean Sticker Pack is the perfect way to express your passion for Rust. +Our stickers are made with a premium water-resistant vinyl with a unique matte finish. +Stick them on your laptop, notebook, or any gadget to show off your love for Rust! + +Moreover, all proceeds contributes directly to the ongoing development of SeaQL projects. + +Sticker Pack Contents: +- Logo of SeaQL projects: SeaQL, SeaORM, SeaQuery, Seaography, FireDBG +- Mascot of SeaQL: Terres the Hermit Crab +- Mascot of Rust: Ferris the Crab +- The Rustacean word + +[Support SeaQL and get a Sticker Pack!](https://www.sea-ql.org/sticker-pack/) + +Rustacean Sticker Pack by SeaQL From b0edc8e602e729cecc484c7c0c70bfc05d350a64 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Mon, 18 Aug 2025 09:50:44 +0100 Subject: [PATCH 03/19] Edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 105 ++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 5 deletions(-) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index 43a4ace7ea..ffa1585b5f 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -19,11 +19,13 @@ There are a few architectural changes that can only be made by breaking the API, ### Forbid unsafe code +[#930](https://github.com/SeaQL/sea-query/pull/930) #![forbid(unsafe_code)] has been added to all workspace crates, ensuring that SeaQuery no longer contains any unsafe code. While only one instance of unsafe was previously used, and has now been removed, this change reinforces our commitment to maintaining code quality. ### Unify `Expr` and `SimpleExpr` as one type -[#890](https://github.com/SeaQL/sea-query/pull/890) Previously, a lot of operator methods (e.g. `eq`) are duplicated across `Expr` and `SimpleExpr`, but the list of methods is slightly different for each. The type conversions between the two are also sometimes non-obvious. It complicates the type system and made writing generic code difficult. +[#890](https://github.com/SeaQL/sea-query/pull/890) +Previously, a lot of operator methods (e.g. `eq`) are duplicated across `Expr` and `SimpleExpr`, but the list of methods is slightly different for each. The type conversions between the two are also sometimes non-obvious. It complicates the type system and made writing generic code difficult. In 1.0, `SimpleExpr` is "merged into" `Expr`. Actually `SimpleExpr` is now just a type alias `type SimpleExpr = Expr;`. So a lot of redundant `.into()` can now be removed. In addition, now all methods are defined by `ExprTrait`, and the inherent methods were removed. If you encounter the following error, please add `use sea_query::ExprTrait` in scope. ```rust @@ -54,7 +56,8 @@ error[E0308]: mismatched types ### Revamp `Iden` type system. -[#909](https://github.com/SeaQL/sea-query/pull/909) Previously, `DynIden` is lazily rendered, i.e. the identifier is only constructed while serializing the AST. Now, it's an eagerly rendered string `Cow<'static, str>`, constructed while constructing the AST. `SeaRc` is no longer an alias to `Rc` / `Arc`, as such, `Send` / `Sync` is removed from the trait `Iden`. +[#909](https://github.com/SeaQL/sea-query/pull/909) +Previously, `DynIden` is lazily rendered, i.e. the identifier is only constructed while serializing the AST. Now, it's an eagerly rendered string `Cow<'static, str>`, constructed while constructing the AST. ```rust pub type DynIden = SeaRc; // old @@ -64,9 +67,46 @@ pub struct SeaRc(pub(crate) RcOrArc); // old pub struct SeaRc; // new ``` +The method signature of `Iden::unquoted` is changed. If you're implementing `Iden` manually, you can modify it like below https://github.com/SeaQL/sea-query/pull/909 +```rust +error[E0050]: method `unquoted` has 2 parameters but the declaration in trait `types::Iden::unquoted` has 1 + --> src/tests_cfg.rs:31:17 + | + | fn unquoted(&self, s: &mut dyn std::fmt::Write) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 parameter, found 2 + | + ::: src/types.rs:63:17 + | + | fn unquoted(&self) -> &str; + | ----- trait requires 1 parameter +``` +```rust +impl Iden for Glyph { + - fn unquoted(&self, s: &mut dyn fmt::Write) { + + fn unquoted(&self) -> &str { + - write!( + - s, + - "{}", + match self { + Self::Table => "glyph", + Self::Id => "id", + Self::Tokens => "tokens", + } + - ) + - .unwrap(); + } +} +``` + +The implications of this new design are: + +1. Type info is erased from `Iden` early +2. `SeaRc` is no longer an alias to `Rc` / `Arc`. As such, `Send` / `Sync` is removed from the trait `Iden` + ### `Alias::new` is no longer needed -[#882](https://github.com/SeaQL/sea-query/pull/882) SeaQuery encourages you to define all column / table identifiers in one place and use them throughout the project. But there are places where an alias is needed once off. Now `&'static str` is an `Iden`, so it can be used in all places where `Alias` are needed. The `Alias` type remains for backwards compatibility, so existing code should still compile. This can reduce the verbosity of code pieces, for example: +[#882](https://github.com/SeaQL/sea-query/pull/882) +SeaQuery encourages you to define all column / table identifiers in one place and use them throughout the project. But there are places where an alias is needed once off. Now `&'static str` is an `Iden`, so it can be used in all places where `Alias` are needed. The `Alias` type remains for backwards compatibility, so existing code should still compile. This can reduce the verbosity of code, for example: ```rust let query = Query::select() @@ -78,7 +118,8 @@ let query = Query::select() ### Unbox `Value` variants -[#925](https://github.com/SeaQL/sea-query/pull/925) Most `Value` variants are now unboxed (except `BigDecimal` and `Array`). Previously the size is 24 bytes, now it's 32. +[#925](https://github.com/SeaQL/sea-query/pull/925) +Most `Value` variants are now unboxed (except `BigDecimal` and `Array`). Previously the size is 24 bytes, now it's 32. ```rust assert_eq!(std::mem::size_of::(), 32); ``` @@ -87,7 +128,8 @@ If you were constructing / pattern matching `Value` variants manually, `Box::new ### `non_exhaustive` AST enums -[#891](https://github.com/SeaQL/sea-query/pull/891) `#[non_exhaustive]` are added to all AST enums. It allows us to add new features and extend the AST without breaking the API. If you encounter the following error, +[#891](https://github.com/SeaQL/sea-query/pull/891) +`#[non_exhaustive]` are added to all AST enums. It allows us to add new features and extend the AST without breaking the API. If you encounter the following error, please add a wildcard match `_ => {..}` https://github.com/SeaQL/sea-query/pull/891 ```rust error[E0004]: non-exhaustive patterns: `&_` not covered @@ -107,6 +149,59 @@ help: ensure that all possible cases are being handled by adding a match arm wit -> | &_ => todo!(), ``` +### Reworked `TableRef` and `ColumnRef` + +[#927](https://github.com/SeaQL/sea-query/pull/927) +Previously, the `TableRef` variants are a product of all valid combinations of `Option`, `Option`, `Table` and `Option`. It is excessive and makes pattern matching difficult. + +Now they're collapsed into one. `SchemaTable` is now simply a type alias of `TableName`. It makes constructing and pattern-matching `TableRef` much easier. + +```rust +// the following variants are collapsed into one: +enum TableRef { + Table(DynIden), + SchemaTable(DynIden, DynIden), + DatabaseSchemaTable(DynIden, DynIden, DynIden), + TableAlias(DynIden, DynIden), + SchemaTableAlias(DynIden, DynIden, DynIden), + DatabaseSchemaTableAlias(DynIden, DynIden, DynIden, DynIden), + .. +} +// now it's just: +enum TableRef { + Table(TableName, Option), // optional Alias + .. +} +// because it's restructured to: +pub struct DatabaseName(pub DynIden); +pub struct SchemaName(pub Option, pub DynIden); +pub struct TableName(pub Option, pub DynIden); +// so TableName can represent [database.][schema.]table +``` +* Reworked `TableRef` and `ColumnRef` variants. `SchemaTable` is now a type alias of `TableName` https://github.com/SeaQL/sea-query/pull/927 +```rust +// the following variants are collapsed into one: +enum TableRef { + Table(DynIden), + SchemaTable(DynIden, DynIden), + DatabaseSchemaTable(DynIden, DynIden, DynIden), + TableAlias(DynIden, DynIden), + SchemaTableAlias(DynIden, DynIden, DynIden), + DatabaseSchemaTableAlias(DynIden, DynIden, DynIden, DynIden), + .. +} +// now it's just: +enum TableRef { + Table(TableName, Option), // optional Alias + .. +} +// because it's restructured to: +pub struct DatabaseName(pub DynIden); +pub struct SchemaName(pub Option, pub DynIden); +pub struct TableName(pub Option, pub DynIden); +// so TableName can represent [database.][schema.]table +``` + ## Release Plan This is just one of many new features we've added while preparing [SeaQuery 1.0](https://github.com/SeaQL/sea-query/blob/master/CHANGELOG.md#100---pending). This is currently an `rc` release, if you have ideas please [join the discussion](https://github.com/SeaQL/sea-query/discussions/795). From c50436055f9015acd9d510106f510f79cda1b1f5 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Tue, 19 Aug 2025 10:04:08 +0100 Subject: [PATCH 04/19] Edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index ffa1585b5f..f4ec7bd4dd 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -20,14 +20,20 @@ There are a few architectural changes that can only be made by breaking the API, ### Forbid unsafe code [#930](https://github.com/SeaQL/sea-query/pull/930) -#![forbid(unsafe_code)] has been added to all workspace crates, ensuring that SeaQuery no longer contains any unsafe code. While only one instance of unsafe was previously used, and has now been removed, this change reinforces our commitment to maintaining code quality. +`#![forbid(unsafe_code)]` has been added to all workspace crates, ensuring that SeaQuery no longer contains any unsafe code. While only one instance of unsafe was previously used, and has now been removed, this change reinforces our commitment to maintaining code quality. ### Unify `Expr` and `SimpleExpr` as one type -[#890](https://github.com/SeaQL/sea-query/pull/890) -Previously, a lot of operator methods (e.g. `eq`) are duplicated across `Expr` and `SimpleExpr`, but the list of methods is slightly different for each. The type conversions between the two are also sometimes non-obvious. It complicates the type system and made writing generic code difficult. +[#890](https://github.com/SeaQL/sea-query/pull/890) Previously, a lot of operator methods (e.g. `eq`) were duplicated across `Expr` and `SimpleExpr`, but the list of methods was slightly different for each. Also, it wasn't clear when to use each of the two types. The type conversions were sometimes non-obvious. It complicated the type system and made writing generic code difficult. + +In 0.32.0, almost a year ago, we added `ExprTrait` ([#771](https://github.com/SeaQL/sea-query/pull/771)) to standardize and share the list of methods, and to allow calling them on other "lower-level" types like so: `1_i32.cast_as("REAL")`. At that time, we decided to keep the original inherent methods for compatibility. That worsened the duplication even further, bloating the codebase by ~1300 lines of code. + +Later, we looked into the `Expr` vs `SimpleExpr` distinction. It turned out that `Expr` was primarily meant to be a "namespace" of static constructors for `SimpleExpr`, similar to [`Func`](https://docs.rs/sea-query/0.32.7/sea_query/func/struct.Func.html) vs [`FunctionCall`](https://docs.rs/sea-query/0.32.7/sea_query/func/struct.FunctionCall.html). But unlike `Func`, which is a unit struct, `Expr` was given its own data fields, which turned out to be a mistake and led users to pass around `Expr`s instead of `SimpleExpr`s. + +In 1.0, `SimpleExpr` is "merged into" `Expr`, meaning that `SimpleExpr` is now just a type alias: `type SimpleExpr = Expr;`. Both names can be used interchangeably. A lot of redundant `.into()` can now be removed. If you implemented some trait for both of those types, two impls for one type will no longer compile and you'll need to delete one of the impls. + +The resulting "merged" type has all methods from the two original types, except for the methods defined by `ExprTrait`. Those inherent methods have been removed and have given us back those 1300 lines of code. If you encounter the following error, please add `use sea_query::ExprTrait` in scope. -In 1.0, `SimpleExpr` is "merged into" `Expr`. Actually `SimpleExpr` is now just a type alias `type SimpleExpr = Expr;`. So a lot of redundant `.into()` can now be removed. In addition, now all methods are defined by `ExprTrait`, and the inherent methods were removed. If you encounter the following error, please add `use sea_query::ExprTrait` in scope. ```rust error[E0599]: no method named `like` found for enum `sea_query::Expr` in the current scope | From 08e942d9be7852124ba4ae12c7c811b7001bf641 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Tue, 19 Aug 2025 12:23:36 +0100 Subject: [PATCH 05/19] Edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index f4ec7bd4dd..f81d4e7faf 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -136,7 +136,7 @@ If you were constructing / pattern matching `Value` variants manually, `Box::new [#891](https://github.com/SeaQL/sea-query/pull/891) `#[non_exhaustive]` are added to all AST enums. It allows us to add new features and extend the AST without breaking the API. If you encounter the following error, -please add a wildcard match `_ => {..}` https://github.com/SeaQL/sea-query/pull/891 +please add a wildcard match `_ => {..}` ```rust error[E0004]: non-exhaustive patterns: `&_` not covered | @@ -162,29 +162,6 @@ Previously, the `TableRef` variants are a product of all valid combinations of ` Now they're collapsed into one. `SchemaTable` is now simply a type alias of `TableName`. It makes constructing and pattern-matching `TableRef` much easier. -```rust -// the following variants are collapsed into one: -enum TableRef { - Table(DynIden), - SchemaTable(DynIden, DynIden), - DatabaseSchemaTable(DynIden, DynIden, DynIden), - TableAlias(DynIden, DynIden), - SchemaTableAlias(DynIden, DynIden, DynIden), - DatabaseSchemaTableAlias(DynIden, DynIden, DynIden, DynIden), - .. -} -// now it's just: -enum TableRef { - Table(TableName, Option), // optional Alias - .. -} -// because it's restructured to: -pub struct DatabaseName(pub DynIden); -pub struct SchemaName(pub Option, pub DynIden); -pub struct TableName(pub Option, pub DynIden); -// so TableName can represent [database.][schema.]table -``` -* Reworked `TableRef` and `ColumnRef` variants. `SchemaTable` is now a type alias of `TableName` https://github.com/SeaQL/sea-query/pull/927 ```rust // the following variants are collapsed into one: enum TableRef { From 9f488a90e5b06edf685a490988b38019075ef727 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Tue, 19 Aug 2025 19:27:38 +0100 Subject: [PATCH 06/19] Acknowledge --- Blog/blog/2025-08-20-sea-query-1.0.md | 42 +++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index f81d4e7faf..848149e21c 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -207,6 +207,48 @@ A big shout out to our [GitHub sponsors](https://github.com/sponsors/SeaQL) 😇 [QDX](https://qdx.co/) pioneers quantum dynamics–powered drug discovery, leveraging AI and supercomputing to accelerate molecular modeling. We're grateful to QDX for sponsoring the development of SeaORM, the SQL toolkit that powers their data engineering workflows. +## Our Team + +SeaQuery 1.0 wouldn't have happened without two contributors who joined us recently - Dmitrii Aleksandrov and Huliiiiii. They've made huge contributions that helped define this release, and we're super grateful for the effort and care they've poured into the project. + +
+ +
+
+
+ + + +
+
Chris Tsang
+ Maintainer +
+
+
+
+
+ + + +
+
Dmitrii Aleksandrov
+ Maintainer +
+
+
+
+
+ + + +
+
Huliiiiii
+ Contributor +
+
+
+
+ ## Rustacean Sticker Pack 🦀 The Rustacean Sticker Pack is the perfect way to express your passion for Rust. From 9cebeb93cd8a20f81f33b30bf5b0367f127a4126 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Wed, 20 Aug 2025 10:33:39 +0100 Subject: [PATCH 07/19] Edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 102 ++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 5 deletions(-) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index 848149e21c..218be3e1e7 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -135,7 +135,20 @@ If you were constructing / pattern matching `Value` variants manually, `Box::new ### `non_exhaustive` AST enums [#891](https://github.com/SeaQL/sea-query/pull/891) -`#[non_exhaustive]` are added to all AST enums. It allows us to add new features and extend the AST without breaking the API. If you encounter the following error, +`#[non_exhaustive]` are added to all AST enums. It allows us to add new features and extend the AST without breaking the API. + +```rust ++ #[non_exhaustive] +enum Mode { + Creation, + Alter, + TableAlter, +} +``` + +#### Potential compile errors + +If you encounter the following error, please add a wildcard match `_ => {..}` ```rust error[E0004]: non-exhaustive patterns: `&_` not covered @@ -160,7 +173,7 @@ help: ensure that all possible cases are being handled by adding a match arm wit [#927](https://github.com/SeaQL/sea-query/pull/927) Previously, the `TableRef` variants are a product of all valid combinations of `Option`, `Option`, `Table` and `Option`. It is excessive and makes pattern matching difficult. -Now they're collapsed into one. `SchemaTable` is now simply a type alias of `TableName`. It makes constructing and pattern-matching `TableRef` much easier. +Now they're collapsed into one. `SchemaTable` is now simply a type alias of `TableName`. It makes constructing and pattern-matching `TableRef` / `ColumnRef` much easier. ```rust // the following variants are collapsed into one: @@ -178,16 +191,95 @@ enum TableRef { Table(TableName, Option), // optional Alias .. } -// because it's restructured to: + pub struct DatabaseName(pub DynIden); pub struct SchemaName(pub Option, pub DynIden); +/// A table name, potentially qualified as [database.][schema.]table pub struct TableName(pub Option, pub DynIden); -// so TableName can represent [database.][schema.]table ``` +Similarly for `ColumnRef`: + +```rust +// before +enum ColumnRef { + Column(DynIden), + TableColumn(DynIden, DynIden), + SchemaTableColumn(DynIden, DynIden, DynIden), + Asterisk, + TableAsterisk(DynIden), +} +// now +enum ColumnRef { + /// A column name, potentially qualified as [database.][schema.][table.]column + Column(ColumnName), + /// An `*` expression, potentially qualified as [database.][schema.][table.]* + Asterisk(Option), +} + +pub struct ColumnName(pub Option, pub DynIden); +``` + +#### Potential compile errors + +`TableRef` + +```rust +error[E0061]: this enum variant takes 2 arguments but 1 argument was supplied + --> src/entity/relation.rs:526:15 + | + > | from_tbl: TableRef::Table("foo".into_iden()), + | ^^^^^^^^^^^^^^^------------------- + | || + | |expected `TableName`, found `DynIden` + | argument #2 of type `Option` is missing +``` +It's recommended to use the `IntoTableRef` trait to convert types instead of constructing AST manually. +```rust +use sea_orm::sea_query::IntoTableRef; + +from_tbl: "foo".into_table_ref(), +``` + +`ColumnRef` + +```rust +error[E0277]: the trait bound `fn(std::option::Option) -> sea_query::ColumnRef {sea_query::ColumnRef::Asterisk}: IntoColumnRef` is not satisfied + --> src/executor/query.rs:1599:21 + | + > | .column(ColumnRef::Asterisk) + | ------ ^^^^^^^^^^^^^^^^^^^ the trait `sea_query::Iden` is not implemented for fn item `fn(std::option::Option) -> sea_query::ColumnRef {sea_query::ColumnRef::Asterisk}` + | | + | required by a bound introduced by this call + +error[E0308]: mismatched types + --> src/executor/query.rs:1607:54 + | + > | SimpleExpr::Column(ColumnRef::Column("id".into_iden())) + | ----------------- ^^^^^^^^^^^^^^^^ expected `ColumnName`, found `DynIden` + | | + | arguments to this enum variant are incorrect +``` +In the former case `Asterisk` has an additional inner `Option`, you can simply put `None`. +```rust +.column(ColumnRef::Asterisk(None)) +``` +In the latter case, `&'static str` can now be used in most methods that accepts `ColumnRef`. +```rust +Expr::column("id") +``` + +## New Features + +### Query Audit + +### Ergonomic raw SQL + ## Release Plan -This is just one of many new features we've added while preparing [SeaQuery 1.0](https://github.com/SeaQL/sea-query/blob/master/CHANGELOG.md#100---pending). This is currently an `rc` release, if you have ideas please [join the discussion](https://github.com/SeaQL/sea-query/discussions/795). +[SeaQuery 1.0](https://github.com/SeaQL/sea-query/blob/master/CHANGELOG.md#100---pending) is currently an `rc` release, and we plan to finalize it soon - meaning no more major breaking changes. If you feel adventurous or want to use some of the latest features, you can upgrade today. Please let us know the problems you faced, this will help us and the community. If you have ideas / feedback please [join the discussion](https://github.com/SeaQL/sea-query/discussions/795) on GitHub! + +As SeaORM is based on top of SeaQuery, the breaking changes above would impact SeaORM users as well. We tried to minimize the impact to lightweight SeaORM users and most changes can be done mechanically. After that, it will be the most exciting release - SeaORM 2.0! ## Sponsor From c20ea7e287cec791c4c6c524916cc20505c20e7c Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Thu, 21 Aug 2025 10:54:26 +0100 Subject: [PATCH 08/19] TODOs --- Blog/blog/2025-08-20-sea-query-1.0.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index 218be3e1e7..a5d1d809d0 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -275,6 +275,12 @@ Expr::column("id") ### Ergonomic raw SQL +## Performance Improvements + +### Reduced heap allocations + +### Reduced SQL serialization overhead + ## Release Plan [SeaQuery 1.0](https://github.com/SeaQL/sea-query/blob/master/CHANGELOG.md#100---pending) is currently an `rc` release, and we plan to finalize it soon - meaning no more major breaking changes. If you feel adventurous or want to use some of the latest features, you can upgrade today. Please let us know the problems you faced, this will help us and the community. If you have ideas / feedback please [join the discussion](https://github.com/SeaQL/sea-query/discussions/795) on GitHub! From a3f30923ffa56dbd010e1b84494ed61ba3eab0d2 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 24 Aug 2025 23:23:55 +0100 Subject: [PATCH 09/19] Edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 207 +++++++++++++++++++++++++- 1 file changed, 205 insertions(+), 2 deletions(-) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index a5d1d809d0..1e0f8dbb0d 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -273,13 +273,216 @@ Expr::column("id") ### Query Audit +[#908](https://github.com/SeaQL/sea-query/pull/908) + +In order to support Role Based Access Control (RBAC) in SeaORM, a given SQL query has to be analyzed to determine what permissions are needed to act on which resources. + +It supports all the query types: `SELECT`, `INSERT`, `UPDATE`, `DELETE` and CTE. This requires the `audit` feature flag. + +```rust +let query = Query::select() + .columns([Char::Character]) + .from(Char::Table) + .left_join( + Font::Table, + Expr::col((Char::Table, Char::FontId)).equals((Font::Table, Font::Id)), + ) + .inner_join( + Glyph::Table, + Expr::col((Char::Table, Char::Character)).equals((Glyph::Table, Glyph::Image)), + ) + .take(); + +assert_eq!( + query.to_string(PostgresQueryBuilder), + r#"SELECT "character" + FROM "character" + LEFT JOIN "font" ON "character"."font_id" = "font"."id" + INNER JOIN "glyph" ON "character"."character" = "glyph"."image""# +); + +assert_eq!( + query.audit()?.selected_tables(), + [ + Char::Table.into_iden(), + Font::Table.into_iden(), + Glyph::Table.into_iden(), + ] +); +``` + ### Ergonomic raw SQL +[#952](https://github.com/SeaQL/sea-query/pull/952) + +This is already covered in a previous [blog post](https://www.sea-ql.org/blog/2025-08-15-sea-query-raw-sql/). +In case you've missed it, we've created a new raw_query! macro with neat features to make writing raw SQL queries more ergononmic. + +```rust +let a = 1; +struct B { b: i32 } +let b = B { b: 2 }; +let c = "A"; +let d = vec![3, 4, 5]; + +let query = sea_query::raw_query!( + PostgresQueryBuilder, + r#"SELECT ("size_w" + {a}) * {b.b} FROM "glyph" + WHERE "image" LIKE {c} AND "id" IN ({..d})"# +); + +assert_eq!( + query.sql, + r#"SELECT ("size_w" + $1) * $2 FROM "glyph" + WHERE "image" LIKE $3 AND "id" IN ($4, $5, $6)"# +); +assert_eq!( + query.values, + Values(vec![1.into(), 2.into(), "A".into(), 3.into(), 4.into(), 5.into()]) +); +``` + +The snippet above demonstrated: + +1. named parameter: `{a}` injected +2. nested parameter access: `{b.b}` inner access +3. array expansion: `{..d}` expanded into three parameters + +## Breaking Changes + +### Replaced `SERIAL` with `GENERATED BY DEFAULT AS IDENTITY` (Postgres) + +[#918](https://github.com/SeaQL/sea-query/pull/918) + +```rust +let table = Table::create() + .table(Char::Table) + .col(ColumnDef::new(Char::Id).integer().not_null().auto_increment().primary_key()) + .to_owned(); + +assert_eq!( + table.to_string(PostgresQueryBuilder), + [ + r#"CREATE TABLE "character" ("#, + r#""id" integer GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY,"#, + r#")"#, + ].join(" ") +); + +// if you needed to support legacy system you can still do: +let table = Table::create() + .table(Char::Table) + .col(ColumnDef::new(Char::Id).custom("serial").not_null().primary_key()) + .to_owned(); + +assert_eq!( + table.to_string(PostgresQueryBuilder), + [ + r#"CREATE TABLE "character" ("#, + r#""id" serial NOT NULL PRIMARY KEY"#, + r#")"#, + ].join(" ") +); +``` + +### Changed `IntoXXX` traits into `Into` + +Changed `IntoCondition` (etc) traits to be defined as `trait IntoCondition: Into`. +A blanket impl is added. +Now `IntoCondition` and `Into` are completely interchangable, but you can still use `.into_condition()` for readability. + +```rust +// before +trait IntoCondition { + fn into_condition(self) -> Condition; +} + +// now +trait IntoCondition: Into { + fn into_condition(self) -> Condition { + self.into() + } +} + +impl IntoCondition for T where T: Into {} +``` + +If you have manually implemented `Into*` traits, it may cause conflicts. You +should rewrite your impls as as `impl From<..> for TableRef`. + +Full list of changed traits: + +* `IntoCondition` [#939](https://github.com/SeaQL/sea-query/pull/939) +* `IntoColumnRef` [#959](https://github.com/SeaQL/sea-query/pull/959) +* `IntoTableRef` [#958](https://github.com/SeaQL/sea-query/pull/958) +* `IntoTypeRef` [#969](https://github.com/SeaQL/sea-query/pull/969) +* `IntoValueTuple` [#960](https://github.com/SeaQL/sea-query/pull/960) + ## Performance Improvements -### Reduced heap allocations +We benchmarked the query-building process - and found out that the bulk of the overhead came from serializing queries into strings, not from the AST building. By optimizing the string handling part of the serialization process, we improved the query-building performance by up to 15%! + +### Replaced `write!` with `write_str` + +This simple but not-so-obvious change by far contributed the biggest gain. + +We won't go into the details here, as there are two tracking issues in rust-lang: + ++ format_args! is slow [rust/#76490](https://github.com/rust-lang/rust/issues/76490) ++ Tracking issue for improving std::fmt::Arguments and format_args!() [rust/#99012](https://github.com/rust-lang/rust/issues/99012) + +```rust +// before +write!( + sql, + "CONSTRAINT {}{}{} ", + self.quote().left(), + name, + self.quote().right() +); + +// now +sql.write_str("CONSTRAINT "); +sql.write_char(self.quote().left()); +sql.write_str(name); +sql.write_char(self.quote().right()); +sql.write_str(" "); +``` + +### Refactor Writer to avoid string allocation + +```rust +// before: an intermediate string is allocated +let value: String = self.value_to_string(value); +write!(sql, "{value}"); + +// now: write to the buffer directly +self.write_value(sql, value); + +fn write_value(&self, sql: &mut dyn Write, value: &Value); +``` + +### Refactor Tokenizer to avoid string allocation -### Reduced SQL serialization overhead +Note that the tokenizer is not part of the runtime query-building code path, but still worth mentioning. + +```rust +// before +enum Token { + Quoted(String), + Unquoted(String), + Space(String), + Punctuation(String), +} + +// now +enum Token<'a> { + Quoted(&'a str), + Unquoted(&'a str), + Space(&'a str), + Punctuation(&'a str), +} +``` ## Release Plan From ef68374d34e4203d9b71c32e2e626d721fc5b0c4 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 24 Aug 2025 23:35:46 +0100 Subject: [PATCH 10/19] Edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 35 +++++++++++++++++++++------ 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index 1e0f8dbb0d..9c31f328b7 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -32,7 +32,11 @@ Later, we looked into the `Expr` vs `SimpleExpr` distinction. It turned out that In 1.0, `SimpleExpr` is "merged into" `Expr`, meaning that `SimpleExpr` is now just a type alias: `type SimpleExpr = Expr;`. Both names can be used interchangeably. A lot of redundant `.into()` can now be removed. If you implemented some trait for both of those types, two impls for one type will no longer compile and you'll need to delete one of the impls. -The resulting "merged" type has all methods from the two original types, except for the methods defined by `ExprTrait`. Those inherent methods have been removed and have given us back those 1300 lines of code. If you encounter the following error, please add `use sea_query::ExprTrait` in scope. +The resulting "merged" type has all methods from the two original types, except for the methods defined by `ExprTrait`. Those inherent methods have been removed and have given us back those 1300 lines of code. + +#### Potential compile errors + +If you encounter the following error, please add `use sea_query::ExprTrait` in scope. ```rust error[E0599]: no method named `like` found for enum `sea_query::Expr` in the current scope @@ -73,7 +77,7 @@ pub struct SeaRc(pub(crate) RcOrArc); // old pub struct SeaRc; // new ``` -The method signature of `Iden::unquoted` is changed. If you're implementing `Iden` manually, you can modify it like below https://github.com/SeaQL/sea-query/pull/909 +The method signature of `Iden::unquoted` is changed. If you're implementing `Iden` manually, you can modify it like below: ```rust error[E0050]: method `unquoted` has 2 parameters but the declaration in trait `types::Iden::unquoted` has 1 --> src/tests_cfg.rs:31:17 @@ -132,6 +136,21 @@ assert_eq!(std::mem::size_of::(), 32); If you were constructing / pattern matching `Value` variants manually, `Box::new` can now be removed and pattern matching is simpler. +It also improved performance because memory allocation and indirection is removed in most cases. + +#### Potential compile errors + +If you encounter the following error, simply remove the `Box` + +```rust +error[E0308]: mismatched types + | + > | Value::String(Some(Box::new(string_value.to_string())))); + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `String`, found `Box` + | | + | arguments to this enum variant are incorrect +``` + ### `non_exhaustive` AST enums [#891](https://github.com/SeaQL/sea-query/pull/891) @@ -148,8 +167,8 @@ enum Mode { #### Potential compile errors -If you encounter the following error, -please add a wildcard match `_ => {..}` +If you encounter the following error, please add a wildcard match `_ => {..}` + ```rust error[E0004]: non-exhaustive patterns: `&_` not covered | @@ -173,7 +192,7 @@ help: ensure that all possible cases are being handled by adding a match arm wit [#927](https://github.com/SeaQL/sea-query/pull/927) Previously, the `TableRef` variants are a product of all valid combinations of `Option`, `Option`, `Table` and `Option`. It is excessive and makes pattern matching difficult. -Now they're collapsed into one. `SchemaTable` is now simply a type alias of `TableName`. It makes constructing and pattern-matching `TableRef` / `ColumnRef` much easier. +Now they're collapsed into one. It makes constructing and pattern-matching `TableRef` / `ColumnRef` much easier. ```rust // the following variants are collapsed into one: @@ -274,7 +293,6 @@ Expr::column("id") ### Query Audit [#908](https://github.com/SeaQL/sea-query/pull/908) - In order to support Role Based Access Control (RBAC) in SeaORM, a given SQL query has to be analyzed to determine what permissions are needed to act on which resources. It supports all the query types: `SELECT`, `INSERT`, `UPDATE`, `DELETE` and CTE. This requires the `audit` feature flag. @@ -314,9 +332,8 @@ assert_eq!( ### Ergonomic raw SQL [#952](https://github.com/SeaQL/sea-query/pull/952) - This is already covered in a previous [blog post](https://www.sea-ql.org/blog/2025-08-15-sea-query-raw-sql/). -In case you've missed it, we've created a new raw_query! macro with neat features to make writing raw SQL queries more ergononmic. +In case you've missed it, we've created a new `raw_query!` macro with neat features to make writing raw SQL queries more ergononmic. ```rust let a = 1; @@ -424,6 +441,7 @@ We benchmarked the query-building process - and found out that the bulk of the o ### Replaced `write!` with `write_str` +[#947](https://github.com/SeaQL/sea-query/pull/947) This simple but not-so-obvious change by far contributed the biggest gain. We won't go into the details here, as there are two tracking issues in rust-lang: @@ -451,6 +469,7 @@ sql.write_str(" "); ### Refactor Writer to avoid string allocation +[#945](https://github.com/SeaQL/sea-query/pull/945) ```rust // before: an intermediate string is allocated let value: String = self.value_to_string(value); From c908f73888701de23e0edaa099e2b93992c5b793 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 24 Aug 2025 23:56:05 +0100 Subject: [PATCH 11/19] 'Final' edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index 9c31f328b7..f7c446228d 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -13,6 +13,17 @@ tags: [news] SeaQuery 0.1.0 was first released on 2020-12-16 - it's been a few years! Since then, there have been 32 releases, each introducing a set of new features. As with many software projects, the organic evolution driven by a diverse community of open source contributors has led to occasional inconsistencies across the codebase. It's a good problem to have, and a testament to our vibrant community. But now, it's time to stabilize SeaQuery and address some of these issues. +A very brief recap of important SeaQuery verisons: + +| version | date | notes | +|--------|-------|-------| +| 0.1.0 | 2020-12-16 | [initial release](https://www.reddit.com/r/rust/comments/kkle6j/seaquery_is_a_database_agnostic_runtime_query/) | +| 0.16.0 | 2021-09-02 | [SeaORM 0.1](https://www.sea-ql.org/blog/2021-09-20-introducing-sea-orm/) | +| 0.30.0 | 2023-07-20 | SeaORM 0.12 | +| 0.31.0 | 2024-08-02 | [SeaORM 1.0](https://www.sea-ql.org/blog/2024-08-04-sea-orm-1.0/) | +| 0.32.0 | 2024-10-17 | SeaORM 1.1 | +| 0.32.7 | 2025-08-06 | latest version | + ## Architectural changes There are a few architectural changes that can only be made by breaking the API, so let's go through them one by one: From 6c03fc8d2d13a78ee1efc64e4ca6b8f001b20b88 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Mon, 25 Aug 2025 01:15:39 +0100 Subject: [PATCH 12/19] Edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index f7c446228d..d68831caac 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -88,6 +88,13 @@ pub struct SeaRc(pub(crate) RcOrArc); // old pub struct SeaRc; // new ``` +The implications of this new design are: + +1. Type info is erased from `Iden` early +2. `SeaRc` is no longer an alias to `Rc` / `Arc`. As such, `Send` / `Sync` is removed from the trait `Iden` + +#### Potential compile errors + The method signature of `Iden::unquoted` is changed. If you're implementing `Iden` manually, you can modify it like below: ```rust error[E0050]: method `unquoted` has 2 parameters but the declaration in trait `types::Iden::unquoted` has 1 @@ -119,11 +126,6 @@ impl Iden for Glyph { } ``` -The implications of this new design are: - -1. Type info is erased from `Iden` early -2. `SeaRc` is no longer an alias to `Rc` / `Arc`. As such, `Send` / `Sync` is removed from the trait `Iden` - ### `Alias::new` is no longer needed [#882](https://github.com/SeaQL/sea-query/pull/882) From a9fca92c6df1e76e07212b1e692cdada44e7deea Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Mon, 25 Aug 2025 12:07:48 +0100 Subject: [PATCH 13/19] Edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index d68831caac..c065834cbc 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -383,6 +383,7 @@ The snippet above demonstrated: ### Replaced `SERIAL` with `GENERATED BY DEFAULT AS IDENTITY` (Postgres) [#918](https://github.com/SeaQL/sea-query/pull/918) +`SERIAL` is deprecated in Postgres because identity column (`GENERATED AS IDENTITY`) is more modern and, for example, can avoid sequence number quirks. ```rust let table = Table::create() @@ -398,8 +399,11 @@ assert_eq!( r#")"#, ].join(" ") ); +``` + +If you need to support legacy systems you can still do: -// if you needed to support legacy system you can still do: +```rust let table = Table::create() .table(Char::Table) .col(ColumnDef::new(Char::Id).custom("serial").not_null().primary_key()) @@ -483,6 +487,8 @@ sql.write_str(" "); ### Refactor Writer to avoid string allocation [#945](https://github.com/SeaQL/sea-query/pull/945) +Less strings is better! + ```rust // before: an intermediate string is allocated let value: String = self.value_to_string(value); From a57406fcba7bba0cc4297918c49f1b72e6da5f96 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 25 Aug 2025 22:54:48 +0800 Subject: [PATCH 14/19] Sponsors --- Blog/blog/2025-08-20-sea-query-1.0.md | 207 ++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index c065834cbc..8506b377cc 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -605,3 +605,210 @@ Sticker Pack Contents: [Support SeaQL and get a Sticker Pack!](https://www.sea-ql.org/sticker-pack/) Rustacean Sticker Pack by SeaQL + +## Sponsor + +If you feel generous, a small donation will be greatly appreciated, and goes a long way towards sustaining the organization. + +A big shout out to our [GitHub sponsors](https://github.com/sponsors/SeaQL) 😇: + + +#### Gold Sponsors + + + + + +[QDX](https://qdx.co/) pioneers quantum dynamics–powered drug discovery, leveraging AI and supercomputing to accelerate molecular modeling. +We're grateful to QDX for sponsoring the development of SeaORM, the SQL toolkit that powers their data engineering workflows. + +#### GitHub Sponsors + +
+
+
+ + + +
+
Subscribe Pro
+
+
+
+
+
+
+
+
+ + + +
+
Variant9
+
+
+
+
+
+ + + +
+
vealth
+
+
+
+
+
+ + + +
+
AurLemon
+
+
+
+
+
+ + + +
+
Ryan Swart
+
+
+
+
+
+ + + +
+
OteroRafael
+
+
+
+
+
+ + + +
+
Yuta Hinokuma
+
+
+
+
+
+ + + +
+
wh7f
+
+
+
+
+
+ + + +
+
MS
+
+
+
+
+
+ + + +
+
Numeus
+
+
+
+
+
+ + + +
+
Data Intuitive
+
+
+
+
+
+ + + +
+
Caido Community
+
+
+
+
+
+ + + +
+
Marcus Buffett
+
+
+
+
+
+
+
+
+ + + +
+
MasakiMiyazaki
+
+
+
+
+
+ + + +
+
KallyDev
+
+
+
+
+
+ + + +
+
Manfred Lee
+
+
+
+
+
+ + + +
+
Afonso Barracha
+
+
+
+
+
+ + + +
+
Dean Sheather
+
+
+
+
From 0043d820bd2e0576d326fd9832f48705b133cbe1 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Mon, 25 Aug 2025 16:44:34 +0100 Subject: [PATCH 15/19] Edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 61 +++++++++------------------ 1 file changed, 21 insertions(+), 40 deletions(-) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index 8506b377cc..67a692685b 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -528,24 +528,6 @@ enum Token<'a> { As SeaORM is based on top of SeaQuery, the breaking changes above would impact SeaORM users as well. We tried to minimize the impact to lightweight SeaORM users and most changes can be done mechanically. After that, it will be the most exciting release - SeaORM 2.0! -## Sponsor - -If you feel generous, a small donation will be greatly appreciated, and goes a long way towards sustaining the organization. - -A big shout out to our [GitHub sponsors](https://github.com/sponsors/SeaQL) 😇: - - - - -#### Gold Sponsor - - - - - -[QDX](https://qdx.co/) pioneers quantum dynamics–powered drug discovery, leveraging AI and supercomputing to accelerate molecular modeling. -We're grateful to QDX for sponsoring the development of SeaORM, the SQL toolkit that powers their data engineering workflows. - ## Our Team SeaQuery 1.0 wouldn't have happened without two contributors who joined us recently - Dmitrii Aleksandrov and Huliiiiii. They've made huge contributions that helped define this release, and we're super grateful for the effort and care they've poured into the project. @@ -588,32 +570,11 @@ SeaQuery 1.0 wouldn't have happened without two contributors who joined us recen -## Rustacean Sticker Pack 🦀 - -The Rustacean Sticker Pack is the perfect way to express your passion for Rust. -Our stickers are made with a premium water-resistant vinyl with a unique matte finish. -Stick them on your laptop, notebook, or any gadget to show off your love for Rust! - -Moreover, all proceeds contributes directly to the ongoing development of SeaQL projects. - -Sticker Pack Contents: -- Logo of SeaQL projects: SeaQL, SeaORM, SeaQuery, Seaography, FireDBG -- Mascot of SeaQL: Terres the Hermit Crab -- Mascot of Rust: Ferris the Crab -- The Rustacean word - -[Support SeaQL and get a Sticker Pack!](https://www.sea-ql.org/sticker-pack/) - -Rustacean Sticker Pack by SeaQL - ## Sponsor If you feel generous, a small donation will be greatly appreciated, and goes a long way towards sustaining the organization. -A big shout out to our [GitHub sponsors](https://github.com/sponsors/SeaQL) 😇: - - -#### Gold Sponsors +#### Gold Sponsor @@ -624,6 +585,8 @@ We're grateful to QDX for sponsoring the development of SeaORM, the SQL toolkit #### GitHub Sponsors +A big shout out to our [GitHub sponsors](https://github.com/sponsors/SeaQL) 😇: +
@@ -812,3 +775,21 @@ We're grateful to QDX for sponsoring the development of SeaORM, the SQL toolkit
+ +## Rustacean Sticker Pack 🦀 + +The Rustacean Sticker Pack is the perfect way to express your passion for Rust. +Our stickers are made with a premium water-resistant vinyl with a unique matte finish. +Stick them on your laptop, notebook, or any gadget to show off your love for Rust! + +Moreover, all proceeds contributes directly to the ongoing development of SeaQL projects. + +Sticker Pack Contents: +- Logo of SeaQL projects: SeaQL, SeaORM, SeaQuery, Seaography, FireDBG +- Mascot of SeaQL: Terres the Hermit Crab +- Mascot of Rust: Ferris the Crab +- The Rustacean word + +[Support SeaQL and get a Sticker Pack!](https://www.sea-ql.org/sticker-pack/) + +
Rustacean Sticker Pack by SeaQL From 7b76ce8de5f6241f98d9c0975211184fcaf5c82e Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Mon, 25 Aug 2025 23:38:30 +0100 Subject: [PATCH 16/19] Edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 28 ++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index 67a692685b..9e10c6a8c4 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -17,12 +17,12 @@ A very brief recap of important SeaQuery verisons: | version | date | notes | |--------|-------|-------| -| 0.1.0 | 2020-12-16 | [initial release](https://www.reddit.com/r/rust/comments/kkle6j/seaquery_is_a_database_agnostic_runtime_query/) | -| 0.16.0 | 2021-09-02 | [SeaORM 0.1](https://www.sea-ql.org/blog/2021-09-20-introducing-sea-orm/) | -| 0.30.0 | 2023-07-20 | SeaORM 0.12 | -| 0.31.0 | 2024-08-02 | [SeaORM 1.0](https://www.sea-ql.org/blog/2024-08-04-sea-orm-1.0/) | -| 0.32.0 | 2024-10-17 | SeaORM 1.1 | -| 0.32.7 | 2025-08-06 | latest version | +| [0.1.0](https://github.com/SeaQL/sea-query/releases/tag/0.1.0) | 2020-12-16 | [initial release](https://www.reddit.com/r/rust/comments/kkle6j/seaquery_is_a_database_agnostic_runtime_query/) | +| [0.16.0](https://github.com/SeaQL/sea-query/releases/tag/0.16.0) | 2021-09-02 | [SeaORM 0.1](https://www.sea-ql.org/blog/2021-09-20-introducing-sea-orm/) | +| [0.30.0](https://github.com/SeaQL/sea-query/releases/tag/0.30.0) | 2023-07-20 | SeaORM 0.12 | +| [0.31.0](https://github.com/SeaQL/sea-query/releases/tag/0.31.0) | 2024-08-02 | [SeaORM 1.0](https://www.sea-ql.org/blog/2024-08-04-sea-orm-1.0/) | +| [0.32.0](https://github.com/SeaQL/sea-query/releases/tag/0.32.0) | 2024-10-17 | SeaORM 1.1 | +| [0.32.7](https://github.com/SeaQL/sea-query/releases/tag/0.32.7) | 2025-08-06 | latest version | ## Architectural changes @@ -33,7 +33,7 @@ There are a few architectural changes that can only be made by breaking the API, [#930](https://github.com/SeaQL/sea-query/pull/930) `#![forbid(unsafe_code)]` has been added to all workspace crates, ensuring that SeaQuery no longer contains any unsafe code. While only one instance of unsafe was previously used, and has now been removed, this change reinforces our commitment to maintaining code quality. -### Unify `Expr` and `SimpleExpr` as one type +### Unified `Expr` and `SimpleExpr` as one type [#890](https://github.com/SeaQL/sea-query/pull/890) Previously, a lot of operator methods (e.g. `eq`) were duplicated across `Expr` and `SimpleExpr`, but the list of methods was slightly different for each. Also, it wasn't clear when to use each of the two types. The type conversions were sometimes non-obvious. It complicated the type system and made writing generic code difficult. @@ -75,7 +75,7 @@ error[E0308]: mismatched types found reference `&'static str` ``` -### Revamp `Iden` type system. +### Revamped `Iden` type system. [#909](https://github.com/SeaQL/sea-query/pull/909) Previously, `DynIden` is lazily rendered, i.e. the identifier is only constructed while serializing the AST. Now, it's an eagerly rendered string `Cow<'static, str>`, constructed while constructing the AST. @@ -139,7 +139,7 @@ let query = Query::select() .to_owned(); ``` -### Unbox `Value` variants +### Unboxed `Value` variants [#925](https://github.com/SeaQL/sea-query/pull/925) Most `Value` variants are now unboxed (except `BigDecimal` and `Array`). Previously the size is 24 bytes, now it's 32. @@ -484,7 +484,7 @@ sql.write_char(self.quote().right()); sql.write_str(" "); ``` -### Refactor Writer to avoid string allocation +### Refactored Writer to avoid string allocation [#945](https://github.com/SeaQL/sea-query/pull/945) Less strings is better! @@ -500,7 +500,7 @@ self.write_value(sql, value); fn write_value(&self, sql: &mut dyn Write, value: &Value); ``` -### Refactor Tokenizer to avoid string allocation +### Refactored Tokenizer to avoid string allocation Note that the tokenizer is not part of the runtime query-building code path, but still worth mentioning. @@ -526,11 +526,13 @@ enum Token<'a> { [SeaQuery 1.0](https://github.com/SeaQL/sea-query/blob/master/CHANGELOG.md#100---pending) is currently an `rc` release, and we plan to finalize it soon - meaning no more major breaking changes. If you feel adventurous or want to use some of the latest features, you can upgrade today. Please let us know the problems you faced, this will help us and the community. If you have ideas / feedback please [join the discussion](https://github.com/SeaQL/sea-query/discussions/795) on GitHub! -As SeaORM is based on top of SeaQuery, the breaking changes above would impact SeaORM users as well. We tried to minimize the impact to lightweight SeaORM users and most changes can be done mechanically. After that, it will be the most exciting release - SeaORM 2.0! +As SeaORM is based on top of SeaQuery, the breaking changes above would impact SeaORM users as well. We tried to minimize the impact to SeaORM users that use SeaQuery lightly and most migrations can be done mechanically. + +After SeaQuery 1.0, it will be the most exciting release - SeaORM 2.0! ## Our Team -SeaQuery 1.0 wouldn't have happened without two contributors who joined us recently - Dmitrii Aleksandrov and Huliiiiii. They've made huge contributions that helped define this release, and we're super grateful for the effort and care they've poured into the project. +SeaQuery 1.0 wouldn't have happened without two contributors who joined us recently - [Dmitrii Aleksandrov](https://github.com/Expurple) and [Huliiiiii](https://github.com/Huliiiiii). They've made huge contributions that helped define this release, and we're super grateful for the effort and care they've poured into the project.
From ebe7b0914c63be3e6be562633eaba08c050d515e Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Tue, 26 Aug 2025 10:14:10 +0100 Subject: [PATCH 17/19] Edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 32 ++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index 9e10c6a8c4..72f170c3e4 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -37,16 +37,36 @@ There are a few architectural changes that can only be made by breaking the API, [#890](https://github.com/SeaQL/sea-query/pull/890) Previously, a lot of operator methods (e.g. `eq`) were duplicated across `Expr` and `SimpleExpr`, but the list of methods was slightly different for each. Also, it wasn't clear when to use each of the two types. The type conversions were sometimes non-obvious. It complicated the type system and made writing generic code difficult. -In 0.32.0, almost a year ago, we added `ExprTrait` ([#771](https://github.com/SeaQL/sea-query/pull/771)) to standardize and share the list of methods, and to allow calling them on other "lower-level" types like so: `1_i32.cast_as("REAL")`. At that time, we decided to keep the original inherent methods for compatibility. That worsened the duplication even further, bloating the codebase by ~1300 lines of code. +In 0.32.0, almost a year ago, we added `ExprTrait` ([#771](https://github.com/SeaQL/sea-query/pull/771)) to standardize and share the list of methods, and to allow calling them on other "lower-level" types like so: `1_i32.cast_as("REAL")`. At that time, we decided to keep the original inherent methods for compatibility, at the cost of ~1300 lines of code bloat. -Later, we looked into the `Expr` vs `SimpleExpr` distinction. It turned out that `Expr` was primarily meant to be a "namespace" of static constructors for `SimpleExpr`, similar to [`Func`](https://docs.rs/sea-query/0.32.7/sea_query/func/struct.Func.html) vs [`FunctionCall`](https://docs.rs/sea-query/0.32.7/sea_query/func/struct.FunctionCall.html). But unlike `Func`, which is a unit struct, `Expr` was given its own data fields, which turned out to be a mistake and led users to pass around `Expr`s instead of `SimpleExpr`s. +Later, we looked into the `Expr` vs `SimpleExpr` distinction. It turned out that `Expr` was originally meant to be a "namespace" of static constructors for `SimpleExpr`, similar to [`Func`](https://docs.rs/sea-query/0.32.7/sea_query/func/struct.Func.html) vs [`FunctionCall`](https://docs.rs/sea-query/0.32.7/sea_query/func/struct.FunctionCall.html). Unlike `Func`, which is a unit struct, `Expr` has data fields, which led to `Expr`s being passed around, making it hard for functions to accept / return "expression fragments". -In 1.0, `SimpleExpr` is "merged into" `Expr`, meaning that `SimpleExpr` is now just a type alias: `type SimpleExpr = Expr;`. Both names can be used interchangeably. A lot of redundant `.into()` can now be removed. If you implemented some trait for both of those types, two impls for one type will no longer compile and you'll need to delete one of the impls. +In 1.0, `SimpleExpr` is "merged into" `Expr`, meaning that `SimpleExpr` is now just a type alias of `Expr`. Both names can be used interchangeably. A lot of redundant type conversions (`.into()`) and generic code (`T: ExprTrait`) can now be removed. -The resulting "merged" type has all methods from the two original types, except for the methods defined by `ExprTrait`. Those inherent methods have been removed and have given us back those 1300 lines of code. +The resulting "merged" type has all methods from the two original types, except for the methods defined by `ExprTrait`. Those inherent methods have been removed and have saved us 1300 lines of code. + +```rust +enum Expr { // the AST node enum + Column(ColumnRef), + Tuple(Vec), + .. +} + +type SimpleExpr = Expr; // now: just an alias + +impl Expr { + pub fn equals(self, col: C) -> Self; // removed +} + +trait ExprTrait: Sized { + fn equals(self, col: C) -> Expr; // please use this +} +``` #### Potential compile errors +If you implemented some trait for both of those types, two impls for one type will no longer compile and you'll need to delete one of the impls. + If you encounter the following error, please add `use sea_query::ExprTrait` in scope. ```rust @@ -164,10 +184,10 @@ error[E0308]: mismatched types | arguments to this enum variant are incorrect ``` -### `non_exhaustive` AST enums +### `non_exhaustive` AST node enums [#891](https://github.com/SeaQL/sea-query/pull/891) -`#[non_exhaustive]` are added to all AST enums. It allows us to add new features and extend the AST without breaking the API. +`#[non_exhaustive]` are added to all AST node enums. It allows us to add new features and extend the AST without breaking the API. ```rust + #[non_exhaustive] From cb1b67736e8ea36111453d8612fdc4d75b196358 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Wed, 27 Aug 2025 10:05:58 +0100 Subject: [PATCH 18/19] Edit --- Blog/blog/2025-08-20-sea-query-1.0.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-20-sea-query-1.0.md index 72f170c3e4..fa658bc6ce 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-20-sea-query-1.0.md @@ -466,8 +466,12 @@ should rewrite your impls as as `impl From<..> for TableRef`. Full list of changed traits: -* `IntoCondition` [#939](https://github.com/SeaQL/sea-query/pull/939) +* `IntoColumnDef` [#975](https://github.com/SeaQL/sea-query/pull/975) * `IntoColumnRef` [#959](https://github.com/SeaQL/sea-query/pull/959) +* `IntoCondition` [#939](https://github.com/SeaQL/sea-query/pull/939) +* `IntoIden` [#973](https://github.com/SeaQL/sea-query/pull/973) +* `IntoIndexColumn` [#976](https://github.com/SeaQL/sea-query/pull/976) +* `IntoLikeExpr` [#974](https://github.com/SeaQL/sea-query/pull/974) * `IntoTableRef` [#958](https://github.com/SeaQL/sea-query/pull/958) * `IntoTypeRef` [#969](https://github.com/SeaQL/sea-query/pull/969) * `IntoValueTuple` [#960](https://github.com/SeaQL/sea-query/pull/960) @@ -522,7 +526,7 @@ fn write_value(&self, sql: &mut dyn Write, value: &Value); ### Refactored Tokenizer to avoid string allocation -Note that the tokenizer is not part of the runtime query-building code path, but still worth mentioning. +[#952](https://github.com/SeaQL/sea-query/pull/952) Note that the tokenizer is not part of the runtime query-building code path, but still worth mentioning. ```rust // before @@ -550,7 +554,7 @@ As SeaORM is based on top of SeaQuery, the breaking changes above would impact S After SeaQuery 1.0, it will be the most exciting release - SeaORM 2.0! -## Our Team +## Our New Team SeaQuery 1.0 wouldn't have happened without two contributors who joined us recently - [Dmitrii Aleksandrov](https://github.com/Expurple) and [Huliiiiii](https://github.com/Huliiiiii). They've made huge contributions that helped define this release, and we're super grateful for the effort and care they've poured into the project. @@ -592,7 +596,7 @@ SeaQuery 1.0 wouldn't have happened without two contributors who joined us recen -## Sponsor +## Sponsors If you feel generous, a small donation will be greatly appreciated, and goes a long way towards sustaining the organization. From 0af0ddccee148d49639ca01bdd30bc320365fe80 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Wed, 27 Aug 2025 10:09:34 +0100 Subject: [PATCH 19/19] Change date --- ...{2025-08-20-sea-query-1.0.md => 2025-08-25-sea-query-1.0.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename Blog/blog/{2025-08-20-sea-query-1.0.md => 2025-08-25-sea-query-1.0.md} (99%) diff --git a/Blog/blog/2025-08-20-sea-query-1.0.md b/Blog/blog/2025-08-25-sea-query-1.0.md similarity index 99% rename from Blog/blog/2025-08-20-sea-query-1.0.md rename to Blog/blog/2025-08-25-sea-query-1.0.md index fa658bc6ce..b1e657081a 100644 --- a/Blog/blog/2025-08-20-sea-query-1.0.md +++ b/Blog/blog/2025-08-25-sea-query-1.0.md @@ -1,5 +1,5 @@ --- -slug: 2025-08-20-sea-query-1.0 +slug: 2025-08-25-sea-query-1.0 title: The road to SeaQuery 1.0 author: SeaQL Team author_title: Chris Tsang