Skip to main content

sea_orm/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![warn(missing_docs)]
3#![deny(
4    missing_debug_implementations,
5    clippy::missing_panics_doc,
6    clippy::unwrap_used,
7    clippy::print_stderr,
8    clippy::print_stdout
9)]
10
11//! <div align="center">
12//!
13//!   <img alt="SeaORM" src="https://www.sea-ql.org/blog/img/SeaORM 2.0 Banner.png"/>
14//!
15//!   <h1></h1>
16//!   <h3>SeaORM is a powerful ORM for building web services in Rust</h3>
17//!
18//!   [![crate](https://img.shields.io/crates/v/sea-orm.svg)](https://crates.io/crates/sea-orm)
19//!   [![build status](https://github.com/SeaQL/sea-orm/actions/workflows/rust.yml/badge.svg)](https://github.com/SeaQL/sea-orm/actions/workflows/rust.yml)
20//!   [![GitHub stars](https://img.shields.io/github/stars/SeaQL/sea-orm.svg?style=social&label=Star&maxAge=1)](https://github.com/SeaQL/sea-orm/stargazers/)
21//!   <br>Support us with a ⭐ !
22//!
23//! </div>
24//!
25//! # 🐚 SeaORM
26//!
27//! [δΈ­ζ–‡ζ–‡ζ‘£](https://github.com/SeaQL/sea-orm/blob/master/README-zh.md)
28//!
29//! ### Advanced Relations
30//!
31//! Model complex relationships 1-1, 1-N, M-N, and even self-referential in a high-level, conceptual way.
32//!
33//! ### Familiar Concepts
34//!
35//! Inspired by popular ORMs in the Ruby, Python, and Node.js ecosystem, SeaORM offers a developer experience that feels instantly recognizable.
36//!
37//! ### Feature Rich
38//!
39//! SeaORM is a batteries-included ORM with filters, pagination, and nested queries to accelerate building REST, GraphQL, and gRPC APIs.
40//!
41//! ### Production Ready
42//!
43//! With 250k+ weekly downloads, SeaORM is production-ready, trusted by startups and enterprises worldwide.
44//!
45//! ## Getting Started
46//!
47//! [![Discord](https://img.shields.io/discord/873880840487206962?label=Discord)](https://discord.com/invite/uCPdDXzbdv)
48//! Join our Discord server to chat with others!
49//!
50//! + [Documentation](https://www.sea-ql.org/SeaORM)
51//!
52//! Integration examples:
53//!
54//! + [Actix Example](https://github.com/SeaQL/sea-orm/tree/master/examples/actix_example)
55//! + [Axum Example](https://github.com/SeaQL/sea-orm/tree/master/examples/axum_example)
56//! + [GraphQL Example](https://github.com/SeaQL/sea-orm/tree/master/examples/graphql_example)
57//! + [jsonrpsee Example](https://github.com/SeaQL/sea-orm/tree/master/examples/jsonrpsee_example)
58//! + [Loco Example](https://github.com/SeaQL/sea-orm/tree/master/examples/loco_example) / [Loco REST Starter](https://github.com/SeaQL/sea-orm/tree/master/examples/loco_starter)
59//! + [Poem Example](https://github.com/SeaQL/sea-orm/tree/master/examples/poem_example)
60//! + [Rocket Example](https://github.com/SeaQL/sea-orm/tree/master/examples/rocket_example) / [Rocket OpenAPI Example](https://github.com/SeaQL/sea-orm/tree/master/examples/rocket_okapi_example)
61//! + [Salvo Example](https://github.com/SeaQL/sea-orm/tree/master/examples/salvo_example)
62//! + [Tonic Example](https://github.com/SeaQL/sea-orm/tree/master/examples/tonic_example)
63//! + [Seaography Example (Bakery)](https://github.com/SeaQL/sea-orm/tree/master/examples/seaography_example) / [Seaography Example (Sakila)](https://github.com/SeaQL/seaography/tree/main/examples/sqlite)
64//!
65//! If you want a simple, clean example that fits in a single file that demonstrates the best of SeaORM, you can try:
66//! + [Quickstart](https://github.com/SeaQL/sea-orm/blob/master/examples/quickstart/src/main.rs)
67//!
68//! Let's have a quick walk through of the unique features of SeaORM.
69//!
70//! ## Expressive Entity format
71//! You don't have to write this by hand! Entity files can be generated from an existing database using `sea-orm-cli`,
72//! following is generated with `--entity-format dense` *(new in 2.0)*.
73//! ```
74//! # #[cfg(feature = "macros")]
75//! # mod entities {
76//! # mod profile {
77//! # use sea_orm::entity::prelude::*;
78//! # #[sea_orm::model]
79//! # #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
80//! # #[sea_orm(table_name = "profile")]
81//! # pub struct Model {
82//! #     #[sea_orm(primary_key)]
83//! #     pub id: i32,
84//! #     pub picture: String,
85//! #     #[sea_orm(unique)]
86//! #     pub user_id: i32,
87//! #     #[sea_orm(belongs_to, from = "user_id", to = "id")]
88//! #     pub user: BelongsTo<super::user::Entity>,
89//! # }
90//! # impl ActiveModelBehavior for ActiveModel {}
91//! # }
92//! # mod tag {
93//! # use sea_orm::entity::prelude::*;
94//! # #[sea_orm::model]
95//! # #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
96//! # #[sea_orm(table_name = "post")]
97//! # pub struct Model {
98//! #     #[sea_orm(primary_key)]
99//! #     pub id: i32,
100//! #     #[sea_orm(has_many, via = "post_tag")]
101//! #     pub tags: HasMany<super::tag::Entity>,
102//! # }
103//! # impl ActiveModelBehavior for ActiveModel {}
104//! # }
105//! # mod post_tag {
106//! # use sea_orm::entity::prelude::*;
107//! # #[sea_orm::model]
108//! # #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
109//! # #[sea_orm(table_name = "post_tag")]
110//! # pub struct Model {
111//! #     #[sea_orm(primary_key, auto_increment = false)]
112//! #     pub post_id: i32,
113//! #     #[sea_orm(primary_key, auto_increment = false)]
114//! #     pub tag_id: i32,
115//! #     #[sea_orm(belongs_to, from = "post_id", to = "id")]
116//! #     pub post: BelongsTo<super::post::Entity>,
117//! #     #[sea_orm(belongs_to, from = "tag_id", to = "id")]
118//! #     pub tag: BelongsTo<super::tag::Entity>,
119//! # }
120//! # impl ActiveModelBehavior for ActiveModel {}
121//! # }
122//! mod user {
123//!     use sea_orm::entity::prelude::*;
124//!
125//!     #[sea_orm::model]
126//!     #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
127//!     #[sea_orm(table_name = "user")]
128//!     pub struct Model {
129//!         #[sea_orm(primary_key)]
130//!         pub id: i32,
131//!         pub name: String,
132//!         #[sea_orm(unique)]
133//!         pub email: String,
134//!         #[sea_orm(has_one)]
135//!         pub profile: HasOne<super::profile::Entity>,
136//!         #[sea_orm(has_many)]
137//!         pub posts: HasMany<super::post::Entity>,
138//!     }
139//! # impl ActiveModelBehavior for ActiveModel {}
140//! }
141//! mod post {
142//!     use sea_orm::entity::prelude::*;
143//!
144//!     #[sea_orm::model]
145//!     #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
146//!     #[sea_orm(table_name = "post")]
147//!     pub struct Model {
148//!         #[sea_orm(primary_key)]
149//!         pub id: i32,
150//!         pub user_id: i32,
151//!         pub title: String,
152//!         #[sea_orm(belongs_to, from = "user_id", to = "id")]
153//!         pub author: BelongsTo<super::user::Entity>,
154//!         #[sea_orm(has_many, via = "post_tag")] // M-N relation with junction
155//!         pub tags: HasMany<super::tag::Entity>,
156//!     }
157//! # impl ActiveModelBehavior for ActiveModel {}
158//! }
159//! # }
160//! ```
161//!
162//! ## Smart Entity Loader
163//! The Entity Loader intelligently uses join for 1-1 and data loader for 1-N relations,
164//! eliminating the N+1 problem even when performing nested queries.
165//! ```
166//! # use sea_orm::{DbConn, DbErr, prelude::*, entity::*, query::*, tests_cfg::*};
167//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
168//! // join paths:
169//! // user -> profile
170//! // user -> post
171//! //         post -> post_tag -> tag
172//! let smart_user = user::Entity::load()
173//!     .filter_by_id(42) // shorthand for .filter(user::COLUMN.id.eq(42))
174//!     .with(profile::Entity) // 1-1 uses join
175//!     .with((post::Entity, tag::Entity)) // 1-N uses data loader
176//!     .one(db)
177//!     .await?
178//!     .unwrap();
179//!
180//! // 3 queries are executed under the hood:
181//! // 1. SELECT FROM user JOIN profile WHERE id = $
182//! // 2. SELECT FROM post WHERE user_id IN (..)
183//! // 3. SELECT FROM tag JOIN post_tag WHERE post_id IN (..)
184//!
185//! smart_user
186//!     == user::ModelEx {
187//!         id: 42,
188//!         name: "Bob".into(),
189//!         email: "bob@sea-ql.org".into(),
190//!         profile: HasOne::loaded(Some(profile::ModelEx {
191//! #           id: 1,
192//!             picture: "image.jpg".into(),
193//! #           user_id: 1,
194//! #           user: BelongsTo::Unloaded,
195//!         })),
196//!         posts: HasMany::Loaded(vec![post::ModelEx {
197//! #           id: 2,
198//! #           user_id: 1,
199//!             title: "Nice weather".into(),
200//! #           author: BelongsTo::Unloaded,
201//! #           comments: HasMany::Unloaded,
202//!             tags: HasMany::Loaded(vec![tag::ModelEx {
203//! #               id: 3,
204//!                 tag: "sunny".into(),
205//! #               posts: HasMany::Unloaded,
206//!             }]),
207//!         }]),
208//!     };
209//! # Ok(())
210//! # }
211//! ```
212//!
213//! ## ActiveModel: nested persistence made simple
214//! Persist an entire object graph: user, profile (1-1), posts (1-N), and tags (M-N)
215//! in a single operation using a fluent builder API. SeaORM automatically determines
216//! the dependencies and inserts or deletes objects in the correct order.
217//! This requires the SeaORM 2.0 dense entity format.
218//!
219//! ```
220//! # use sea_orm::{DbConn, DbErr, entity::*, query::*, tests_cfg::*};
221//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
222//! // this creates the nested object as shown above:
223//! let user = user::ActiveModel::builder()
224//!     .set_name("Bob")
225//!     .set_email("bob@sea-ql.org")
226//!     .set_profile(profile::ActiveModel::builder().set_picture("image.jpg"))
227//!     .add_post(
228//!         post::ActiveModel::builder()
229//!             .set_title("Nice weather")
230//!             .add_tag(tag::ActiveModel::builder().set_tag("sunny")),
231//!     )
232//!     .save(db)
233//!     .await?;
234//! # Ok(())
235//! # }
236//! ```
237//!
238//! ## Schema first or Entity first? Your choice
239//!
240//! SeaORM provides a powerful migration system that lets you create tables, modify schemas, and seed data with ease.
241//!
242//! With SeaORM 2.0, you also get a first-class [Entity First Workflow](https://www.sea-ql.org/blog/2025-10-30-sea-orm-2.0/):
243//! simply define new entities or add columns to existing ones,
244//! and SeaORM will automatically detect the changes and create the new tables, columns, unique keys, and foreign keys.
245//!
246//! ```ignore
247//! // SeaORM resolves foreign key dependencies and creates the tables in topological order.
248//! // Requires the `entity-registry` and `schema-sync` feature flags.
249//! db.get_schema_registry("my_crate::entity::*").sync(db).await;
250//! ```
251//!
252//! ## Ergonomic Raw SQL
253//!
254//! Let SeaORM handle 95% of your transactional queries.
255//! For the remaining cases that are too complex to express,
256//! SeaORM still offers convenient support for writing raw SQL.
257//! ```
258//! # use sea_orm::{DbErr, DbConn};
259//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
260//! # use sea_orm::{entity::*, query::*, tests_cfg::*, raw_sql};
261//! # struct Item<'a> { name: &'a str }
262//! let user = Item { name: "Bob" }; // nested parameter access
263//! let ids = [2, 3, 4]; // expanded by the `..` operator
264//!
265//! let user: Option<user::Model> = user::Entity::find()
266//!     .from_raw_sql(raw_sql!(
267//!         Sqlite,
268//!         r#"SELECT "id", "name" FROM "user"
269//!            WHERE "name" LIKE {user.name}
270//!            AND "id" in ({..ids})
271//!         "#
272//!     ))
273//!     .one(db)
274//!     .await?;
275//! # Ok(())
276//! # }
277//! ```
278//!
279//! ## Synchronous Support
280//!
281//! [`sea-orm-sync`](https://crates.io/crates/sea-orm-sync) provides the full SeaORM API without requiring an async runtime, making it ideal for lightweight CLI programs with SQLite.
282//!
283//! See the [quickstart example](https://github.com/SeaQL/sea-orm/blob/master/sea-orm-sync/examples/quickstart/src/main.rs) for usage.
284//!
285//! ## Basics
286//!
287//! ### Select
288//! SeaORM models 1-N and M-N relationships at the Entity level,
289//! letting you traverse many-to-many links through a junction table in a single call.
290//! ```
291//! # use sea_orm::{DbConn, DbErr, entity::*, query::*, tests_cfg::*};
292//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
293//! // find all models
294//! let cakes: Vec<cake::Model> = Cake::find().all(db).await?;
295//!
296//! // find and filter
297//! let chocolate: Vec<cake::Model> = Cake::find()
298//!     .filter(Cake::COLUMN.name.contains("chocolate"))
299//!     .all(db)
300//!     .await?;
301//!
302//! // find one model
303//! let cheese: Option<cake::Model> = Cake::find_by_id(1).one(db).await?;
304//! let cheese: cake::Model = cheese.unwrap();
305//!
306//! // find related models (lazy)
307//! let fruit: Option<fruit::Model> = cheese.find_related(Fruit).one(db).await?;
308//!
309//! // find related models (eager): for 1-1 relations
310//! let cake_with_fruit: Vec<(cake::Model, Option<fruit::Model>)> =
311//!     Cake::find().find_also_related(Fruit).all(db).await?;
312//!
313//! // find related models (eager): works for both 1-N and M-N relations
314//! let cake_with_fillings: Vec<(cake::Model, Vec<filling::Model>)> = Cake::find()
315//!     .find_with_related(Filling) // for M-N relations, two joins are performed
316//!     .all(db) // rows are automatically consolidated by left entity
317//!     .await?;
318//! # Ok(())
319//! # }
320//! ```
321//! ### Nested Select
322//!
323//! Partial models prevent overfetching by letting you querying only the fields
324//! you need; it also makes writing deeply nested relational queries simple.
325//! ```
326//! # use sea_orm::{DbConn, DbErr, entity::*, query::*, tests_cfg::*};
327//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
328//! use sea_orm::DerivePartialModel;
329//!
330//! #[derive(DerivePartialModel)]
331//! #[sea_orm(entity = "cake::Entity")]
332//! struct CakeWithFruit {
333//!     id: i32,
334//!     name: String,
335//!     #[sea_orm(nested)]
336//!     fruit: Option<fruit::Model>, // this can be a regular or another partial model
337//! }
338//!
339//! let cakes: Vec<CakeWithFruit> = Cake::find()
340//!     .left_join(fruit::Entity) // no need to specify join condition
341//!     .into_partial_model() // only the columns in the partial model will be selected
342//!     .all(db)
343//!     .await?;
344//! # Ok(())
345//! # }
346//! ```
347//!
348//! ### Insert
349//! SeaORM's ActiveModel lets you work directly with Rust data structures and
350//! persist them through a simple API.
351//! It's easy to insert large batches of rows from different data sources.
352//! ```
353//! # use sea_orm::{DbConn, DbErr, entity::*, query::*, tests_cfg::*};
354//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
355//! let apple = fruit::ActiveModel {
356//!     name: Set("Apple".to_owned()),
357//!     ..Default::default() // no need to set primary key
358//! };
359//!
360//! let pear = fruit::ActiveModel {
361//!     name: Set("Pear".to_owned()),
362//!     ..Default::default()
363//! };
364//!
365//! // insert one: Active Record style
366//! let apple = apple.insert(db).await?;
367//! apple.id == 1;
368//! # let apple = fruit::ActiveModel {
369//! #     name: Set("Apple".to_owned()),
370//! #     ..Default::default() // no need to set primary key
371//! # };
372//!
373//! // insert one: repository style
374//! let result = Fruit::insert(apple).exec(db).await?;
375//! result.last_insert_id == 1;
376//! # let apple = fruit::ActiveModel {
377//! #     name: Set("Apple".to_owned()),
378//! #     ..Default::default() // no need to set primary key
379//! # };
380//!
381//! // insert many returning last insert id
382//! let result = Fruit::insert_many([apple, pear]).exec(db).await?;
383//! result.last_insert_id == Some(2);
384//! # Ok(())
385//! # }
386//! ```
387//!
388//! ### Insert (advanced)
389//! You can take advantage of database specific features to perform upsert and idempotent insert.
390//! ```
391//! # use sea_orm::{DbConn, TryInsertResult, DbErr, entity::*, query::*, tests_cfg::*};
392//! # async fn function_1(db: &DbConn) -> Result<(), DbErr> {
393//! # let apple = fruit::ActiveModel {
394//! #     name: Set("Apple".to_owned()),
395//! #     ..Default::default() // no need to set primary key
396//! # };
397//! # let pear = fruit::ActiveModel {
398//! #     name: Set("Pear".to_owned()),
399//! #     ..Default::default()
400//! # };
401//! // insert many with returning (if supported by database)
402//! let models: Vec<fruit::Model> = Fruit::insert_many([apple, pear])
403//!     .exec_with_returning(db)
404//!     .await?;
405//! models[0]
406//!     == fruit::Model {
407//!         id: 1, // database assigned value
408//!         name: "Apple".to_owned(),
409//!         cake_id: None,
410//!     };
411//! # Ok(())
412//! # }
413//!
414//! # async fn function_2(db: &DbConn) -> Result<(), DbErr> {
415//! # let apple = fruit::ActiveModel {
416//! #     name: Set("Apple".to_owned()),
417//! #     ..Default::default() // no need to set primary key
418//! # };
419//! # let pear = fruit::ActiveModel {
420//! #     name: Set("Pear".to_owned()),
421//! #     ..Default::default()
422//! # };
423//! // insert with ON CONFLICT on primary key do nothing, with MySQL specific polyfill
424//! let result = Fruit::insert_many([apple, pear])
425//!     .on_conflict_do_nothing()
426//!     .exec(db)
427//!     .await?;
428//!
429//! matches!(result, TryInsertResult::Conflicted);
430//! # Ok(())
431//! # }
432//! ```
433//!
434//! ### Update
435//! ActiveModel avoids race conditions by updating only the fields you've changed,
436//! never overwriting untouched columns.
437//! You can also craft complex bulk update queries with a fluent query building API.
438//! ```
439//! # use sea_orm::{DbConn, DbErr, entity::*, query::*, tests_cfg::*};
440//! use sea_orm::sea_query::{Expr, Value};
441//!
442//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
443//! let pear: Option<fruit::Model> = Fruit::find_by_id(1).one(db).await?;
444//! let mut pear: fruit::ActiveModel = pear.unwrap().into();
445//!
446//! pear.name = Set("Sweet pear".to_owned()); // update value of a single field
447//!
448//! // update one: only changed columns will be updated
449//! let pear: fruit::Model = pear.update(db).await?;
450//!
451//! // update many: UPDATE "fruit" SET "cake_id" = "cake_id" + 2
452//! //               WHERE "fruit"."name" LIKE '%Apple%'
453//! Fruit::update_many()
454//!     .col_expr(fruit::COLUMN.cake_id, fruit::COLUMN.cake_id.add(2))
455//!     .filter(fruit::COLUMN.name.contains("Apple"))
456//!     .exec(db)
457//!     .await?;
458//! # Ok(())
459//! # }
460//! ```
461//! ### Save
462//! You can perform "insert or update" operation with ActiveModel, making it easy to compose transactional operations.
463//! ```
464//! # use sea_orm::{DbConn, DbErr, entity::*, query::*, tests_cfg::*};
465//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
466//! let banana = fruit::ActiveModel {
467//!     id: NotSet,
468//!     name: Set("Banana".to_owned()),
469//!     ..Default::default()
470//! };
471//!
472//! // create, because primary key `id` is `NotSet`
473//! let mut banana = banana.save(db).await?;
474//!
475//! banana.id == Unchanged(2);
476//! banana.name = Set("Banana Mongo".to_owned());
477//!
478//! // update, because primary key `id` is present
479//! let banana = banana.save(db).await?;
480//! # Ok(())
481//! # }
482//! ```
483//! ### Delete
484//! The same ActiveModel API consistent with insert and update.
485//! ```
486//! # use sea_orm::{DbConn, DbErr, entity::*, query::*, tests_cfg::*};
487//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
488//! // delete one: Active Record style
489//! let orange: Option<fruit::Model> = Fruit::find_by_id(1).one(db).await?;
490//! let orange: fruit::Model = orange.unwrap();
491//! orange.delete(db).await?;
492//!
493//! // delete one: repository style
494//! let orange = fruit::ActiveModel {
495//!     id: Set(2),
496//!     ..Default::default()
497//! };
498//! fruit::Entity::delete(orange).exec(db).await?;
499//!
500//! // delete many: DELETE FROM "fruit" WHERE "fruit"."name" LIKE '%Orange%'
501//! fruit::Entity::delete_many()
502//!     .filter(fruit::COLUMN.name.contains("Orange"))
503//!     .exec(db)
504//!     .await?;
505//!
506//! # Ok(())
507//! # }
508//! ```
509//! ### Raw SQL Query
510//! The `raw_sql!` macro is like the `format!` macro but without the risk of SQL injection.
511//! It supports nested parameter interpolation, array and tuple expansion, and even repeating group,
512//! offering great flexibility in crafting complex queries.
513//!
514//! ```
515//! # use sea_orm::{DbErr, DbConn};
516//! # async fn functio(db: &DbConn) -> Result<(), DbErr> {
517//! # use sea_orm::{query::*, FromQueryResult, raw_sql};
518//! #[derive(FromQueryResult)]
519//! struct CakeWithBakery {
520//!     name: String,
521//!     #[sea_orm(nested)]
522//!     bakery: Option<Bakery>,
523//! }
524//!
525//! #[derive(FromQueryResult)]
526//! struct Bakery {
527//!     #[sea_orm(alias = "bakery_name")]
528//!     name: String,
529//! }
530//!
531//! let cake_ids = [2, 3, 4]; // expanded by the `..` operator
532//!
533//! // can use many APIs with raw SQL, including nested select
534//! let cake: Option<CakeWithBakery> = CakeWithBakery::find_by_statement(raw_sql!(
535//!     Sqlite,
536//!     r#"SELECT "cake"."name", "bakery"."name" AS "bakery_name"
537//!        FROM "cake"
538//!        LEFT JOIN "bakery" ON "cake"."bakery_id" = "bakery"."id"
539//!        WHERE "cake"."id" IN ({..cake_ids})"#
540//! ))
541//! .one(db)
542//! .await?;
543//! # Ok(())
544//! # }
545//! ```
546//!
547//! ## 🧭 Seaography: instant GraphQL API
548//!
549//! [Seaography](https://github.com/SeaQL/seaography) is a GraphQL framework built for SeaORM.
550//! Seaography allows you to build GraphQL resolvers quickly.
551//! With just a few commands, you can launch a fullly-featured GraphQL server from SeaORM entities,
552//! complete with filter, pagination, relational queries and mutations!
553//!
554//! Look at the [Seaography Example](https://github.com/SeaQL/sea-orm/tree/master/examples/seaography_example) to learn more.
555//!
556//! <img src="https://raw.githubusercontent.com/SeaQL/sea-orm/master/examples/seaography_example/Seaography%20example.png"/>
557//!
558//! ## πŸ–₯️ SeaORM Pro: Professional Admin Panel
559//!
560//! [SeaORM Pro](https://github.com/SeaQL/sea-orm-pro/) is an admin panel solution allowing you to quickly and easily launch an admin panel for your application - frontend development skills not required, but certainly nice to have!
561//!
562//! SeaORM Pro has been updated to support the latest features in SeaORM 2.0.
563//!
564//! Features:
565//!
566//! + Full CRUD
567//! + Built on React + GraphQL
568//! + Built-in GraphQL resolver
569//! + Customize the UI with TOML config
570//! + Role Based Access Control *(new in 2.0)*
571//!
572//! Read the [Getting Started](https://www.sea-ql.org/sea-orm-pro/docs/install-and-config/getting-started/) guide to learn more.
573//!
574//! ![](https://raw.githubusercontent.com/SeaQL/sea-orm/refs/heads/master/docs/sea-orm-pro-dark.png#gh-dark-mode-only)
575//! ![](https://raw.githubusercontent.com/SeaQL/sea-orm/refs/heads/master/docs/sea-orm-pro-light.png#gh-light-mode-only)
576//!
577//! ## SQL Server Support
578//!
579//! [SQL Server for SeaORM](https://www.sea-ql.org/SeaORM-X/) offers the same SeaORM API for MSSQL. We ported all test cases and examples, complemented by MSSQL specific documentation. If you are building enterprise software, you can [request commercial access](https://forms.office.com/r/1MuRPJmYBR). It is currently based on SeaORM 1.0, but we will offer free upgrade to existing users when SeaORM 2.0 is finalized.
580//!
581//! ## Releases
582//!
583//! SeaORM 2.0 has reached its release candidate phase. We'd love for you to try it out and help shape the final release by [sharing your feedback](https://github.com/SeaQL/sea-orm/discussions/).
584//!
585//! + [Change Log](https://github.com/SeaQL/sea-orm/tree/master/CHANGELOG.md)
586//!
587//! SeaORM 2.0 is shaping up to be our most significant release yet - with a few breaking changes, plenty of enhancements, and a clear focus on developer experience.
588//!
589//! + [A Sneak Peek at SeaORM 2.0](https://www.sea-ql.org/blog/2025-09-16-sea-orm-2.0/)
590//! + [SeaORM 2.0: A closer look](https://www.sea-ql.org/blog/2025-09-24-sea-orm-2.0/)
591//! + [Role Based Access Control in SeaORM 2.0](https://www.sea-ql.org/blog/2025-09-30-sea-orm-rbac/)
592//! + [Seaography 2.0: A Powerful and Extensible GraphQL Framework](https://www.sea-ql.org/blog/2025-10-08-seaography/)
593//! + [SeaORM 2.0: New Entity Format](https://www.sea-ql.org/blog/2025-10-20-sea-orm-2.0/)
594//! + [SeaORM 2.0: Entity First Workflow](https://www.sea-ql.org/blog/2025-10-30-sea-orm-2.0/)
595//! + [SeaORM 2.0: Strongly-Typed Column](https://www.sea-ql.org/blog/2025-11-11-sea-orm-2.0/)
596//! + [What's new in SeaORM Pro 2.0](https://www.sea-ql.org/blog/2025-11-21-whats-new-in-seaormpro-2.0/)
597//! + [SeaORM 2.0: Nested ActiveModel](https://www.sea-ql.org/blog/2025-11-25-sea-orm-2.0/)
598//! + [A walk-through of SeaORM 2.0](https://www.sea-ql.org/blog/2025-12-05-sea-orm-2.0/)
599//! + [How we made SeaORM synchronous](https://www.sea-ql.org/blog/2025-12-12-sea-orm-2.0/)
600//! + [SeaORM 2.0 Migration Guide](https://www.sea-ql.org/blog/2026-01-12-sea-orm-2.0/)
601//! + [SeaORM now supports Arrow & Parquet](https://www.sea-ql.org/blog/2026-02-22-sea-orm-arrow/)
602//! + [SeaORM 2.0 with SQL Server Support](https://www.sea-ql.org/blog/2026-02-25-sea-orm-x/)
603//!
604//! If you make extensive use of SeaQuery, we recommend checking out our blog post on SeaQuery 1.0 release:
605//!
606//! + [The road to SeaQuery 1.0](https://www.sea-ql.org/blog/2025-08-30-sea-query-1.0/)
607//!
608//! ## License
609//!
610//! Licensed under either of
611//!
612//! -   Apache License, Version 2.0
613//!     ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
614//! -   MIT license
615//!     ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
616//!
617//! at your option.
618//!
619//! ## Contribution
620//!
621//! Unless you explicitly state otherwise, any contribution intentionally submitted
622//! for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
623//! dual licensed as above, without any additional terms or conditions.
624//!
625//! We invite you to participate, contribute and together help build Rust's future.
626//!
627//! A big shout out to our contributors!
628//!
629//! [![Contributors](https://opencollective.com/sea-orm/contributors.svg?width=1000&button=false)](https://github.com/SeaQL/sea-orm/graphs/contributors)
630//!
631//! ## Who's using SeaORM?
632//!
633//! Here is a short list of awesome open source software built with SeaORM. Feel free to [submit yours](https://github.com/SeaQL/sea-orm/blob/master/COMMUNITY.md#built-with-seaorm)!
634//!
635//! | Project | GitHub | Tagline |
636//! |---------|--------|---------|
637//! | [Zed](https://github.com/zed-industries/zed) | ![GitHub stars](https://img.shields.io/github/stars/zed-industries/zed.svg?style=social) | A high-performance, multiplayer code editor |
638//! | [Servo](https://github.com/servo/servo) | ![GitHub stars](https://img.shields.io/github/stars/servo/servo.svg?style=social) | The Servo Parallel Browser Engine Project |
639//! | [OpenObserve](https://github.com/openobserve/openobserve) | ![GitHub stars](https://img.shields.io/github/stars/openobserve/openobserve.svg?style=social) | Open-source observability platform |
640//! | [RisingWave](https://github.com/risingwavelabs/risingwave) | ![GitHub stars](https://img.shields.io/github/stars/risingwavelabs/risingwave.svg?style=social) | Stream processing and management platform |
641//! | [Warpgate](https://github.com/warp-tech/warpgate) | ![GitHub stars](https://img.shields.io/github/stars/warp-tech/warpgate.svg?style=social) | Smart SSH bastion that works with any SSH client |
642//! | [LLDAP](https://github.com/nitnelave/lldap) | ![GitHub stars](https://img.shields.io/github/stars/nitnelave/lldap.svg?style=social) | A light LDAP server for user management |
643//! | [Svix](https://github.com/svix/svix-webhooks) | ![GitHub stars](https://img.shields.io/github/stars/svix/svix-webhooks.svg?style=social) | The enterprise ready webhooks service |
644//! | [Ryot](https://github.com/IgnisDa/ryot) | ![GitHub stars](https://img.shields.io/github/stars/ignisda/ryot.svg?style=social) | The only self hosted tracker you will ever need |
645//! | [OctoBase](https://github.com/toeverything/OctoBase) | ![GitHub stars](https://img.shields.io/github/stars/toeverything/OctoBase.svg?style=social) | A light-weight, scalable, offline collaborative data backend |
646//! | [System Initiative](https://github.com/systeminit/si) | ![GitHub stars](https://img.shields.io/github/stars/systeminit/si.svg?style=social) | DevOps Automation Platform |
647//!
648//! ## Sponsorship
649//!
650//! [SeaQL.org](https://www.sea-ql.org/) is an independent open-source organization run by passionate developers.
651//! If you feel generous, a small donation via [GitHub Sponsor](https://github.com/sponsors/SeaQL) will be greatly appreciated, and goes a long way towards sustaining the organization.
652//!
653//! ### Gold Sponsors
654//!
655//! <table><tr>
656//! <td><a href="https://qdx.co/">
657//!   <img src="https://www.sea-ql.org/static/sponsors/QDX.svg" width="138"/>
658//! </a></td>
659//! </tr></table>
660//!
661//! [QDX](https://qdx.co/) pioneers quantum dynamics-powered drug discovery, leveraging AI and supercomputing to accelerate molecular modeling.
662//! We're immensely grateful to QDX for sponsoring the development of SeaORM, the SQL toolkit that powers their data intensive applications.
663//!
664//! ### Silver Sponsors
665//!
666//! We're grateful to our silver sponsors: Digital Ocean, for sponsoring our servers. And JetBrains, for sponsoring our IDE.
667//!
668//! <table><tr>
669//! <td><a href="https://www.digitalocean.com/">
670//!   <img src="https://www.sea-ql.org/static/sponsors/DigitalOcean.svg" width="125">
671//! </a></td>
672//!
673//! <td><a href="https://www.jetbrains.com/">
674//!   <img src="https://www.sea-ql.org/static/sponsors/JetBrains.svg" width="125">
675//! </a></td>
676//! </tr></table>
677//!
678//! ## Mascot
679//!
680//! A friend of Ferris, Terres the hermit crab is the official mascot of SeaORM. His hobby is collecting shells.
681//!
682//! <img alt="Terres" src="https://www.sea-ql.org/SeaORM/img/Terres.png" width="400"/>
683//!
684//! ## πŸ¦€ Rustacean Sticker Pack
685//! 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.
686//!
687//! Sticker Pack Contents:
688//!
689//! + Logo of SeaQL projects: SeaQL, SeaORM, SeaQuery, Seaography
690//! + Mascots: Ferris the Crab x 3, Terres the Hermit Crab
691//! + The Rustacean wordmark
692//!
693//! [Support SeaQL and get a Sticker Pack!](https://www.sea-ql.org/sticker-pack/) All proceeds contributes directly to the ongoing development of SeaQL projects.
694//!
695//! <a href="https://www.sea-ql.org/sticker-pack/"><img alt="Rustacean Sticker Pack by SeaQL" src="https://www.sea-ql.org/static/sticker-pack-1s.jpg" width="600"/></a>
696#![doc(
697    html_logo_url = "https://raw.githubusercontent.com/SeaQL/sea-query/master/docs/SeaQL icon dark.png"
698)]
699
700mod database;
701mod docs;
702mod driver;
703pub mod dynamic;
704pub mod entity;
705/// Error types returned by SeaORM operations.
706pub mod error;
707mod executor;
708/// Per-query metric collection hooks.
709pub mod metric;
710pub mod query;
711#[cfg(feature = "rbac")]
712#[cfg_attr(docsrs, doc(cfg(feature = "rbac")))]
713pub mod rbac;
714pub mod schema;
715/// Helpers for working with [`sea_query::Value`].
716pub mod value;
717
718#[doc(hidden)]
719#[cfg(all(feature = "macros", feature = "tests-cfg"))]
720pub mod tests_cfg;
721mod util;
722
723pub use database::*;
724#[allow(unused_imports)]
725pub use driver::*;
726pub use entity::*;
727pub use error::*;
728pub use executor::*;
729pub use query::*;
730pub use schema::*;
731
732#[cfg(feature = "macros")]
733pub use sea_orm_macros::{
734    DeriveActiveEnum, DeriveActiveModel, DeriveActiveModelBehavior, DeriveActiveModelEx,
735    DeriveArrowSchema, DeriveColumn, DeriveDisplay, DeriveEntity, DeriveEntityModel, DeriveIden,
736    DeriveIntoActiveModel, DeriveMigrationName, DeriveModel, DeriveModelEx, DerivePartialModel,
737    DerivePrimaryKey, DeriveRelatedEntity, DeriveRelation, DeriveValueType, FromJsonQueryResult,
738    FromQueryResult, raw_sql, sea_orm_compact_model as compact_model, sea_orm_model as model,
739};
740
741pub use sea_query;
742pub use sea_query::Iden;
743
744pub use sea_orm_macros::EnumIter;
745pub use strum;
746
747#[cfg(feature = "with-arrow")]
748pub use sea_orm_arrow::arrow;
749
750#[cfg(feature = "sqlx-dep")]
751pub use sqlx;