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