PageSourceSearch

https://www.sea-ql.org/blog/assets/js/9d602b09.43d4bec9.js

js sea-ql.org collected 2026-10-03 19:05:02 UTC 29,173 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunksea_ql_blog=self.webpackChunksea_ql_blog||[]).push([[1679],{5680:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023-08-12-announcing-seaorm-0.12","editUrl":"https://github.com/SeaQL/seaql.github.io/edit/master/Blog/blog/2023-08-12-announcing-seaorm-0.12.md","source":"@site/blog/2023-08-12-announcing-seaorm-0.12.md","title":"Announcing SeaORM 0.12","description":"\ud83c\udf89 We are pleased to announce SeaORM 0.12 today!","date":"2023-08-12T00:00:00.000Z","tags":[{"inline":true,"label":"news","permalink":"/blog/tags/news"}],"readingTime":10.6,"hasTruncateMarker":false,"authors":[{"name":"SeaQL Team","title":"Chris Tsang","url":"https://github.com/SeaQL","imageURL":"https://www.sea-ql.org/blog/img/SeaQL.png","key":null,"page":null}],"frontMatter":{"slug":"2023-08-12-announcing-seaorm-0.12","title":"Announcing SeaORM 0.12","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","tags":["news"]},"unlisted":false,"prevItem":{"title":"What\'s new in SeaStreamer 0.3","permalink":"/blog/2023-09-06-whats-new-in-sea-streamer-0.3"},"nextItem":{"title":"Introducing SeaStreamer \ud83c\udf0a","permalink":"/blog/2023-04-03-intro-sea-streamer"}}')},5867:(e,a,r)=>{r.r(a),r.d(a,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>n,toc:()=>d});var n=r(5680),t=r(4848),s=r(8453);const i={slug:"2023-08-12-announcing-seaorm-0.12",title:"Announcing SeaORM 0.12",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",tags:["news"]},o=void 0,l={authorsImageUrls:[void 0]},d=[{value:"New Features \ud83c\udf1f",id:"new-features-",level:2},{value:"\ud83e\udded Seaography: GraphQL integration (preview)",id:"-seaography-graphql-integration-preview",level:3},{value:"Added macro <code>DerivePartialModel</code>",id:"added-macro-derivepartialmodel",level:3},{value:"Added <code>Select::find_with_linked</code>",id:"added-selectfind_with_linked",level:3},{value:"Added <code>DeriveValueType</code> derive macro for custom wrapper types",id:"added-derivevaluetype-derive-macro-for-custom-wrapper-types",level:3},{value:"Enhancements \ud83c\udd99",id:"enhancements-",level:2},{value:"#1433 Chained AND / OR join ON condition",id:"1433-chained-and--or-join-on-condition",level:4},{value:"#1508 Supports entity with composite primary key of arity 12",id:"1508-supports-entity-with-composite-primary-key-of-arity-12",level:4},{value:"#1677 Added <code>UpdateMany::exec_with_returning()</code>",id:"1677-added-updatemanyexec_with_returning",level:4},{value:"#1511 Added <code>MigratorTrait::migration_table_name()</code> method to configure the name of migration table",id:"1511-added-migratortraitmigration_table_name-method-to-configure-the-name-of-migration-table",level:4},{value:"#1707 Added <code>DbErr::sql_err()</code> method to parse common database errors",id:"1707-added-dberrsql_err-method-to-parse-common-database-errors",level:4},{value:"#1737 Introduced new <code>ConnAcquireErr</code>
1",id:"1737-introduced-new-connacquireerr",level:4},{value:"#1627 Added <code>DatabaseConnection::ping()</code>",id:"1627-added-databaseconnectionping",level:4},{value:"#1708 Added <code>TryInsert</code> that does not panic on empty inserts",id:"1708-added-tryinsert-that-does-not-panic-on-empty-inserts",level:4},{value:"#1712 Insert on conflict do nothing to return Ok",id:"1712-insert-on-conflict-do-nothing-to-return-ok",level:4},{value:"#1740, #1755 Replacing <code>sea_query::Iden</code> with <code>sea_orm::DeriveIden</code>",id:"1740-1755-replacing-sea_queryiden-with-sea_ormderiveiden",level:4},{value:"New Release <del>Train</del> Ferry \ud83d\udea2",id:"new-release-train-ferry-",level:2},{value:"Community Survey \ud83d\udcdd",id:"community-survey-",level:2},{value:"Sponsor \ud83e\udd47",id:"sponsor-",level:2},{value:"What&#39;s Next for SeaORM? \u26f5",id:"whats-next-for-seaorm-",level:2}];function c(e){const a={a:"a",code:"code",del:"del",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("img",{alt:"SeaORM 0.12 Banner",src:"/blog/img/SeaORM%2012%20Banner.png"}),"\n",(0,t.jsxs)(a.p,{children:["\ud83c\udf89 We are pleased to announce SeaORM ",(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/releases/tag/0.12.1",children:(0,t.jsx)(a.code,{children:"0.12"})})," today!"]}),"\n",(0,t.jsxs)(a.p,{children:["We still remember the time when we first ",(0,t.jsx)(a.a,{href:"https://www.sea-ql.org/blog/2021-09-20-introducing-sea-orm/",children:"introduced SeaORM"})," to the Rust community two years ago. We set out a goal to enable developers to build asynchronous database-driven applications in Rust."]}),"\n",(0,t.jsxs)(a.p,{children:["Today, many open-source projects, ",(0,t.jsx)(a.a,{href:"https://www.sea-ql.org/SeaORM/index.html#our-users",children:"a handful of startups"})," and many more closed-source projects are using SeaORM. Thank you all who participated and contributed in the making!"]}),"\n",(0,t.jsx)("img",{alt:"SeaORM Star History",src:"/blog/img/star-history-sea-orm-2023.png"}),"\n",(0,t.jsx)(a.h2,{id:"new-features-",children:"New Features \ud83c\udf1f"}),"\n",(0,t.jsxs)(a.h3,{id:"-seaography-graphql-integration-preview",children:["\ud83e\udded ",(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/seaography",children:"Seaography"}),": GraphQL integration (preview)"]}),"\n",(0,t.jsx)("img",{alt:"Seaography example",src:"/blog/img/Seaography%20example.png"}),"\n",(0,t.jsxs)(a.p,{children:["Seaography is a GraphQL framework built on top of SeaORM. In ",(0,t.jsx)(a.code,{children:"0.12"}),", Seaography integration is built into ",(0,t.jsx)(a.code,{children:"sea-orm"}),".\nSeaography allows you to build GraphQL resolvers quickly. With just a few commands, you can launch a GraphQL server from SeaORM entities!"]}),"\n",(0,t.jsx)(a.p,{children:"While Seaography development is still in an early stage, it is especially useful in prototyping and building internal-use admin panels."}),"\n",(0,t.jsxs)(a.p,{children:[(0,t.jsx)(a.a,{href:"https://www.sea-ql.org/SeaORM/docs/seaography/seaography-intro/",children:"Read the documentation"})," to learn more."]}),"\n",(0,t.jsxs)(a.h3,{id:"added-macro-derivepartialmodel",children:["Added macro ",(0,t.jsx)(a.a,{href:"https://docs.rs/sea-orm/0.12.2/sea_orm/derive.DerivePartialModel.html",children:(0,t.jsx)(a.code,{children:"DerivePartialModel"})})]}),"\n",(0,t.jsxs)(a.p,{children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1597",children:"#1597"})," Now you can easily perform custom select to query only the columns you needed"]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:'#[derive(DerivePartialModel, FromQueryResult)]\n#[sea_orm(entity = "Cake")]\nstruct PartialCake {\n    name: String,\n    #[sea_orm(\n        from_expr = r#"SimpleExpr::FunctionCall(Func::upper(Expr::col((Cake, cake::Column::Name))))"#\n    )]\n    name_upper: String,\n}\n\nassert_eq!(\n    cake::Entity::find()\n        .into_partial_model::<PartialCake>
1()\n        .into_statement(DbBackend::Sqlite)\n        .to_string(),\n    r#"SELECT "cake"."name", UPPER("cake"."name") AS "name_upper" FROM "cake""#\n);\n'})}),"\n",(0,t.jsxs)(a.h3,{id:"added-selectfind_with_linked",children:["Added ",(0,t.jsx)(a.a,{href:"https://docs.rs/sea-orm/0.12.2/sea_orm/query/struct.Select.html#method.find_with_linked",children:(0,t.jsx)(a.code,{children:"Select::find_with_linked"})})]}),"\n",(0,t.jsxs)(a.p,{children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1728",children:"#1728"}),", ",(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1743",children:"#1743"})," Similar to ",(0,t.jsx)(a.code,{children:"find_with_related"}),", you can now select related entities and consolidate the models."]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:"// Consider the following link\npub struct BakedForCustomer;\n\nimpl Linked for BakedForCustomer {\n    type FromEntity = Entity;\n\n    type ToEntity = super::customer::Entity;\n\n    fn link(&self) -> Vec<RelationDef> {\n        vec![\n            super::cakes_bakers::Relation::Baker.def().rev(),\n            super::cakes_bakers::Relation::Cake.def(),\n            super::lineitem::Relation::Cake.def().rev(),\n            super::lineitem::Relation::Order.def(),\n            super::order::Relation::Customer.def(),\n        ]\n    }\n}\n\nlet res: Vec<(baker::Model, Vec<customer::Model>)>
1 = Baker::find()\n    .find_with_linked(baker::BakedForCustomer)\n    .order_by_asc(baker::Column::Id)\n    .all(db)\n    .await?\n"})}),"\n",(0,t.jsxs)(a.h3,{id:"added-derivevaluetype-derive-macro-for-custom-wrapper-types",children:["Added ",(0,t.jsx)(a.a,{href:"https://docs.rs/sea-orm/latest/sea_orm/derive.DeriveValueType.html",children:(0,t.jsx)(a.code,{children:"DeriveValueType"})})," derive macro for ",(0,t.jsx)(a.a,{href:"https://www.sea-ql.org/SeaORM/docs/generate-entity/newtype/",children:"custom wrapper types"})]}),"\n",(0,t.jsxs)(a.p,{children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1720",children:"#1720"})," So now you can use newtypes easily."]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:'#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]\n#[sea_orm(table_name = "custom_value_type")]\npub struct Model {\n    #[sea_orm(primary_key)]\n    pub id: i32,\n    pub number: Integer,\n    // Postgres only\n    pub str_vec: StringVec,\n}\n\n#[derive(Clone, Debug, PartialEq, Eq, DeriveValueType)]\npub struct Integer(i32);\n\n#[derive(Clone, Debug, PartialEq, Eq, DeriveValueType)]\npub struct StringVec(pub Vec<String>);\n'})}),"\n",(0,t.jsx)(a.p,{children:"Which saves you the boilerplate of:"}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:'impl std::convert::From<StringVec> for Value { .. }\n\nimpl TryGetable for StringVec {\n    fn try_get_by<I: ColIdx>(res: &QueryResult, idx: I)\n        -> Result<Self, TryGetError> { .. }\n}\n\nimpl ValueType for StringVec {\n    fn try_from(v: Value) -> Result<Self, ValueTypeErr> { .. }\n\n    fn type_name() -> String { "StringVec".to_owned() }\n\n    fn array_type() -> ArrayType { ArrayType::String }\n\n    fn column_type() -> ColumnType { ColumnType::String(None) }\n}\n'})}),"\n",(0,t.jsx)(a.h2,{id:"enhancements-",children:"Enhancements \ud83c\udd99"}),"\n",(0,t.jsxs)(a.h4,{id:"1433-chained-and--or-join-on-condition",children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1433",children:"#1433"})," Chained AND / OR join ON condition"]}),"\n",(0,t.jsxs)(a.p,{children:["Added more macro attributes to ",(0,t.jsx)(a.a,{href:"https://docs.rs/sea-orm/0.12.2/sea_orm/derive.DeriveRelation.html",children:(0,t.jsx)(a.code,{children:"DeriveRelation"})})]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:'// Entity file\n\n#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]\npub enum Relation {\n    // By default, it\'s `JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` AND `fruit`.`name` LIKE \'%tropical%\'`\n    #[sea_orm(\n        has_many = "super::fruit::Entity",\n        on_condition = r#"super::fruit::Column::Name.like("%tropical%")"#\n    )]\n    TropicalFruit,\n    // Specify `condition_type = "any"` to override it, now it becomes\n    // `JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` OR `fruit`.`name` LIKE \'%tropical%\'`\n    #[sea_orm(\n        has_many = "super::fruit::Entity",\n        on_condition = r#"super::fruit::Column::Name.like("%tropical%")"#\n        condition_type = "any",\n    )]\n    OrTropicalFruit,\n}\n'})}),"\n",(0,t.jsxs)(a.h4,{id:"1508-supports-entity-with-composite-primary-key-of-arity-12",children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1508",children:"#1508"})," Supports entity with composite primary key of arity 12"]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:'#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]\n#[sea_orm(table_name = "primary_key_of_12")]\npub struct Model {\n    #[sea_orm(primary_key, auto_increment = false)]\n    pub id_1: String,\n    ...\n    #[sea_orm(primary_key, auto_increment = false)]\n    pub id_12: bool,\n}\n'})}),"\n",(0,t.jsxs)(a.h4,{id:"1677-added-updatemanyexec_with_returning",children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1677",children:"#1677"})," Added ",(0,t.jsx)(a.a,{href:"https://docs.rs/sea-orm/0.12.2/sea_orm/query/struct.UpdateMany.html#method.exec_with_returning",children:(0,t.jsx)(a.code,{children:"UpdateMany::exec_with_returning()"})})]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:"let models: Vec<Model> = Entity::update_many()\n    .col_expr(Column::Values, Expr::expr(..))\n    .exec_with_returning(db)\n    .await?;\n"})}),"\n",(0,t.jsxs)(a.h4,{id:"1511-added-migratortraitmigration_table_name-method-to-configure-the-name-of-migration-table",children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1511",children:"#1511"})," Added ",(0,t.jsx)(a.a,{href:"https://docs.rs/sea-orm-migration/0.12.2/sea_orm_migration/migrator/trait.MigratorTrait.html#method.migration_table_name",children:(0,t.jsx)(a.code,{children:"MigratorTrait::migration_table_name()"})})," method to configure the name of migration table"]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:'#[async_trait::async_trait]\nimpl MigratorTrait for Migrator {\n    // Override the name of migration table\n    fn migration_table_name() -> sea_orm::DynIden {\n        Alias::new("override_migration_table_name").into_iden()\n    }\n    ...\n}\n'})}),"\n",(0,t.jsxs)(a.h4,{id:"1707-added-dberrsql_err-method-to-parse-common-database-errors",children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1707",children:"#1707"})," Added ",(0,t.jsx)(a.a,{href:"https://docs.rs/sea-orm/0.12.2/sea_orm/error/enum.DbErr.html#method.sql_err",children:(0,t.jsx)(a.code,{children:"DbErr::sql_err()"})})," method to parse common database errors"]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:'assert!(matches!(\n    cake.into_active_model().insert(db).await\n        .expect_err("Insert a row with duplicated primary key")\n        .sql_err(),\n    Some(SqlErr::UniqueConstraintViolation(_))\n)
1);\n\nassert!(matches!(\n    fk_cake.insert(db).await\n        .expect_err("Insert a row with invalid foreign key")\n        .sql_err(),\n    Some(SqlErr::ForeignKeyConstraintViolation(_))\n));\n'})}),"\n",(0,t.jsxs)(a.h4,{id:"1737-introduced-new-connacquireerr",children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1737",children:"#1737"})," Introduced new ",(0,t.jsx)(a.a,{href:"https://docs.rs/sea-orm/0.12.2/sea_orm/error/enum.ConnAcquireErr.html",children:(0,t.jsx)(a.code,{children:"ConnAcquireErr"})})]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:"enum DbErr {\n    ConnectionAcquire(ConnAcquireErr),\n    ..\n}\n\nenum ConnAcquireErr {\n    Timeout,\n    ConnectionClosed,\n}\n"})}),"\n",(0,t.jsxs)(a.h4,{id:"1627-added-databaseconnectionping",children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1627",children:"#1627"})," Added ",(0,t.jsx)(a.a,{href:"https://docs.rs/sea-orm/0.12.2/sea_orm/error/enum.ConnAcquireErr.html",children:(0,t.jsx)(a.code,{children:"DatabaseConnection::ping()"})})]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:"|db: DatabaseConnection| {\n    assert!(db.ping().await.is_ok());\n    db.clone().close().await;\n    assert!(matches!(db.ping().await, Err(DbErr::ConnectionAcquire)));\n}\n"})}),"\n",(0,t.jsxs)(a.h4,{id:"1708-added-tryinsert-that-does-not-panic-on-empty-inserts",children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1708",children:"#1708"})," Added ",(0,t.jsx)(a.a,{href:"https://docs.rs/sea-orm/0.12.2/sea_orm/query/struct.TryInsert.html",children:(0,t.jsx)(a.code,{children:"TryInsert"})})," that does not panic on empty inserts"]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:"// now, you can do:\nlet res = Bakery::insert_many(std::iter::empty())\n    .on_empty_do_nothing()\n    .exec(db)\n    .await;\n\nassert!(matches!(res, Ok(TryInsertResult::Empty)));\n"})}),"\n",(0,t.jsxs)(a.h4,{id:"1712-insert-on-conflict-do-nothing-to-return-ok",children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1712",children:"#1712"})," Insert on conflict do nothing to return Ok"]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:"let on = OnConflict::column(Column::Id).do_nothing().to_owned();\n\n// Existing behaviour\nlet res = Entity::insert_many([..]).on_conflict(on).exec(db).await;\nassert!(matches!(res, Err(DbErr::RecordNotInserted)));\n\n// New API; now you can:\nlet res =\nEntity::insert_many([..]).on_conflict(on).do_nothing().exec(db).await;\nassert!(matches!(res, Ok(TryInsertResult::Conflicted)));\n"})}),"\n",(0,t.jsxs)(a.h4,{id:"1740-1755-replacing-sea_queryiden-with-sea_ormderiveiden",children:[(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1740",children:"#1740"}),", ",(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/pull/1755",children:"#1755"})," Replacing ",(0,t.jsx)(a.code,{children:"sea_query::Iden"})," with ",(0,t.jsx)(a.a,{href:"https://docs.rs/sea-orm/0.12.2/sea_orm/derive.DeriveIden.html",children:(0,t.jsx)(a.code,{children:"sea_orm::DeriveIden"})})]}),"\n",(0,t.jsxs)(a.p,{children:["To provide a more consistent interface, ",(0,t.jsx)(a.code,{children:"sea-query/derive"})," is no longer enabled by ",(0,t.jsx)(a.code,{children:"sea-orm"}),", as such, ",(0,t.jsx)(a.code,{children:"Iden"})," no longer works as a derive macro (it's still a trait)."]}),"\n",(0,t.jsx)(a.pre,{children:(0,t.jsx)(a.code,{className:"language-rust",children:'// then:\n\n#[derive(Iden)]\n#[iden = "category"]\npub struct CategoryEnum;\n\n#[derive(Iden)]\npub enum Tea {\n    Table,\n    #[iden = "AfternoonTea"]\n    EverydayTea,\n}\n\n// now:\n\n#[derive(DeriveIden)]\n#[sea_orm(iden = "category")]\npub struct CategoryEnum;\n\n#[derive(DeriveIden)]\npub enum Tea {\n    Table,\n    #[sea_orm(iden = "AfternoonTea")]\n    EverydayTea,\n}\n'})}),"\n",(0,t.jsxs)(a.h2,{id:"new-release-train-ferry-",children:["New Release ",(0,t.jsx)(a.del,{children:"Train"})," Ferry \ud83d\udea2"]}),"\n",(0,t.jsxs)(a.p,{children:["It's been the ",(0,t.jsx)(a.strong,{children:"12th"})," release of SeaORM! Initially, a major version was released every month. It gradually became 2 to 3 months, and now, it's been 6 months since the last major release. As our userbase grew and s
1ome are already ",(0,t.jsx)(a.a,{href:"https://github.com/SeaQL/sea-orm/blob/master/COMMUNITY.md#startups",children:"using SeaORM in production"}),", we understand the importance of having a stable API surface and feature set."]}),"\n",(0,t.jsx)(a.p,{children:"That's why we are committed to:"}),"\n",(0,t.jsxs)(a.ol,{children:["\n",(0,t.jsx)(a.li,{children:"Reviewing breaking changes with strict scrutiny"}),"\n",(0,t.jsx)(a.li,{children:"Expanding our test suite to cover all features of our library"}),"\n",(0,t.jsx)(a.li,{children:"Never remove features, and consider deprecation carefully"}),"\n"]}),"\n",(0,t.jsxs)(a.p,{children:["Today, the architecture of SeaORM is pretty solid and stable, and with the ",(0,t.jsx)(a.code,{children:"0.12"})," release where we paid back a lot of technical debt, we will be able to deliver new features and enhancements without breaking. As our major dependency ",(0,t.jsx)(a.a,{href:"https://github.com/launchbadge/sqlx",children:"SQLx"})," is not ",(0,t.jsx)(a.code,{children:"1.0"})," yet, technically we cannot be ",(0,t.jsx)(a.code,{children:"1.0"}),"."]}),"\n",(0,t.jsxs)(a.p,{children:["We are still advancing rapidly, and we will always make a new release as soon as SQLx makes a new release, so that you can upgrade everything at once. As a result, the next major release of SeaORM will come out ",(0,t.jsx)(a.strong,{children:"6 months from now, or when SQLx makes a new release"}),", whichever is earlier."]}),"\n",(0,t.jsxs)(a.h2,{id:"community-survey-",children:[(0,t.jsx)(a.a,{href:"https://www.sea-ql.org/community-survey",children:"Community Survey"})," \ud83d\udcdd"]}),"\n",(0,t.jsxs)(a.p,{children:["SeaQL is an independent open-source organization. Our goal is to enable developers to build data intensive applications in Rust. If you are using SeaORM, please participate in the ",(0,t.jsx)(a.a,{href:"https://www.sea-ql.org/community-survey",children:"SeaQL Community Survey"}),"!"]}),"\n",(0,t.jsx)(a.p,{children:"By completing this survey, you will help us gather insights into how you, the developer, are using our libraries and identify means to improve your developer experience. We will also publish an annual survey report to summarize our findings."}),"\n",(0,t.jsxs)(a.p,{children:["If you are a happy user of SeaORM, consider ",(0,t.jsx)(a.a,{href:"https://forms.office.com/r/YbeqfTAgkJ",children:"writing us a testimonial"}),"!"]}),"\n",(0,t.jsx)(a.h2,{id:"sponsor-",children:"Sponsor \ud83e\udd47"}),"\n",(0,t.jsxs)(a.p,{children:["A big thank to ",(0,t.jsx)(a.a,{href:"https://www.digitalocean.com/",children:"DigitalOcean"})," who sponsored our server hosting, and ",(0,t.jsx)(a.a,{href:"https://www.jetbrains.com/",children:"JetBrains"})," who sponsored our IDE, and every sponsor on ",(0,t.jsx)(a.a,{href:"https://github.com/sponsors/SeaQL",children:"GitHub Sponsor"}),"!"]}),"\n",(0,t.jsx)(a.p,{children:"If you feel generous, a small donation will be greatly appreciated, and goes a long way towards sustaining the organization."}),"\n",(0,t.jsx)(a.p,{children:"A big shout out to our sponsors \ud83d\ude07:"}),"\n",(0,t.jsxs)("div",{class:"row",children:[(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",href:"https://github.com/shanesveller",children:(0,t.jsx)("img",{src:"https://avatars.githubusercontent.com/u/831?v=4"})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"Shane Sveller"})})})]})}),(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",href:"https://github.com/Sytten",children:(0,t.jsx)("img",{src:"https://avatars.githubusercontent.com/u/2366731?v=4"})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"\xc9mile Fugulin"})})})]})}),(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",href:"https://github.com/tugascript",children:(0,t.jsx)("img",{src:"https://avatars.githubusercontent.com/u/64930104?v=4"})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"Afonso Barracha"})})})]})}),(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",href:"https://github.com/trueb2",children:(0,t.jsx)("img",{src:"https://avatars.githubusercontent.com/u/8592049?v=4"})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"Jacob Trueb"})})})]})}),(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",href:"https://github.com/siketyan",children:(0,t.jsx)("img",{src:"https://avatars.githubusercontent.com/u/12772118?v=4"})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"Natsuki Ikeguchi"})})})]})}),(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",href:"https://github.com/mmuellersoppart",children:(0,t.jsx)("img",{src:"https://avatars.githubusercontent.com/u/16762461?v=4"})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"Marlon Mueller-Soppart"})})})]})}),(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",href:"https://github.com/kallydev",children:(0,t.jsx)("img",{src:"https://avatars.githubusercontent.com/u/36319157?v=4"})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"KallyDev"})})})]})}),(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",href:"https://github.com/deansheather",children:(0,t.jsx)("img",{src:"https://avatars.githubusercontent.com/u/11241812?v=4"})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"Dean Sheather"})})})]})}),(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",href:"https://github.com/manfredcml",children:(0,t.jsx)("img",{src:"https://avatars.githubusercontent.com/u/27536502?v=4"})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"Manfred Lee"})})})]})}),(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",href:"https://github.com/rgoracz",children:(0,t.jsx)("img",{src:"https://avatars.githubusercontent.com/u/6758092?v=4"})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"Roland Gor\xe1cz"})})})]})}),(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",href:"https://github.com/Iceapinan",children:(0,t.jsx)("img",{src:"https://avatars.githubusercontent.com/u/2698243?v=4"})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"IceApinan"})})})]})}),(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",href:"https://github.com/reneklacan",children:(0,t.jsx)("img",{src:"https://avatars.githubusercontent.com/u/1935686?v=4"})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"Ren\xe9 Kla\u010dan"})})})]})}),(0,t.jsx)("div",{class:"col col--6 margin-bottom--md",children:(0,t.jsxs)("div",{class:"avatar",children:[(0,t.jsx)("a",{class:"avatar__photo-link avatar__photo avatar__photo--sm",children:(0,t.jsx)("img",{style:{width:"100%"},src:"data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="})}),(0,t.jsx)("div",{class:"avatar__intro",children:(0,t.jsx)("div",{class:"avatar__name",children:(0,t.jsx)(a.p,{children:"Unnamed Sponsor"})})})]})})]}),"\n",(0,t.jsx)(a.h2,{id:"whats-next-for-seaorm-",children:"What's Next for SeaORM? \u26f5"}),"\n",(0,t.jsx)(a.p,{children:"Open-source project is a never-ending work, and we are actively looking for ways to sustain the project. You can support our endeavour by starring & sharing our repositories and becoming a sponsor."}),"\n",(0,t.jsxs)(a.p,{children:["We are considering multiple directions to generate revenue for the organization. If you have any suggestion, or want to join or collaborate with us, please contact us via ",(0,t.jsx)(a.code,{children:"hello[at]sea-ql.org"}),"."]}
1),"\n",(0,t.jsx)(a.p,{children:"Thank you for your support, and together we can make open-source sustainable."})]})}function h(e={}){const{wrapper:a}={...(0,s.R)(),...e.components};return a?(0,t.jsx)(a,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,a,r)=>{r.d(a,{R:()=>i,x:()=>o});var n=r(6540);const t={},s=n.createContext(t);function i(e){const a=n.useContext(s);return n.useMemo(function(){return"function"==typeof e?e(a):{...a,...e}},[a,e])}function o(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),n.createElement(s.Provider,{value:a},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.