Skip to content

chore(deps): update sea-orm monorepo to v2 - #491

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/major-sea-orm-monorepo
Open

chore(deps): update sea-orm monorepo to v2#491
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/major-sea-orm-monorepo

Conversation

@renovate

@renovate renovate Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Type Update Change
sea-orm (source) workspace.dependencies major 1.1.22.0.0
sea-orm-migration (source) workspace.dependencies major 1.1.22.0.0

Release Notes

SeaQL/sea-orm (sea-orm)

v2.0.0

Compare Source

Release Candidates
  • 2.0.0-rc.43BelongsTo relation type (opt-in, compile-time FK cardinality), CLI generation-option errors, has_related Condition::any() & PG enum-array codegen fixes
  • 2.0.0-rc.42 — typed value arrays, HasOne replace/delete, ActiveHasOne/ActiveHasMany rename, codegen ColumnType fixes
  • 2.0.0-rc.41SelectFourMany, update_without_returning, cargo binstall sea-orm-cli, junction ActiveModelBehavior & schema-sync PG-schema fixes
  • 2.0.0-rc.40 - Restore pgvector binding with SQLx 0.9
  • 2.0.0-rc.39 - SeaQuery 1.0, SQLx 0.9, async transaction helpers
  • 2.0.0-rc.38find_both_related, set_ne, pool options, schema sync fixes
  • 2.0.0-rc.37 — ER Diagram Generation
  • 2.0.0-rc.36 — Per-migration transaction control
  • 2.0.0-rc.35 — SQLite transaction modes, DeriveIntoActiveModel extensions, Decimal64/Bytes, schema sync fix
  • 2.0.0-rc.34 — Arrow/Parquet support, try_from_u64 for DeriveValueType
  • 2.0.0-rc.32MigratorTrait with self, PostgreSQL application_name
  • 2.0.0-rc.31ne_all, typed TextUuid, COUNT overflow fix
  • 2.0.0-rc.30 — Maintenance release, sea-query bump
  • 2.0.0-rc.29 — Tracing spans, UUID-as-TEXT, relation filtering, LEFT JOIN fix
  • 2.0.0-rc.28sqlx-all in migration, set_if_not_equals_and, auto_increment for String/Uuid PKs
  • 2.0.0-rc.27DeriveValueType implements NotU8 for PostgreSQL arrays
  • 2.0.0-rc.26postgres-use-serial-pk feature for legacy serial PKs
  • 2.0.0-rc.25 — Value system restoration, sea-query bump
  • 2.0.0-rc.24sea-query bump to rc.27
  • 2.0.0-rc.23DeriveValueType implements IntoActiveValue, remove NotU8
  • 2.0.0-rc.22DatabaseExecutor unified type, value array refactor
  • 2.0.0-rc.21 — Rusqlite / sea-orm-sync crate, exists on PaginatorTrait
  • 2.0.0-rc.20 — Stringy newtypes, M2M self-ref, nullable columns, bug fixes
New Features
  • Split belongs_to from has_one with a new BelongsTo relation type #​3118

    A belongs_to relation can now be typed BelongsTo<Entity> (required) or
    BelongsTo<Option<Entity>> (optional), encoding the foreign-key cardinality in the type,
    paired with the write-side companion ActiveBelongsTo. BelongsTo is the recommended
    type for belongs_to; the legacy HasOne<Entity> field type remains supported for
    backward compatibility.

  • Role Based Access Control #​2683

    1. a hierarchical RBAC engine that is table scoped
      • a user has 1 (and only 1) role
      • a role has a set of permissions on a set of resources
        • permissions here are CRUD operations and resources are tables
        • but the engine is generic so can be used for other things
      • roles have hierarchy, and so can inherit permissions
      • there is a wildcard * to grant all permissions or resources
      • individual users can have rules override
    2. a set of Entities to load / store the access control rules to / from database
    3. a query auditor that dissect queries for necessary permissions (implemented in SeaQuery)
    4. integration of RBAC into SeaORM in form of RestrictedConnection.
      it implements ConnectionTrait, and will audit all queries and perform permission check,
      and reject them accordingly. all Entity operations except raw SQL are supported.
      complex joins, insert select from, and even CTE queries are supported.
// load rules from database
db_conn.load_rbac().await?;

// admin can create bakery
let db = db_conn.restricted_for(admin)?;
let seaside_bakery = bakery::ActiveModel {
    name: Set("SeaSide Bakery".to_owned()),
    ..Default::default()
};
assert!(Bakery::insert(seaside_bakery).exec(&db).await.is_ok());

// public cannot create bakery
let db = db_conn.restricted_for(public)?;
assert!(matches!(
    Bakery::insert(bakery::ActiveModel::default())
        .exec(&db)
        .await,
    Err(DbErr::AccessDenied { .. })
));
  • Overhauled Entity::insert_many. We've made a number of changes #​2628
    1. removed APIs that can panic
    2. new helper struct InsertMany, last_insert_id is now Option<Value>
    3. on empty iterator, None or vec![] is returned on exec operations
    4. TryInsert API is unchanged

Previously, insert_many shares the same helper struct with insert_one, which led to an awkard API.

let res = Bakery::insert_many(std::iter::empty())
    .on_empty_do_nothing() // <- you need to add this
    .exec(db)
    .await;

assert!(matches!(res, Ok(TryInsertResult::Empty)));

last_insert_id is now Option<Value>:

struct InsertManyResult<A: ActiveModelTrait>
{
    pub last_insert_id: Option<<PrimaryKey<A> as PrimaryKeyTrait>::ValueType>,
}

Which means the awkardness is removed:

let res = Entity::insert_many::<ActiveModel, _>([]).exec(db).await;

assert_eq!(res?.last_insert_id, None); // insert nothing return None

let res = Entity::insert_many([ActiveModel { id: Set(1) }, ActiveModel { id: Set(2) }])
    .exec(db)
    .await;

assert_eq!(res?.last_insert_id, Some(2)); // insert something return Some

Same on conflict API as before:

let res = Entity::insert_many([ActiveModel { id: Set(3) }, ActiveModel { id: Set(4) }])
    .on_conflict_do_nothing()
    .exec(db)
    .await;

assert!(matches!(conflict_insert, Ok(TryInsertResult::Conflicted)));

Exec with returning now returns a Vec<Model>, so it feels intuitive:

assert!(
    Entity::insert_many::<ActiveModel, _>([])
        .exec_with_returning(db)
        .await?
        .is_empty() // no footgun, nice
);

assert_eq!(
    Entity::insert_many([
        ActiveModel {
            id: NotSet,
            value: Set("two".into()),
        }
    ])
    .exec_with_returning(db)
    .await
    .unwrap(),
    [
        Model {
            id: 2,
            value: "two".into(),
        }
    ]
);
  • Improved utility of ActiveModel::from_json. Consider the following Entity #​2599
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "cake")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: i32,      // <- not nullable
    pub name: String,
}

Previously, the following would result in error "missing field id":

assert!(
    cake::ActiveModel::from_json(json!({
        "name": "Apple Pie",
    })).is_err();
);

Now, the ActiveModel will be partially filled:

assert_eq!(
    cake::ActiveModel::from_json(json!({
        "name": "Apple Pie",
    }))
    .unwrap(),
    cake::ActiveModel {
        id: NotSet,
        name: Set("Apple Pie".to_owned()),
    }
);
  • A full Model can now be used as PartialModel in nested query #​2642
#[derive(DerivePartialModel)]
#[sea_orm(entity = "cake::Entity")]
struct Cake {
    id: i32,
    name: String,
    #[sea_orm(nested)]
    bakery: Option<bakery::Model>,
}

let cake: Cake = cake::Entity::find()
    .left_join(bakery::Entity)
    .order_by_asc(cake::Column::Id)
    .into_partial_model()
    .one(&ctx.db)
    .await?
    .unwrap();

assert_eq!(cake.id, 13);
assert_eq!(cake.name, "Cheesecake");
assert_eq!(
    cake.bakery.unwrap(),
    bakery::Model {
        id: 42,
        name: "cool little bakery".to_string(),
    }
);
  • Wrapper type derived with DeriveValueType can now be used as primary key #​2643
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "my_value_type")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: MyInteger,
}

#[derive(Clone, Debug, PartialEq, Eq, DeriveValueType)]
pub struct MyInteger(pub i32);
// only for i8 | i16 | i32 | i64 | u8 | u16 | u32 | u64
  • You can now define unique keys that span multiple columns in Entity #​2651
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "lineitem")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: i32,
    #[sea_orm(unique_key = "item")]
    pub order_id: i32,
    #[sea_orm(unique_key = "item")]
    pub cake_id: i32,
}

let stmts = Schema::new(backend).create_index_from_entity(lineitem::Entity);

assert_eq!(
    stmts[0],
    Index::create()
        .name("idx-lineitem-item")
        .table(lineitem::Entity)
        .col(lineitem::Column::OrderId)
        .col(lineitem::Column::CakeId)
        .unique()
        .take()
);

assert_eq!(
    backend.build(stmts[0]),
    r#"CREATE UNIQUE INDEX "idx-lineitem-item" ON "lineitem" ("order_id", "cake_id")"#
);
  • Overhauled ConnectionTrait API: execute, query_one, query_all, stream now takes in SeaQuery statement instead of raw SQL statement #​2657
// old
let query: SelectStatement = Entity::find().filter(..).into_query();
let backend = self.db.get_database_backend();
let stmt = backend.build(&query);
let rows = self.db.query_all(stmt).await?;

// new
let query: SelectStatement = Entity::find().filter(..).into_query();
let rows = self.db.query_all(&query).await?;
  • Added raw_sql macro for ergonomic parameter injection
#[derive(FromQueryResult)]
struct Cake {
    name: String,
    #[sea_orm(nested)]
    bakery: Option<Bakery>,
}

#[derive(FromQueryResult)]
struct Bakery {
    #[sea_orm(alias = "bakery_name")]
    name: String,
}

let cake_ids = [2, 3, 4]; // expanded by the `..` operator

let cake: Option<Cake> = Cake::find_by_statement(raw_sql!(
    Sqlite,
    r#"SELECT "cake"."name", "bakery"."name" AS "bakery_name"
       FROM "cake"
       LEFT JOIN "bakery" ON "cake"."bakery_id" = "bakery"."id"
       WHERE "cake"."id" IN ({..cake_ids})"#
))
.one(db)
.await?;
  • Added consolidate method to SelectThree. This output has different shape depending on the topology of the join.
// Order -> Customer
//       -> Lineitem

let items: Vec<(order::Model, Option<customer::Model>, Option<lineitem::Model>)> =
    order::Entity::find()
        .find_also_related(customer::Entity)
        .find_also_related(lineitem::Entity)
        .order_by_asc(order::Column::Id)
        .order_by_asc(lineitem::Column::Id)
        .all(&ctx.db)
        .await?;

// flat result
assert_eq!(
    items,
    vec![
        (order, Some(customer), Some(line_1)),
        (order, Some(customer), Some(line_2)),
    ]
);

let items: Vec<(order::Model, Vec<customer::Model>, Vec<lineitem::Model>)> =
    order::Entity::find()
        .find_also_related(customer::Entity)
        .find_also_related(lineitem::Entity)
        .order_by_asc(order::Column::Id)
        .order_by_asc(lineitem::Column::Id)
        .consolidate() // <-
        .all(&ctx.db)
        .await?;

// consolidated by order
assert_eq!(
    items,
    vec![(
        order,
        vec![customer],
        vec![line_1, line_2]
    )]
);

// Order -> Lineitem -> Cake
let items: Vec<(order::Model, Option<lineitem::Model>, Option<cake::Model>)> =
    order::Entity::find()
        .find_also_related(lineitem::Entity)
        .and_also_related(cake::Entity)
        .order_by_asc(order::Column::Id)
        .order_by_asc(lineitem::Column::Id)
        .all(&ctx.db)
        .await?;

// flat result
assert_eq!(
    items,
    vec![
        (order, Some(line_1), Some(cake_1)),
        (order, Some(line_2), Some(cake_2)),
    ]
);

let items: Vec<(order::Model, Vec<(lineitem::Model, Vec<cake::Model>)>)> =
    order::Entity::find()
        .find_also_related(lineitem::Entity)
        .and_also_related(cake::Entity)
        .order_by_asc(order::Column::Id)
        .order_by_asc(lineitem::Column::Id)
        .consolidate() // <-
        .all(&ctx.db)
        .await?;

// consolidated by order first, then by line
assert_eq!(
    items,
    vec![(
        order,
        vec![(line_1, vec![cake_1]), (line_2, vec![cake_2])]
    )]
);
  • Added Select::has_related
// cake -> fruit: find all cakes containing mango
assert_eq!(
    cake::Entity::find()
        .has_related(fruit::Entity, fruit::Column::Name.eq("Mango"))
        .build(DbBackend::Sqlite)
        .to_string(),
    [
        r#"SELECT "cake"."id", "cake"."name" FROM "cake""#,
        r#"WHERE EXISTS(SELECT 1 FROM "fruit""#,
        r#"WHERE "fruit"."name" = 'Mango'"#,
        r#"AND "cake"."id" = "fruit"."cake_id")"#,
    ]
    .join(" ")
);
// cake -> cake_filling -> filling: find all cakes with orange fillings
assert_eq!(
    cake::Entity::find()
        .has_related(filling::Entity, filling::Column::Name.eq("Marmalade"))
        .build(DbBackend::Sqlite)
        .to_string(),
    [
        r#"SELECT "cake"."id", "cake"."name" FROM "cake""#,
        r#"WHERE EXISTS(SELECT 1 FROM "filling""#,
        r#"INNER JOIN "cake_filling" ON "cake_filling"."filling_id" = "filling"."id""#,
        r#"WHERE "filling"."name" = 'Marmalade'"#,
        r#"AND "cake"."id" = "cake_filling"."cake_id")"#,
    ]
    .join(" ")
);
  • Support self-referencing relations in loader
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]

#[sea_orm(table_name = "staff")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: i32,
    pub name: String,
    pub reports_to_id: Option<i32>,
    #[sea_orm(self_ref, relation_enum = "ReportsTo", from = "reports_to_id", to = "id")]
    pub reports_to: HasOne<Entity>,
}

// Entity Loader
let staff = staff::Entity::load()
    .with(staff::Relation::ReportsTo)
    .all(db)
    .await?;

assert_eq!(staff[0].name, "Alan");
assert_eq!(staff[0].reports_to, None);

assert_eq!(staff[1].name, "Ben");
assert_eq!(staff[1].reports_to.as_ref().unwrap().name, "Alan");

assert_eq!(staff[2].name, "Alice");
assert_eq!(staff[2].reports_to.as_ref().unwrap().name, "Alan");

// Model Loader
let staff = staff::Entity::find().all(db).await?;

let reports_to = staff
    .load_self(staff::Entity, staff::Relation::ReportsTo, db)
    .await?;

assert_eq!(staff[0].name, "Alan");
assert_eq!(reports_to[0], None);

assert_eq!(staff[1].name, "Ben");
assert_eq!(reports_to[1].unwrap().name, "Alan");

assert_eq!(staff[2].name, "Alice");
assert_eq!(reports_to[2].unwrap().name, "Alan");
// old
user::Entity::find().filter(user::Column::Name.contains("Bob"))

// new
user::Entity::find().filter(user::COLUMN.name.contains("Bob"))

// compile error: the trait `From<{integer}>` is not implemented for `String`
user::Entity::find().filter(user::COLUMN.name.like(2))
  • Unix timestamp column type that will be mapped to big integer in database
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "access_log")]
pub struct Model {
    .. // with `chrono` crate
    pub ts: ChronoUnixTimestamp,
    pub ms: ChronoUnixTimestampMillis,
    .. // with `time` crate
    pub ts: TimeUnixTimestamp,
    pub ms: TimeUnixTimestampMillis,
}
  • Nested ActiveModel (ActiveModelEx) and cascade operations #​2818

    The following operation saves a new set of user + profile + post + tag + post_tag into the database atomically:

let user = user::ActiveModel::builder()
    .set_name("Bob")
    .set_email("bob@sea-ql.org")
    .set_profile(profile::ActiveModel::builder().set_picture("image.jpg"))
    .add_post(
        post::ActiveModel::builder()
            .set_title("Nice weather")
            .add_tag(tag::ActiveModel::builder().set_tag("sunny")),
    )
    .save(db)
    .await?;
Enhancements
  • Added serde feature
  • TextUuid now derives Serialize and Deserialize when the serde feature is enabled
  • [sea-orm-cli] Added --column-extra-derives #​2212
  • [sea-orm-cli] Added --big-integer-type=i32 to use i32 for bigint (for SQLite)
  • [sea-orm-cli] Fix codegen to not generate relations to filtered entities #​2913
  • [sea-orm-cli] Added --experimental-preserve-user-modifications #​2755 #​2964
  • [sea-orm-migration] Add custom connection entrypoint to migration CLI #​3035
  • Added Model::try_set
  • Added new error variant BackendNotSupported. Previously, it panics with e.g. "Database backend doesn't support RETURNING" #​2630
let result = cake::Entity::insert_many([])
    .exec_with_returning_keys(db)
    .await;

if db.support_returning() {
    // Postgres and SQLite
    assert_eq!(result.unwrap(), []);
} else {
    // MySQL
    assert!(matches!(result, Err(DbErr::BackendNotSupported { .. })));
}
  • Added new error variant PrimaryKeyNotSet. Previously, it panics with "PrimaryKey is not set" #​2627
assert!(matches!(
    Update::one(cake::ActiveModel {
        ..Default::default()
    })
    .exec(&db)
    .await,
    Err(DbErr::PrimaryKeyNotSet { .. })
));
  • Remove panics in Schema::create_enum_from_active_enum #​2634
fn create_enum_from_active_enum<A>(&self) -> Option<TypeCreateStatement>
// method can now return None
  • Added ColumnTrait::eq_any as a shorthand for the = ANY operator. Postgres only.
assert_eq!(
    cake::Entity::find()
        .filter(cake::Column::Id.eq_any(vec![4, 5]))
        .build(DbBackend::Postgres)
        .to_string(),
    r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "cake"."id" = ANY(ARRAY [4,5])"#
);
  • Added ActiveModelTrait::try_set
pub trait ActiveModelTrait {
    /// old: set the Value of a ActiveModel field, panic if failed
    fn set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) {
        self.try_set(c, v).unwrap_or_else(|e| panic!(..))
    }

    /// new: same as above but non-panicking
    fn try_set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) -> Result<(), DbErr>;
}
  • Linked can now be used in partial select, in case Related cannot be defined
pub struct ToBakery;
impl Linked for ToBakery {
    type FromEntity = super::cake::Entity;
    type ToEntity = super::bakery::Entity;

    fn link(&self) -> Vec<RelationDef> {
        vec![Relation::Bakery.def()]
    }
}

#[derive(Debug, DerivePartialModel)]

#[sea_orm(entity = "cake::Entity", into_active_model)]
struct Cake2 {
    id: i32,
    name: String,
    #[sea_orm(nested, alias = "r0")]
    bakery: Option<Bakery>,
    #[sea_orm(skip)]
    ignore: Ignore,
}

let cake2: Cake2 = cake::Entity::find()
    .left_join_linked(ToBakery)
    .order_by_asc(cake::Column::Id)
    .into_partial_model()
    .one(&ctx.db)
    .await?
    .unwrap();
  • RelationDef now implements Clone. on_condition is changed to Arc but this is a minor breaking change.
  • Added extra on column attribute:
#[cfg(feature = "with-rust_decimal")]
#[sea_orm(extra = "CHECK (price > 0)")]
pub price: Decimal,

// results in:
ColumnDef::new("price")
    .decimal()
    .not_null()
    .extra("CHECK (price > 0)"),
  • Added ColumnTrait::avg, in addition to sum, min, max etc
let average: Decimal = order::Entity::find()
    .select_only()
    .column_as(order::Column::Total.avg(), "avg")
    .into_tuple()
    .one(&ctx.db)
    .await?
    .unwrap();
  • SchemaBuilder::sync can now be used in migrations
#[async_trait::async_trait]
impl MigrationTrait for Migration {
    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        let db = manager.get_connection();

        db.get_schema_builder()
            .register(note::Entity)
            .sync(db)
            .await
    }
}
  • Allowed None for max_lifetime and idle_timeout Parameters #​2748
  • Try to parse u32 in Postgres as i32 #​2753
  • DeriveActiveEnum now also impl IntoActiveValue #​1972
  • DeriveValueType now also supports any structs that can be converted to / from string #​2811
#[derive(Copy, Clone, Debug, PartialEq, Eq, DeriveValueType)]
#[sea_orm(value_type = "String")]
pub struct Tag3 {
    pub i: i64,
}

impl std::fmt::Display for Tag3 {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.i)
    }
}

impl std::str::FromStr for Tag3 {
    type Err = std::num::ParseIntError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let i: i64 = s.parse()?;
        Ok(Self { i })
    }
}
  • Fix DeriveIntoActiveModel on Option<T> fields #​2926
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "fruit")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: i32,
    pub name: String,
    pub cake_id: Option<i32>,
}

#[derive(DeriveIntoActiveModel)]

#[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
struct PartialFruit {
    cake_id: Option<i32>,
}

assert_eq!(
    PartialFruit { cake_id: Some(1) }.into_active_model(),
    fruit::ActiveModel { id: NotSet, name: NotSet, cake_id: Set(Some(1)) }
);

assert_eq!(
    PartialFruit { cake_id: None }.into_active_model(),
    fruit::ActiveModel { id: NotSet, name: NotSet, cake_id: NotSet }
);
  • FromQueryResult now supports nullable nested model #​2845
#[derive(FromQueryResult)]
struct CakeWithOptionalBakeryModel {
    #[sea_orm(alias = "cake_id")]
    id: i32,
    #[sea_orm(alias = "cake_name")]
    name: String,
    #[sea_orm(nested)]
    bakery: Option<bakery::Model>, // can be null
}
  • Added try_from_u64 to DeriveValueType #​2958
// Test for try_from_u64 attribute with type alias
type UserId = i32;

#[derive(Clone, Debug, PartialEq, Eq, DeriveValueType)]

#[sea_orm(try_from_u64)]
pub struct MyUserId(pub UserId);
  • Arrow / Parquet support #​2957
    • Added ArrowSchema, DeriveArrowSchema
    • Support decimal with different formats
    • Support timestamp with different timezone / resolution
    • Added parquet example
  • Support HashMap and BTreeMap for JSON columns via TryGetableFromJson #​3009
  • Derive macros now inherit the visibility of the input type for generated items such as Entity, Column, PrimaryKey, and ActiveModel #​3029
Bug Fixes
  • [sea-orm-migration] PostgreSQL drop_everything now drops custom types with CASCADE
Breaking Changes

Please read SeaQuery's breaking changes as well. But for most compile errors, you can simply add use sea_orm::ExprTrait; in scope.

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<L>(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_orm::ExprTrait;
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`
error[E0308]: mismatched types
    |
390 |             Some(Expr::col(Name).eq(PgFunc::any(query.symbol)))
    |                                  -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&Expr`, found `FunctionCall`
    |                                  |
    |                                  arguments to this method are incorrect
    |
note: method defined here
   --> /rustc/6b00bc3880198600130e1cf62b8f8a93494488cc/library/core/src/cmp.rs:254:8
error[E0277]: the trait bound `sea_orm::Condition: From<bool>` is not satisfied
    |
367 |         .add_option(option)
    |          ---------- ^^^^^^ the trait `From<bool>` is not implemented for `sea_orm::Condition`
    |          |
    |          required by a bound introduced by this call
    |
    = note: required for `bool` to implement `Into<sea_orm::Condition>`
  • Removed runtime-actix feature flag. It's been an alias of runtime-tokio for more than a year, so there should be no impact.
  • Enabled sqlite-use-returning-for-3_35 by default. SQLite 3.35 was released in 2021, it should be the default by now.
  • Now implemented impl<T: ModelTrait + FromQueryResult> PartialModelTrait for T, there may be a potential conflict #​2642
  • Now DeriveValueType will also TryFromU64 if applicable, there may be a potential conflict #​2643
  • Now DeriveValueType also impl IntoActiveValue and NotU8, there may be a potential conflict
  • Added TryIntoModel and Serialize to trait bounds of ActiveModel::from_json. There should be no impact if your models are derived with DeriveEntityModel #​2599
fn from_json(mut json: serde_json::Value) -> Result<Self, DbErr>
where
    Self: TryIntoModel<<Self::Entity as EntityTrait>::Model>,
    <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
    for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
        serde::de::Deserialize<'de> + serde::Serialize,
  • DerivePartialModel now implement FromQueryResult by default, so there may be a potential conflict. Remove FromQueryResult in these cases #​2653
error[E0119]: conflicting implementations of trait `sea_orm::FromQueryResult` for type `CakeWithFruit`
  |
> | #[derive(DerivePartialModel, FromQueryResult)]
  |          ------------------  ^^^^^^^^^^^^^^^ conflicting implementation for `CakeWithFruit`
  • Changed IdenStatic and EntityName definition #​2667
trait IdenStatic {
    fn as_str(&self) -> &'static str; // added static lifetime
}
trait EntityName {
    fn table_name(&self) -> &'static str; // added static lifetime
}
  • Removed DeriveCustomColumn and default_as_str #​2667
// This is no longer supported:

#[derive(Copy, Clone, Debug, EnumIter, DeriveCustomColumn)]
pub enum Column {
    Id,
    Name,
}

impl IdenStatic for Column {
    fn as_str(&self) -> &str {
        match self {
            Self::Name => "my_name",
            _ => self.default_as_str(),
        }
    }
}

// Do the following instead:

#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
pub enum Column {
    Id,
    #[sea_orm(column_name = "my_name")]
    Name,
}
  • execute, query_one, query_all, stream now takes in SeaQuery statement instead of raw SQL statement. a new set of methods execute_raw, query_one_raw, query_all_raw, stream_raw is added #​2657
  --> src/executor/paginator.rs:53:38
   |
>  |         let rows = self.db.query_all(stmt).await?;
   |                            --------- ^^^^ expected `&_`, found `Statement`
   |                            |
   |                            arguments to this method are incorrect
   |
   = note: expected reference `&_`
                 found struct `statement::Statement`
let backend = self.db.get_database_backend();
let stmt = backend.build(&query);
// change to:
let rows = self.db.query_all_raw(stmt).await?;
// if the query is a SeaQuery statement, then just do this:
let rows = self.db.query_all(&query).await?; // no need to build query
  • DatabaseConnection is changed from enum to struct. The original enum is moved into DatabaseConnection::inner. The new enum is named DatabaseConnectionType #​2671
error[E0599]: no associated item named `Disconnected` found for struct `db_connection::DatabaseConnection` in the current scope
   --> src/database/db_connection.rs:137:33
    |
>   | pub struct DatabaseConnection {
    | ----------------------------- associated item `Disconnected` not found for this struct
...
>   |             DatabaseConnection::Disconnected => Err(conn_err("Disconnected")),
    |                                 ^^^^^^^^^^^^ associated item not found in `DatabaseConnection`
match conn.inner {
    DatabaseConnectionType::Disconnected => (),
    _ => (),
}
  • DeleteOne and UpdateOne no longer implement QueryFilter and QueryTrait
    directly. Those implementations could expose an incomplete SQL query with an
    incomplete condition that touches too many records. To generate the right
    condition, we must make sure that the primary key is set on the input
    ActiveModel. If you need to access the generated SQL query, convert into
    ValidatedDeleteOne/ValidatedUpdateOne first.
error[E0599]: no method named `build` found for struct `query::update::UpdateOne` in the current scope
   --> src/entity/column.rs:607:22
    |
  > | /                 Update::one(active_model)
  > | |                     .build(DbBackend::Postgres)
    | |                     -^^^^^ method not found in `UpdateOne<A>`
    | |_____________________|
    |

Call the validate() method:

Update::one(active_model)
  + .validate()?
    .build(DbBackend::Postgres)
  • Removed DbBackend::get_query_builder() because QueryBuilder is not longer object safe.
  - fn get_query_builder(&self) -> Box<dyn QueryBuilder>
  • A number of methods has been removed from SelectTwoMany: into_partial_model, into_json, stream. These methods are same as those in SelectTwo.
    Please use Cake::find().find_also_related(Fruit).into_json() instead.
  • The delete_by_id method has changed to returning DeleteOne instead of DeleteMany. It doesn't change normal exec usage, but would change return type of exec_with_returning to Option<Model>
fn delete_by_id<T>(values: T) -> DeleteMany<Self>         // old

fn delete_by_id<T>(values: T) -> ValidatedDeleteOne<Self> // new
  • DeriveActiveEnum now also automatically impl IntoActiveValue, if you have a custom impl before, there would be a collision
  • with-bigdecimal is now removed from default features
  • RuntimeErr::SqlxError is now held in Arc to make DbErr clonable and smaller:
pub enum RuntimeErr {
    SqlxError(Arc<sqlx::error::Error>),
Upgrades
  • Upgraded Rust Edition to 2024 #​2596
  • Upgraded strum to 0.27

Configuration

📅 Schedule: (UTC)

  • Branch creation
    • Between 12:00 AM and 03:59 AM, only on Monday (* 0-3 * * 1)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about these updates again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate
renovate Bot force-pushed the renovate/major-sea-orm-monorepo branch from fa6c09d to 06896a4 Compare July 27, 2026 04:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants