sea-orm-cli@2.0.3
update examples
2.0.3
(since 2.0.2)
Selecting two models panicked when a column needed a cast on select. A combined select derives each A_ / B_ prefixed alias from the selected expression, and a cast is neither a plain column nor an enum cast, so that derivation gave up. Columns now carry their own alias into the combined select and the prefix is applied to it https://github.com/SeaQL/sea-orm/pull/3194
Entity::find().select_also(other::Entity).build(DbBackend::Postgres)
// before: panicked with "cannot apply alias for expr other than Column or AsEnum"
-- after
SELECT "hello"."id" AS "A_id", CAST("hello"."two" AS integer) AS "A_two", ...
Generated code referred to bindings by plain name, so a field that happened to share a name with one of them shadowed it and the expansion failed to compile. The generated bindings are now hygienic https://github.com/SeaQL/sea-orm/pull/3185
// did not compile before: `row` and `pre` collided with the generated bindings
#[derive(FromQueryResult)]
struct QueryResultProjection {
row: String,
pre: String,
}
The generated TryFrom<&str> impl wrote its error type as Self::Error, which an Error variant on the enum shadowed. The impl now names sea_orm::DbErr outright https://github.com/SeaQL/sea-orm/pull/3185
#[derive(Debug, EnumIter, DeriveActiveEnum, Eq, PartialEq)]
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "error_variant")]
enum ErrorVariantEnum {
#[sea_orm(string_value = "error")]
Error, // no longer breaks the generated `TryFrom<&str>`
}
Eq is deliberately not inherited from the model, because a nested relation may hold non-Eq fields — but the filter also discarded an Eq asked for explicitly. An explicit derive is now kept, and the clippy::derive_partial_eq_without_eq warning that the missing Eq triggered is silenced https://github.com/SeaQL/sea-orm/pull/3193
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "user", model_ex_attrs(derive(Eq)))]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
} // ModelEx now derives Eq
A unique index with a WHERE predicate was generated as an unconditional unique column, claiming a constraint the database does not enforce. Partial indexes are now skipped, since codegen cannot express the predicate https://github.com/SeaQL/sea-orm/pull/3196
CREATE UNIQUE INDEX login_human_login_id_key
ON login (human_login_id)
WHERE human_login_id IS NOT NULL; -- no longer emits #[sea_orm(unique)]
The shorthand form has no authority component, so it yields no URL path segments and the CLI reported it as having no database name. The whole path is now read as the database name https://github.com/SeaQL/sea-orm/pull/3197
sea-orm-cli generate entity -u postgres:my_db -o src/entities
-
The alias fix changes emitted SQL for ordinary single-model queries too: a column with a
select_ascast is now followed byAS "<column>". Results are unchanged, but tests asserting on generated SQL strings will need updating.-- Entity::find(), before SELECT "hello"."id", CAST("hello"."two" AS integer), "hello"."three3" FROM "hello" -- after SELECT "hello"."id", CAST("hello"."two" AS integer) AS "two", "hello"."three3" FROM "hello"
-
No public API was added, removed, or changed in
sea-orm,sea-orm-migration,sea-orm-codegen,sea-orm-macrosorsea-orm-cli.
sea-orm-cli@2.0.2
Add changelog for 2.0.2
2.0.2
- Add
require_oneto fetch exactly one row, erroring if none: a non-optional counterpart toone()that returns the item directly and yieldsDbErr::RecordNotFoundwhen no row matches, so call sites can use?instead of unwrapping anOption. Available onSelector/SelectorRawand theSelect,SelectTwo, andSelectTwoRequiredwrappers https://github.com/SeaQL/sea-orm/pull/3164 - Add
date_time_default_nowschema helper — a column defaulting toExpr::current_timestamp()https://github.com/SeaQL/sea-orm/pull/3159 - Add
timestamp_default_nowandtimestamp_with_time_zone_default_nowschema helpers, mirroringdate_time_default_nowfor the timestamp family https://github.com/SeaQL/sea-orm/pull/3165
- CLI: deduplicate grouped vs individual imports when regenerating entities with
--preserve-user-modifications, so a user-groupeduse foo::{A, B}is recognised as equivalent to the freshly generateduse foo::A; use foo::B;and no longer emitted twice https://github.com/SeaQL/sea-orm/pull/3163
sea-orm-cli@2.0.1
Tag seaography example sea-orm version for bump.sh; tolerate taplo padding
2.0.1
- Add
set_pagetoPaginatorto set the current page https://github.com/SeaQL/sea-orm/pull/2963 - Add
as_option/into_optiontoActiveValue<Option<V>>, flattening the outer active-value state and the inner option https://github.com/SeaQL/sea-orm/pull/3155 - Add
set_unsetand friends toActiveValue: set the value only when currentlyNotSethttps://github.com/SeaQL/sea-orm/pull/3083 - Add
is_set_and/is_unchanged_andtoActiveValuehttps://github.com/SeaQL/sea-orm/pull/3125 - Add
ConnectOptions::test_before_acquire_if_idle_for(Duration)— ping a pooled connection before it is handed out only once it has been idle for at least the given duration, instead of on every acquire; setting it disablestest_before_acquire. Alsomap_sqlx_postgres_before_acquire/map_sqlx_mysql_before_acquire/map_sqlx_sqlite_before_acquireto install a per-backend SQLxbefore_acquirecallback (composes with the idle-ping shorthand: idle-ping first, then the callback), plus the corresponding getters https://github.com/SeaQL/sea-orm/pull/3143 - Add
MigratorTrait::get_pending_migrations_read_only/get_applied_migrations_read_only/get_migration_with_status_read_only(and thewith-selfequivalents) — query migration status without runningCREATE TABLE, so a database user without DDL privileges can check pending migrations; if the migration table does not exist, all migrations are reported as pending https://github.com/SeaQL/sea-orm/pull/3144
-
Require
TransactionTrait::Transactionto be a fixed point, fixing nested-transaction recursion (E0275/future_not_send) in#[sea_orm::model]generated save methods https://github.com/SeaQL/sea-orm/pull/3153Compatibility note: if you implement
TransactionTraityourself,Selfmust beSync, and yourTransactiontype must beSendand its own transaction type (Transaction::Transaction = Transaction). Implementations delegating toDatabaseConnection/DatabaseTransaction, and virtually all#[async_trait]implementations, already satisfy this. Callers are unaffected.
- Loco examples upgraded to
loco-rs1.0 (which runs on SeaORM 2.0 stable) https://github.com/SeaQL/sea-orm/pull/3152
sea-orm-cli@2.0.0
Reformat example manifests with taplo after 2.0.0 bump
2.0.0
SeaORM 2.0 is the first stable release of the 2.x line. It reworks how entities, relations, and ActiveModels are defined and used, adds an entity-first workflow, introduces role-based access control, and brings the library onto SeaQuery 1.0 and SQLx 0.9.
The full, itemized changelog for the 2.0 series (all release candidates included) is in CHANGELOG.md.
Relations are now declared directly on the Model struct with #[sea_orm::model], replacing the separate Relation enum and Related impls.
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "user")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
#[sea_orm(has_one)]
pub profile: HasOne<super::profile::Entity>,
#[sea_orm(has_many)]
pub posts: HasMany<super::post::Entity>,
}
See the new entity format walk-through.
A belongs_to relation can be typed BelongsTo<Entity> (required) or BelongsTo<Option<Entity>> (optional), encoding the foreign-key cardinality in the type and paired with the write-side ActiveBelongsTo. The macro validates the type against the nullability of the from columns at compile time. BelongsTo is the recommended type for belongs_to; the legacy HasOne<Entity> field type remains supported for backward compatibility. (https://github.com/SeaQL/sea-orm/pull/3118)
Filter with the typed COLUMN constant for compile-time type safety, alongside the existing Column enum.
user::Entity::find().filter(user::COLUMN.name.contains("Bob"))
Build and persist an entity together with its related rows in one expression, and push has-many children onto a loaded model.
let bob = user::ActiveModel::builder()
.set_name("Bob")
.set_email("bob@sea-ql.org")
.set_profile(profile::ActiveModel::builder().set_picture("Tennis"))
.insert(db)
.await?;
See nested ActiveModel.
Load an entity together with its relations, including nested relations, in a single call.
let user = user::Entity::load()
.filter_by_id(12)
.with(profile::Entity)
.with((post::Entity, comment::Entity))
.one(db)
.await?;
Create tables directly from entity definitions via the schema registry, without writing a migration first.
db.get_schema_registry("my_crate::*").sync(db).await?;
See the entity-first workflow.
A table-scoped, hierarchical RBAC engine with a query auditor and a RestrictedConnection that implements ConnectionTrait and enforces permissions on all Entity operations (including complex joins, insert-select, and CTE queries). (https://github.com/SeaQL/sea-orm/pull/2683)
insert_many no longer shares a helper struct with single insert. Panic-prone APIs were removed, empty input returns None / vec![] on exec, and the new InsertMany helper exposes last_insert_id: Option<Value>. (https://github.com/SeaQL/sea-orm/pull/2628)
The sea-orm-sync crate provides a synchronous SeaORM backed by rusqlite, mirroring the async API with async/await stripped away.
Follow the 1.0 to 2.0 migration guide and the 2.0 walk-through.
Notable breaking changes to be aware of:
- Expression methods like
.eq(),.like(),.contains()now requireuse sea_orm::ExprTrait;in scope. Also read SeaQuery's breaking changes. execute/query_one/query_all/streamnow take a SeaQuery statement; the raw-SQL variants areexecute_raw/query_one_raw/query_all_raw/stream_raw.- PostgreSQL auto-increment columns now use
GENERATED BY DEFAULT AS IDENTITYinstead ofserial; opt back in withoption-postgres-use-serialif needed. - SQLite maps both
IntegerandBigIntegertointeger. DeriveValueTypenow also derivesNotU8,IntoActiveValue, andTryFromU64; remove any manual implementations to avoid conflicts.- Removed the
runtime-actixfeature alias (useruntime-tokio); removedDeriveCustomColumnanddefault_as_str.
- SeaQuery 1.0
- SQLx 0.9
- sea-schema 0.18
2.0.0-rc.43
(since 2.0.0-rc.42)
BelongsTo relation type (#3118, #3133, #3134)
A dedicated BelongsTo<E> / BelongsTo<Option<E>> type for belongs_to relations, alongside the existing HasOne. Cardinality lives in the type parameter, so the foreign-key nullability is expressed — and checked — at compile time:
BelongsTo<E>— the FK isNOT NULL; the relation cannot be detached (there is no way to set it to "none" on the active side), so orphaning a required parent is a compile error rather than a runtime constraint violation.BelongsTo<Option<E>>— the FK is nullable; the relation can be detached, which nulls the FK on save.
The cardinality is validated against the FK columns when the entity is derived: BelongsTo<Entity> requires every from column to be NOT NULL, and BelongsTo<Option<Entity>> requires at least one nullable from column — a mismatch is a compile error. Composite foreign keys with mixed nullability detach by nulling only their nullable columns.
#[sea_orm(belongs_to, from = "user_id", to = "id")]
pub author: BelongsTo<super::user::Entity>, // required
#[sea_orm(belongs_to, from = "bakery_id", to = "id")]
pub bakery: BelongsTo<Option<super::bakery::Entity>>, // optional
The active side is ActiveBelongsTo<..>, mirroring ActiveHasOne / ActiveHasMany.
HasOne still works for belongs_to — no migration required (#3133)
Adopting BelongsTo is opt-in. A belongs_to field may keep its existing HasOne<Entity> type; it continues to compile and behave as before. Use BelongsTo when you want the compile-time cardinality guarantee; otherwise nothing changes.
CLI lists valid options on generation error (#3131)
sea-orm-cli generate entity now prints the valid choices when an invalid option value is supplied, instead of only reporting that the value was rejected.
has_related with a Condition::any() filter (#3126)
has_related wrapped the caller's condition and then added the mandatory FK/join condition to it. When the caller passed a Condition::any() (an OR group), the join condition was folded into that disjunction, so the relation constraint was no longer guaranteed. The caller's condition is now wrapped in Condition::all() first, yielding (caller condition) AND (fk join) regardless of any() / all().
Entity codegen for PostgreSQL enum array columns (#3120)
Array-of-enum columns were generated as scalar active-enum fields because the type resolver unwrapped Array(Enum) to Enum. Array columns now route through the full type resolver, so enum[] columns generate Vec<Enum> fields.
belongs_torelations may now be typedBelongsTo<Entity>/BelongsTo<Option<Entity>>. This is opt-in — existingHasOne-typedbelongs_tofields are unchanged and still supported.sea-orm-clicontinues to generate theHasOneform.- The compile-time detach guarantee applies only to
BelongsTo<Entity>(non-null); it is a property of the type, so it costs nothing at runtime. - A
BelongsTofield's type parameter must match its FK nullability (checked when the entity is derived). This only affects code that opts intoBelongsTo. - The nested-
ActiveModelrelation types remain semver-exempt (unstable): rc.43 drops theirPartialEq<Option<..>>impls, so compare an empty relation withis_unloaded_or_not_found()/is_not_found()/as_ref()rather than== None/== Some(..).
2.0.0-rc.42
(since 2.0.0-rc.41)
Typed value arrays via try_getable_array (#3108, #2967)
DeriveValueType wrappers backed by a Vec<_> now round-trip as native PostgreSQL arrays: the derive generates a try_getable_array implementation, so a newtype over Vec<i32> reads and writes as INTEGER[] without a manual TryGetable impl.
#[derive(Clone, Debug, PartialEq, DeriveValueType)]
pub struct Tags(Vec<String>);
Replace and delete a nested HasOne (#3110, #3060, #3061)
The active has-one type (ActiveHasOne) gains a Delete variant plus generated delete_<field> / set_<field>_option builders. Setting a populated has-one now replaces the existing linked record (deleting or orphaning the old one) instead of erroring, and Delete removes it on save.
let mut user = user::Entity::load().filter_by_id(1).with(profile::Entity).one(db).await?.unwrap();
user.delete_profile().save(db).await?; // remove the linked profile
TryFrom<&str> for active enums (#3111)
DeriveActiveEnum now generates a TryFrom<&str> implementation, so a string value can be parsed straight into the enum by its database string representation.
let color = Color::try_from("Black")?;
ActiveHasOne / ActiveHasMany (renamed)
The active/write-side companions to HasOne / HasMany are renamed from HasOneModel / HasManyModel to ActiveHasOne / ActiveHasMany, so the names read as active-model values rather than loaded models. The read-side HasOne / HasMany types are unchanged.
Documented SqlErr and DbErr::sql_err() (#2940)
DbErr::sql_err() and the SqlErr variants are documented, including how to reach the raw driver error for backend-specific handling.
if let Some(SqlErr::UniqueConstraintViolation(_)) = err.sql_err() { /* ... */ }
Schema sync warns on column-type divergence (#3106)
SchemaBuilder::sync() logs a warning when a live column's type diverges from the entity definition instead of silently ignoring the difference.
Codegen ColumnType coverage (#3092)
Entity generation emits compiling code for Year, Bit, VarBit, MacAddr, LTree, and Interval columns, and for Money columns carrying precision and scale — previously these produced non-compiling ColumnType expressions.
Skip generated columns in entity generation (#3094)
sea-orm-cli generate entity skips database-generated columns, which cannot be inserted or updated, instead of emitting them as ordinary fields.
SchemaBuilder::sync() returns a Send future (#3100)
Regression fix: sync() no longer returns a non-Send future, so it can be used across .await points on multi-threaded runtimes. Released together with sea-schema 0.18.1.
sea-orm-sync generation fixes (#3112)
The make-sync transform correctly handles futures_util usage in the mock driver, keeping the blocking sea-orm-sync crate in sync with the async source.
HasOneModel/HasManyModelare renamed toActiveHasOne/ActiveHasMany. Update references; the read-sideHasOne/HasManyare unaffected.DbErr,UpdateResult,DeleteResult,ActiveHasOne, andActiveHasManyare now#[non_exhaustive]; downstreammatches need a wildcard arm.- Schema sync and nested-ActiveModel relation mutation are marked unstable (semver-exempt) while their APIs settle.
- Prebuilt
sea-orm-clibinaries no longer include the Intel macOS (x86_64-apple-darwin) target.