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 src="https://www.sea-ql.org/SeaORM/img/SeaORM banner.png"/>
14//!
15//! <h1>SeaORM</h1>
16//!
17//! <h3>π An async & dynamic ORM for Rust</h3>
18//!
19//! [](https://crates.io/crates/sea-orm)
20//! [](https://docs.rs/sea-orm)
21//! [](https://github.com/SeaQL/sea-orm/actions/workflows/rust.yml)
22//!
23//! </div>
24//!
25//! # SeaORM
26//!
27//! [δΈζζζ‘£](https://github.com/SeaQL/sea-orm/blob/1.1.x/README-zh.md)
28//!
29//! #### SeaORM is a relational ORM to help you build web services in Rust with the familiarity of dynamic languages.
30//!
31//! [](https://github.com/SeaQL/sea-orm/stargazers/)
32//! If you like what we do, consider starring, sharing and contributing!
33//!
34//! Please help us with maintaining SeaORM by completing the [SeaQL Community Survey 2025](https://www.sea-ql.org/community-survey/)!
35//!
36//! [](https://discord.com/invite/uCPdDXzbdv)
37//! Join our Discord server to chat with other members of the SeaQL community!
38//!
39//! ## Getting Started
40//!
41//! + [Documentation](https://www.sea-ql.org/SeaORM)
42//! + [Tutorial](https://www.sea-ql.org/sea-orm-tutorial)
43//! + [Cookbook](https://www.sea-ql.org/sea-orm-cookbook)
44//!
45//! Integration examples:
46//!
47//! + [Actix v4 Example](https://github.com/SeaQL/sea-orm/tree/master/examples/actix_example)
48//! + [Axum Example](https://github.com/SeaQL/sea-orm/tree/master/examples/axum_example)
49//! + [GraphQL Example](https://github.com/SeaQL/sea-orm/tree/master/examples/graphql_example)
50//! + [jsonrpsee Example](https://github.com/SeaQL/sea-orm/tree/master/examples/jsonrpsee_example)
51//! + [Loco TODO 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)
52//! + [Poem Example](https://github.com/SeaQL/sea-orm/tree/master/examples/poem_example)
53//! + [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)
54//! + [Salvo Example](https://github.com/SeaQL/sea-orm/tree/master/examples/salvo_example)
55//! + [Tonic Example](https://github.com/SeaQL/sea-orm/tree/master/examples/tonic_example)
56//! + [Seaography Example](https://github.com/SeaQL/sea-orm/tree/master/examples/seaography_example)
57//!
58//! ## Features
59//!
60//! 1. Async
61//!
62//! Relying on [SQLx](https://github.com/launchbadge/sqlx), SeaORM is a new library with async support from day 1.
63//!
64//! 2. Dynamic
65//!
66//! Built upon [SeaQuery](https://github.com/SeaQL/sea-query), SeaORM allows you to build complex dynamic queries.
67//!
68//! 3. Service Oriented
69//!
70//! Quickly build services that join, filter, sort and paginate data in REST, GraphQL and gRPC APIs.
71//!
72//! 4. Production Ready
73//!
74//! SeaORM is feature-rich, well-tested and used in production by companies and startups.
75//!
76//! ## A quick taste of SeaORM
77//!
78//! ### Entity
79//! ```
80//! # #[cfg(feature = "macros")]
81//! # mod entities {
82//! # mod fruit {
83//! # use sea_orm::entity::prelude::*;
84//! # #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
85//! # #[sea_orm(table_name = "fruit")]
86//! # pub struct Model {
87//! # #[sea_orm(primary_key)]
88//! # pub id: i32,
89//! # pub name: String,
90//! # pub cake_id: Option<i32>,
91//! # }
92//! # #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
93//! # pub enum Relation {
94//! # #[sea_orm(
95//! # belongs_to = "super::cake::Entity",
96//! # from = "Column::CakeId",
97//! # to = "super::cake::Column::Id"
98//! # )]
99//! # Cake,
100//! # }
101//! # impl Related<super::cake::Entity> for Entity {
102//! # fn to() -> RelationDef {
103//! # Relation::Cake.def()
104//! # }
105//! # }
106//! # impl ActiveModelBehavior for ActiveModel {}
107//! # }
108//! # mod cake {
109//! use sea_orm::entity::prelude::*;
110//!
111//! #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
112//! #[sea_orm(table_name = "cake")]
113//! pub struct Model {
114//! #[sea_orm(primary_key)]
115//! pub id: i32,
116//! pub name: String,
117//! }
118//!
119//! #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
120//! pub enum Relation {
121//! #[sea_orm(has_many = "super::fruit::Entity")]
122//! Fruit,
123//! }
124//!
125//! impl Related<super::fruit::Entity> for Entity {
126//! fn to() -> RelationDef {
127//! Relation::Fruit.def()
128//! }
129//! }
130//! # impl ActiveModelBehavior for ActiveModel {}
131//! # }
132//! # }
133//! ```
134//!
135//! ### Select
136//! ```
137//! # use sea_orm::{DbConn, error::*, entity::*, query::*, tests_cfg::*};
138//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
139//! // find all models
140//! let cakes: Vec<cake::Model> = Cake::find().all(db).await?;
141//!
142//! // find and filter
143//! let chocolate: Vec<cake::Model> = Cake::find()
144//! .filter(cake::Column::Name.contains("chocolate"))
145//! .all(db)
146//! .await?;
147//!
148//! // find one model
149//! let cheese: Option<cake::Model> = Cake::find_by_id(1).one(db).await?;
150//! let cheese: cake::Model = cheese.unwrap();
151//!
152//! // find related models (lazy)
153//! let fruits: Vec<fruit::Model> = cheese.find_related(Fruit).all(db).await?;
154//!
155//! // find related models (eager)
156//! let cake_with_fruits: Vec<(cake::Model, Vec<fruit::Model>)> =
157//! Cake::find().find_with_related(Fruit).all(db).await?;
158//!
159//! # Ok(())
160//! # }
161//! ```
162//!
163//! ### Nested Select
164//!
165//! ```
166//! # use sea_orm::{DbConn, error::*, entity::*, query::*, tests_cfg::*};
167//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
168//! use sea_orm::DerivePartialModel;
169//!
170//! #[derive(DerivePartialModel)]
171//! #[sea_orm(entity = "cake::Entity", from_query_result)]
172//! struct CakeWithFruit {
173//! id: i32,
174//! name: String,
175//! #[sea_orm(nested)]
176//! fruit: Option<Fruit>,
177//! }
178//!
179//! #[derive(DerivePartialModel)]
180//! #[sea_orm(entity = "fruit::Entity", from_query_result)]
181//! struct Fruit {
182//! id: i32,
183//! name: String,
184//! }
185//!
186//! let cakes: Vec<CakeWithFruit> = cake::Entity::find()
187//! .left_join(fruit::Entity)
188//! .into_partial_model()
189//! .all(db)
190//! .await?;
191//! # Ok(())
192//! # }
193//! ```
194//! ### Insert
195//! ```
196//! # use sea_orm::{DbConn, error::*, entity::*, query::*, tests_cfg::*};
197//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
198//! let apple = fruit::ActiveModel {
199//! name: Set("Apple".to_owned()),
200//! ..Default::default() // no need to set primary key
201//! };
202//!
203//! let pear = fruit::ActiveModel {
204//! name: Set("Pear".to_owned()),
205//! ..Default::default()
206//! };
207//!
208//! // insert one
209//! let pear = pear.insert(db).await?;
210//! # Ok(())
211//! # }
212//! # async fn function2(db: &DbConn) -> Result<(), DbErr> {
213//! # let apple = fruit::ActiveModel {
214//! # name: Set("Apple".to_owned()),
215//! # ..Default::default() // no need to set primary key
216//! # };
217//! # let pear = fruit::ActiveModel {
218//! # name: Set("Pear".to_owned()),
219//! # ..Default::default()
220//! # };
221//!
222//! // insert many
223//! Fruit::insert_many([apple, pear]).exec(db).await?;
224//! # Ok(())
225//! # }
226//! ```
227//! ### Insert (advanced)
228//! ```
229//! # use sea_orm::{DbConn, TryInsertResult, error::*, entity::*, query::*, tests_cfg::*};
230//! # async fn function_1(db: &DbConn) -> Result<(), DbErr> {
231//! # let apple = fruit::ActiveModel {
232//! # name: Set("Apple".to_owned()),
233//! # ..Default::default() // no need to set primary key
234//! # };
235//! # let pear = fruit::ActiveModel {
236//! # name: Set("Pear".to_owned()),
237//! # ..Default::default()
238//! # };
239//! // insert many with returning (if supported by database)
240//! let models: Vec<fruit::Model> = Fruit::insert_many([apple, pear])
241//! .exec_with_returning_many(db)
242//! .await?;
243//! models[0]
244//! == fruit::Model {
245//! id: 1,
246//! name: "Apple".to_owned(),
247//! cake_id: None,
248//! };
249//! # Ok(())
250//! # }
251//!
252//! # async fn function_2(db: &DbConn) -> Result<(), DbErr> {
253//! # let apple = fruit::ActiveModel {
254//! # name: Set("Apple".to_owned()),
255//! # ..Default::default() // no need to set primary key
256//! # };
257//! # let pear = fruit::ActiveModel {
258//! # name: Set("Pear".to_owned()),
259//! # ..Default::default()
260//! # };
261//! // insert with ON CONFLICT on primary key do nothing, with MySQL specific polyfill
262//! let result = Fruit::insert_many([apple, pear])
263//! .on_conflict_do_nothing()
264//! .exec(db)
265//! .await?;
266//!
267//! matches!(result, TryInsertResult::Conflicted);
268//! # Ok(())
269//! # }
270//! ```
271//! ### Update
272//! ```
273//! # use sea_orm::{DbConn, error::*, entity::*, query::*, tests_cfg::*};
274//! use sea_orm::sea_query::{Expr, Value};
275//!
276//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
277//! let pear: Option<fruit::Model> = Fruit::find_by_id(1).one(db).await?;
278//! let mut pear: fruit::ActiveModel = pear.unwrap().into();
279//!
280//! pear.name = Set("Sweet pear".to_owned());
281//!
282//! // update one
283//! let pear: fruit::Model = pear.update(db).await?;
284//!
285//! // update many: UPDATE "fruit" SET "cake_id" = NULL WHERE "fruit"."name" LIKE '%Apple%'
286//! Fruit::update_many()
287//! .col_expr(fruit::Column::CakeId, Expr::value(Value::Int(None)))
288//! .filter(fruit::Column::Name.contains("Apple"))
289//! .exec(db)
290//! .await?;
291//!
292//! # Ok(())
293//! # }
294//! ```
295//! ### Save
296//! ```
297//! # use sea_orm::{DbConn, error::*, entity::*, query::*, tests_cfg::*};
298//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
299//! let banana = fruit::ActiveModel {
300//! id: NotSet,
301//! name: Set("Banana".to_owned()),
302//! ..Default::default()
303//! };
304//!
305//! // create, because primary key `id` is `NotSet`
306//! let mut banana = banana.save(db).await?;
307//!
308//! banana.name = Set("Banana Mongo".to_owned());
309//!
310//! // update, because primary key `id` is `Set`
311//! let banana = banana.save(db).await?;
312//!
313//! # Ok(())
314//! # }
315//! ```
316//! ### Delete
317//! ```
318//! # use sea_orm::{DbConn, error::*, entity::*, query::*, tests_cfg::*};
319//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
320//! // delete one
321//! let orange: Option<fruit::Model> = Fruit::find_by_id(1).one(db).await?;
322//! let orange: fruit::Model = orange.unwrap();
323//! fruit::Entity::delete(orange.into_active_model())
324//! .exec(db)
325//! .await?;
326//!
327//! // or simply
328//! let orange: Option<fruit::Model> = Fruit::find_by_id(1).one(db).await?;
329//! let orange: fruit::Model = orange.unwrap();
330//! orange.delete(db).await?;
331//!
332//! // delete many: DELETE FROM "fruit" WHERE "fruit"."name" LIKE 'Orange'
333//! fruit::Entity::delete_many()
334//! .filter(fruit::Column::Name.contains("Orange"))
335//! .exec(db)
336//! .await?;
337//!
338//! # Ok(())
339//! # }
340//! ```
341//!
342//! ## π§ Seaography: instant GraphQL API
343//!
344//! [Seaography](https://github.com/SeaQL/seaography) is a GraphQL framework built on top of SeaORM. Seaography allows you to build GraphQL resolvers quickly. With just a few commands, you can launch a GraphQL server from SeaORM entities!
345//!
346//! Look at the [Seaography Example](https://github.com/SeaQL/sea-orm/tree/master/examples/seaography_example) to learn more.
347//!
348//! <img src="https://raw.githubusercontent.com/SeaQL/sea-orm/master/examples/seaography_example/Seaography%20example.png"/>
349//!
350//! ## π₯οΈ SeaORM Pro: Effortless Admin Panel
351//!
352//! [SeaORM Pro](https://www.sea-ql.org/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!
353//!
354//! Features:
355//!
356//! + Full CRUD
357//! + Built on React + GraphQL
358//! + Built-in GraphQL resolver
359//! + Customize the UI with simple TOML
360//!
361//! Learn More
362//!
363//! + [Example Repo](https://github.com/SeaQL/sea-orm-pro)
364//! + [Getting Started with Loco](https://www.sea-ql.org/sea-orm-pro/docs/install-and-config/getting-started-loco/)
365//! + [Getting Started with Axum](https://www.sea-ql.org/sea-orm-pro/docs/install-and-config/getting-started-axum/)
366//!
367//! 
368//! 
369//!
370//! ## Releases
371//!
372//! [SeaORM 1.0](https://www.sea-ql.org/blog/2024-08-04-sea-orm-1.0/) is a stable release. The 1.x version will be updated until at least October 2025, and we'll decide whether to release a 2.0 version or extend the 1.x life cycle.
373//!
374//! It doesn't mean that SeaORM is 'done', we've designed an architecture to allow us to deliver new features without major breaking changes. In fact, more features are coming!
375//!
376//! + [Change Log](https://github.com/SeaQL/sea-orm/tree/master/CHANGELOG.md)
377//!
378//! ### Who's using SeaORM?
379//!
380//! Here is a short list of awesome open source software built with SeaORM. [Full list here](https://github.com/SeaQL/sea-orm/blob/master/COMMUNITY.md#built-with-seaorm). Feel free to submit yours!
381//!
382//! | Project | GitHub | Tagline |
383//! |---------|--------|---------|
384//! | [Zed](https://github.com/zed-industries/zed) |  | A high-performance, multiplayer code editor |
385//! | [OpenObserve](https://github.com/openobserve/openobserve) |  | Open-source observability platform |
386//! | [RisingWave](https://github.com/risingwavelabs/risingwave) |  | Stream processing and management platform |
387//! | [LLDAP](https://github.com/nitnelave/lldap) |  | A light LDAP server for user management |
388//! | [Warpgate](https://github.com/warp-tech/warpgate) |  | Smart SSH bastion that works with any SSH client |
389//! | [Svix](https://github.com/svix/svix-webhooks) |  | The enterprise ready webhooks service |
390//! | [Ryot](https://github.com/IgnisDa/ryot) |  | The only self hosted tracker you will ever need |
391//! | [Lapdev](https://github.com/lapce/lapdev) |  | Self-hosted remote development enviroment |
392//! | [System Initiative](https://github.com/systeminit/si) |  | DevOps Automation Platform |
393//! | [OctoBase](https://github.com/toeverything/OctoBase) |  | A light-weight, scalable, offline collaborative data backend |
394//!
395//! ## License
396//!
397//! Licensed under either of
398//!
399//! - Apache License, Version 2.0
400//! ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
401//! - MIT license
402//! ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
403//!
404//! at your option.
405//!
406//! ## Contribution
407//!
408//! Unless you explicitly state otherwise, any contribution intentionally submitted
409//! for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
410//! dual licensed as above, without any additional terms or conditions.
411//!
412//! We invite you to participate, contribute and together help build Rust's future.
413//!
414//! A big shout out to our contributors!
415//!
416//! [](https://github.com/SeaQL/sea-orm/graphs/contributors)
417//!
418//! ## Sponsorship
419//!
420//! [SeaQL.org](https://www.sea-ql.org/) is an independent open-source organization run by passionate developers. If you enjoy using our libraries, please star and share our repositories. 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.
421//!
422//! ### Gold Sponsors
423//!
424//! <table><tr>
425//! <td><a href="https://qdx.co/">
426//! <img src="https://www.sea-ql.org/static/sponsors/QDX.svg" width="138"/>
427//! </a></td>
428//! </tr></table>
429//!
430//! [QDX](https://qdx.co/) pioneers quantum dynamics-powered drug discovery, leveraging AI and supercomputing to accelerate molecular modeling.
431//! We're immensely grateful to QDX for sponsoring the development of SeaORM, the SQL toolkit that powers their data engineering workflows.
432//!
433//! ### Silver Sponsors
434//!
435//! Weβre grateful to our silver sponsors: Digital Ocean, for sponsoring our servers. And JetBrains, for sponsoring our IDE.
436//!
437//! <table><tr>
438//! <td><a href="https://www.digitalocean.com/">
439//! <img src="https://www.sea-ql.org/static/sponsors/DigitalOcean.svg" width="125">
440//! </a></td>
441//!
442//! <td><a href="https://www.jetbrains.com/">
443//! <img src="https://www.sea-ql.org/static/sponsors/JetBrains.svg" width="125">
444//! </a></td>
445//! </tr></table>
446//!
447//! ## Mascot
448//!
449//! A friend of Ferris, Terres the hermit crab is the official mascot of SeaORM. His hobby is collecting shells.
450//!
451//! <img alt="Terres" src="https://www.sea-ql.org/SeaORM/img/Terres.png" width="400"/>
452//!
453//! ### Rustacean Sticker Pack π¦
454//!
455//! The Rustacean Sticker Pack is the perfect way to express your passion for Rust.
456//! Our stickers are made with a premium water-resistant vinyl with a unique matte finish.
457//! Stick them on your laptop, notebook, or any gadget to show off your love for Rust!
458//!
459//! Sticker Pack Contents:
460//! - Logo of SeaQL projects: SeaQL, SeaORM, SeaQuery, Seaography, FireDBG
461//! - Mascot of SeaQL: Terres the Hermit Crab
462//! - Mascot of Rust: Ferris the Crab
463//! - The Rustacean word
464//!
465//! [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.
466//!
467//! <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>
468#![doc(
469 html_logo_url = "https://raw.githubusercontent.com/SeaQL/sea-query/master/docs/SeaQL icon dark.png"
470)]
471
472mod database;
473mod docs;
474mod driver;
475/// Module for the Entity type and operations
476pub mod entity;
477/// Error types for all database operations
478pub mod error;
479/// This module performs execution of queries on a Model or ActiveModel
480mod executor;
481/// Types and methods to perform metric collection
482pub mod metric;
483/// Types and methods to perform queries
484pub mod query;
485/// Types that defines the schemas of an Entity
486pub mod schema;
487/// Helpers for working with Value
488pub mod value;
489
490#[doc(hidden)]
491#[cfg(all(feature = "macros", feature = "tests-cfg"))]
492pub mod tests_cfg;
493mod util;
494
495pub use database::*;
496#[allow(unused_imports)]
497pub use driver::*;
498pub use entity::*;
499pub use error::*;
500pub use executor::*;
501pub use query::*;
502pub use schema::*;
503
504#[cfg(feature = "macros")]
505pub use sea_orm_macros::{
506 DeriveActiveEnum, DeriveActiveModel, DeriveActiveModelBehavior, DeriveColumn,
507 DeriveCustomColumn, DeriveDisplay, DeriveEntity, DeriveEntityModel, DeriveIden,
508 DeriveIntoActiveModel, DeriveMigrationName, DeriveModel, DerivePartialModel, DerivePrimaryKey,
509 DeriveRelatedEntity, DeriveRelation, DeriveValueType, FromJsonQueryResult, FromQueryResult,
510};
511
512pub use sea_query;
513pub use sea_query::Iden;
514
515pub use sea_orm_macros::EnumIter;
516pub use strum;
517
518#[cfg(feature = "sqlx-dep")]
519pub use sqlx;