### Connect to SQLite and Setup Schema Source: https://www.sea-ql.org/SeaORM/docs/write-test/sqlite Connects to an in-memory SQLite database, sets up the schema, and performs basic tests. This is a foundational example for integration testing. ```rust async fn main() -> Result<(), DbErr> { // Connecting SQLite let db = Database::connect("sqlite::memory:").await?; // Setup database schema setup_schema(&db).await?; // Performing tests testcase(&db).await?; Ok(()) } ``` -------------------------------- ### MySQL Connection String Example Source: https://www.sea-ql.org/SeaORM/docs/install-and-config/connection Example of a connection string for MySQL databases. ```rust mysql://username:password@host/database ``` -------------------------------- ### Install SeaORM CLI Source: https://www.sea-ql.org/SeaORM/docs/migration/setting-up-migration Install the SeaORM command-line interface tool, which is necessary for managing migrations. ```bash cargo install sea-orm-cli@^2.0.0-rc ``` -------------------------------- ### Start the GraphQL Server Source: https://www.sea-ql.org/SeaORM/docs/graph-ql/getting-started Navigate to the generated 'graphql' directory and run the server using Cargo. ```bash cd graphql cargo run ``` -------------------------------- ### Install sea-orm-cli Source: https://www.sea-ql.org/SeaORM/docs/generate-entity/sea-orm-cli Install the sea-orm-cli tool using cargo. Ensure you are using a version compatible with sea-orm. ```bash cargo install sea-orm-cli@^2.0.0-rc ``` -------------------------------- ### Install Seaography CLI Source: https://www.sea-ql.org/SeaORM/docs/graph-ql/getting-started Install the Seaography CLI using Cargo. Ensure you are using version 2.0.0-rc or later. ```bash cargo install seaography-cli@^2.0.0-rc ``` -------------------------------- ### Create RBAC Tables Source: https://www.sea-ql.org/SeaORM/docs/sea-orm-pro/role-based-access-control Initializes the necessary database tables for RBAC functionality. This should be run once during schema setup. ```rust sea_orm::rbac::schema::create_tables(db, Default::default()).await?; ``` -------------------------------- ### Postgres Connection String with Schema Source: https://www.sea-ql.org/SeaORM/docs/install-and-config/connection Example of a connection string for PostgreSQL databases, specifying a schema search path. ```rust postgres://username:password@host/database?options=--search_path=my_schema ``` -------------------------------- ### Setup Database Schema with SchemaBuilder Source: https://www.sea-ql.org/SeaORM/docs/write-test/sqlite Demonstrates how to set up a database schema for testing using SeaORM's SchemaBuilder, which automatically handles entity registration and foreign key dependencies. It also shows an alternative manual DDL creation. ```rust async fn setup_schema(db: &DbConn) -> Result<()> { // it doesn't matter which order you register entities. // SeaORM figures out the foreign key dependencies and // creates the tables in the right order along with foreign keys db.get_schema_builder() .register(cake::Entity) .register(cake_filling::Entity) .register(filling::Entity) .apply(db) .await?; // or, write DDL manually db.execute( Table::create() .table(cake::Entity) .col(pk_auto(cake::Column::Id)) .col(string(cake::Column::Name)) ).await?; Ok(()) } ``` -------------------------------- ### Compact Entity Format Example (cake.rs) Source: https://www.sea-ql.org/SeaORM/docs/graph-ql/getting-started An example of a SeaORM entity defined in the compact format, including the `RelatedEntity` enum for defining relationships. ```rust //! `SeaORM` Entity, @generated by sea-orm-codegen 2.0.0-rc.12 use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "cake")] pub struct Model { #[sea_orm(primary_key)] pub id: i32, pub name: String, #[sea_orm(column_type = "Decimal(Some((16, 4)))")] pub price: Decimal, pub bakery_id: i32, pub gluten_free: bool, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { .. } impl Related for Entity { .. } impl ActiveModelBehavior for ActiveModel {} #[derive(Copy, Clone, Debug, EnumIter, DeriveRelatedEntity)] pub enum RelatedEntity { #[sea_orm(entity = "super::bakery::Entity")] Bakery, #[sea_orm(entity = "super::baker::Entity")] Baker, } ``` -------------------------------- ### Dense Entity Format Example (cake.rs) Source: https://www.sea-ql.org/SeaORM/docs/graph-ql/getting-started An example of a SeaORM entity defined in the dense format, including relationship definitions for 'bakery' and 'bakers'. ```rust //! `SeaORM` Entity, @generated by sea-orm-codegen 2.0.0-rc.14 use sea_orm::entity::prelude::*; #[sea_orm::model] #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "cake")] pub struct Model { #[sea_orm(primary_key)] pub id: i32, pub name: String, #[sea_orm(column_type = "Decimal(Some((16, 4)))")] pub price: Decimal, pub bakery_id: i32, pub gluten_free: bool, #[sea_orm( belongs_to, from = "bakery_id", to = "id", on_update = "Cascade", on_delete = "Cascade" )] pub bakery: HasOne, #[sea_orm(has_many, via = "cake_baker")] pub bakers: HasMany, } impl ActiveModelBehavior for ActiveModel {} ``` -------------------------------- ### Workspace and App Crate Configuration Source: https://www.sea-ql.org/SeaORM/docs/migration/setting-up-migration Set up a Cargo workspace to manage separate app and migration crates. This example shows the root `Cargo.toml` configuration. ```toml [workspace] members = [".", "migration"] [dependencies] migration = { path = "migration" } [dependencies] sea-orm = { version = "2.0.0-rc", features = [..] } ``` -------------------------------- ### SQL Example with Custom Join Condition Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/custom-join-condition Demonstrates a SQL query with a custom condition in the LEFT JOIN clause. ```sql SELECT `cake`.`id`, `cake`.`name` FROM `cake` LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` AND `fruit`.`name` LIKE '%tropical%' ``` -------------------------------- ### Diamond Topology Join Example Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/advanced-joins Illustrates joining through multiple paths to a common table, forming a diamond topology. This requires aliasing intermediate tables. ```rust .join_as(JoinType::LeftJoin, complex_product::Relation::BaseProduct.def(), Base) .join_as(JoinType::LeftJoin, complex_product::Relation::Material.def(), Material) .join(JoinType::InnerJoin, base_product::Relation::Attribute.def().from_alias(Base)) .join(JoinType::InnerJoin, material::Relation::Attribute.def().from_alias(Material)) ``` -------------------------------- ### Setup Tracing Subscriber for Debug Log Source: https://www.sea-ql.org/SeaORM/docs/install-and-config/debug-log Configure `tracing-subscriber` to capture and display debug logs from SeaORM. This setup allows viewing logs at the DEBUG level. ```rust pub async fn main() { tracing_subscriber::fmt() .with_max_level(tracing::Level::DEBUG) .with_test_writer() .init(); // ... } ``` -------------------------------- ### Get Help with sea-orm-cli Source: https://www.sea-ql.org/SeaORM/docs/generate-entity/sea-orm-cli Use the -h flag with any sea-orm-cli command or subcommand to view available options and usage instructions. ```bash # List all available commands sea-orm-cli -h ``` ```bash # List all subcommands available in `generate` command sea-orm-cli generate -h ``` ```bash # Show how to use `generate entity` subcommand sea-orm-cli generate entity -h ``` -------------------------------- ### Implement Logic Tests for SeaORM Entities Source: https://www.sea-ql.org/SeaORM/docs/write-test/testing Write unit tests for the logic of your SeaORM entities and associated types. This example includes methods for calculating the area of a triangle and the distance between points, demonstrating pure Rust testing. ```rust use triangle::{Model as Triangle, Point}; impl Triangle { fn area(&self) -> f64 { let a = self.p1.distance_to(&self.p2); let b = self.p2.distance_to(&self.p3); let c = self.p3.distance_to(&self.p1); let s = (a + b + c) / 2.0; (s * (s - a) * (s - b) * (s - c)).sqrt() } } impl Point { fn distance_to(&self, p: &Point) -> f64 { let dx = self.x - p.x; let dy = self.y - p.y; (dx * dx + dy * dy).sqrt() } } assert!( (Triangle { id: 1, p1: Point { x: 0., y: 0. }, p2: Point { x: 2., y: 0. }, p3: Point { x: 0., y: 2. }, } .area() - 2.) .abs() < 0.00000001 ); ``` -------------------------------- ### Custom Select Query with Joins Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/advanced-joins Construct a custom select query by specifying columns and joining tables. This example demonstrates aliasing tables and joining through related entities. ```rust pub fn query() -> Select { complex_product::Entity::find() .select_only() .tbl_col_as((Base, Id), "id") .tbl_col_as((Base, Name), "name") .column_as(product_type::Column::Name, "type") .column_as(ProdCol::Price, "price") .column_as(ProdCol::LotSize, "lot_size") .column_as(ProdCol::DateAdded, "date_added") .column_as(ProdCol::LastModified, "last_modified") .join_as(JoinType::InnerJoin, ProdRel::BaseProduct.def(), Base) .join(JoinType::InnerJoin, base_product::Relation::ProductType.def().from_alias(Base)) .order_by_asc(Expr::col((Base, Id))) } ``` -------------------------------- ### Get Custom Result using query_one and query_all Source: https://www.sea-ql.org/SeaORM/docs/basic-crud/raw-sql Execute raw SQL queries using `query_one_raw` and `query_all_raw` to retrieve custom results. Results are of type `QueryResult`. ```rust let query_res: Option = db .query_one_raw(Statement::from_string( DbBackend::MySql, "SELECT * FROM `cake`;", )) .await?; let query_res = query_res.unwrap(); let id: i32 = query_res.try_get("", "id")?; let query_res_vec: Vec = db .query_all_raw(Statement::from_string( DbBackend::MySql, "SELECT * FROM `cake`;", )) .await?; ``` -------------------------------- ### Sum with Group By in SeaORM Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/aggregate-function Calculates the sum of a column for each group. This example joins two entities and groups by customer name to find the total spent per customer. ```rust let (customer, total_spent): (String, Decimal) = customer::Entity::find() .left_join(order::Entity) .select_only() .column(customer::Column::Name) .column_as(order::Column::Total.sum(), "sum") .group_by(customer::Column::Name) .into_tuple() .one(db) .await? .unwrap(); assert_eq!(customer, "Kate"); assert_eq!(total_spent, 25.into()); ``` -------------------------------- ### Loading Nested Entities with Entity Loader Source: https://www.sea-ql.org/SeaORM/docs/relation/entity-loader Demonstrates loading a 'cake' entity with its related 'fruit' (1-1) and 'fillings' which have 'ingredients' (M-N). This example shows how the Entity Loader uses join for 1-1 relations and data loader for M-N relations, resulting in optimized queries. ```rust let super_cake = cake::Entity::load() .filter_by_id(42) // shorthand for .filter(cake::Column::Id.eq(42)) .with(fruit::Entity) // 1-1 uses join .with((filling::Entity, ingredient::Entity)) // M-N uses data loader .one(db) .await? .unwrap(); ``` ```rust super_cake == cake::ModelEx { id: 42, name: "Black Forest".into(), fruit: Some( fruit::ModelEx { name: "Cherry".into(), } .into(), ), fillings: vec![filling::ModelEx { name: "Chocolate".into(), ingredients: vec![ingredient::ModelEx { name: "Syrup".into(), }], }], }; ``` -------------------------------- ### Save New Nested User, Profile, Post, and Tag Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/nested-active-model This example demonstrates saving a new, deeply nested set of related models (user, profile, post, tag) into the database atomically using a builder pattern. ```rust let user = user::ActiveModel::builder() .set_name("Bob") .set_email("bob@sea-ql.org") .set_profile(profile::ActiveModel::builder().set_picture("image.jpg")) .add_post( post::ActiveModel::builder() .set_title("Nice weather") .add_tag(tag::ActiveModel::builder().set_tag("sunny")), ) .save(db) .await?; ``` -------------------------------- ### Seed Data Transactionally in Migration Source: https://www.sea-ql.org/SeaORM/docs/migration/seeding-data Demonstrates how to perform data seeding within a transaction. This ensures that all operations succeed or fail together, maintaining data integrity. The transaction is started using `db.begin().await?` and committed with `txn.commit().await?`. ```rust use sea_orm_migration::sea_orm::{entity::*, query::*}; // ... #[async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { // Get the connection and start a transaction let db = manager.get_connection(); let txn = db.begin().await?; cake::ActiveModel { name: Set("Cheesecake".to_owned()), ..Default::default() } .insert(&txn) .await?; // Commit it txn.commit().await?; Ok(()) } } ``` -------------------------------- ### Seaography CLI Help Source: https://www.sea-ql.org/SeaORM/docs/graph-ql/getting-started Display the help information for the Seaography CLI, showing available options for generating a GraphQL project. ```bash seaography-cli --output-dir --entities --database-url Arguments: Crate name for generated project Options: -o, --output-dir Project output directory [default: ./] -e, --entities Entities directory -u, --database-url Database URL [env: DATABASE_URL] -f, --framework Which web framework to use [default: poem] [possible values: actix, poem, axum] --depth-limit GraphQL depth limit --complexity-limit GraphQL complexity limit -h, --help Print help -V, --version Print version ``` -------------------------------- ### GraphQL Query Example Source: https://www.sea-ql.org/SeaORM/docs/graph-ql/getting-started An example GraphQL query to find chocolate cakes and their associated bakery names. This demonstrates filtering and relationship traversal. ```graphql { cake(filters: { name: { contains: "Chocolate" } }) { nodes { name price bakery { name } } } } ``` -------------------------------- ### Schema Definition and Index Creation with SeaORM Source: https://www.sea-ql.org/SeaORM/docs/internal-design/diesel Shows how to define a database schema using SeaORM's `DeriveEntityModel` and generate SQL for creating unique indexes. ```rust #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] #[sea_orm(table_name = "lineitem")] pub struct Model { #[sea_orm(primary_key)] pub id: i32, #[sea_orm(unique_key = "item")] pub order_id: i32, #[sea_orm(unique_key = "item")] pub cake_id: i32, } let stmts = Schema::new(backend).create_index_from_entity(lineitem::Entity); assert_eq!( backend.build(stmts[0]), r#"CREATE UNIQUE INDEX "idx-lineitem-item" ON "lineitem" ("order_id", "cake_id")"# ); ``` -------------------------------- ### Initialize Migration Directory Source: https://www.sea-ql.org/SeaORM/docs/migration/setting-up-migration Set up the migration directory structure in your project. This command creates necessary files and folders for managing migrations. ```bash # Setup the migration directory in ./migration $ sea-orm-cli migrate init Initializing migration directory... Creating file ./migration/src/lib.rs Creating file ./migration/src/m20220101_000001_create_table.rs Creating file ./migration/src/main.rs Creating file ./migration/Cargo.toml Creating file ./migration/README.md Done! ``` ```bash # If you want to setup the migration directory in else where $ sea-orm-cli migrate init -d ./other/migration/dir ``` -------------------------------- ### Get Schema Registry for Current Crate Source: https://www.sea-ql.org/SeaORM/docs/generate-entity/entity-first Alternatively, use `module_path!()` to dynamically get the caller's crate name for schema registry. ```rust // This returns the caller's crate db.get_schema_registry(module_path!().split("::").next().unwrap()) ``` -------------------------------- ### Run Migrations on Startup Source: https://www.sea-ql.org/SeaORM/docs/migration/setting-up-migration Integrate migration execution into your application's startup process by calling `Migrator::up`. ```rust use migration::{Migrator, MigratorTrait}; let connection = sea_orm::Database::connect(&database_url).await?; Migrator::up(&connection, None).await?; ``` -------------------------------- ### Establish Database Connection Source: https://www.sea-ql.org/SeaORM/docs/install-and-config/connection Use the `Database::connect` method with a connection string to obtain a database connection. The protocol can be `mysql:`, `postgres:`, or `sqlite:`. The host is typically `localhost` or an IP address. ```rust let db: DatabaseConnection = Database::connect("protocol://username:password@host/database").await?; ``` -------------------------------- ### Insert One Record and Get Last Insert ID - SeaORM Source: https://www.sea-ql.org/SeaORM/docs/basic-crud/insert Insert an active model and get back the last insert ID. Its type matches the model's primary key type, so it could be a tuple if the model has a composite primary key. ```rust let pear = fruit::ActiveModel { name: Set("Pear".to_owned()), ..Default::default() // all other attributes are `NotSet` }; let res: InsertResult = fruit::Entity::insert(pear).exec(db).await?; assert_eq!(res.last_insert_id, 28) ``` -------------------------------- ### Basic Transaction with Begin and Commit Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/transaction Demonstrates creating a transaction, saving entities within it, and committing the changes. Assertions verify the state before, during, and after the transaction. ```rust assert_eq!(Bakery::find().all(db).await?.len(), 0); let txn = db.begin().await?; // First create 2 bakeries seaside_bakery().save(&txn).await?; lakeside_bakery().save(&txn).await?; assert_eq!(Bakery::find().all(&txn).await?.len(), 2); // Try nested transaction committed { let txn = txn.begin().await?; let _ = bakery::ActiveModel { name: Set("Hillside Bakery".to_owned()), profit_margin: Set(88.88), ..Default::default() } .save(&txn) .await?; assert_eq!(Bakery::find().all(txn).await?.len(), 3); // Try nested-nested transaction rollbacked { let txn = txn.begin().await?; let _ = bakery::ActiveModel { name: Set("Canalside Bakery".to_owned()), profit_margin: Set(28.8), ..Default::default() } .save(&txn) .await?; assert_eq!(Bakery::find().all(txn).await?.len(), 4); } txn.commit().await?; } assert_eq!(Bakery::find().all(&txn).await?.len(), 3); txn.commit().await?; assert_eq!(Bakery::find().all(db).await?.len(), 3); ``` -------------------------------- ### Ergonomic Raw SQL with Parameter Expansion in SeaORM Source: https://www.sea-ql.org/SeaORM/docs/internal-design/diesel Shows how to use raw SQL with parameter expansion for complex queries, including nested parameter access and array expansion. ```rust let item = Item { id: 2 }; // nested parameter access let cake_ids = [2, 3, 4]; // expanded by the `..` operator // can use nested select with raw SQL let cake: Option = CakeWithBakery::find_by_statement(raw_sql!( Sqlite, r#"SELECT "cake"."name", "bakery"."name" AS "bakery_name" FROM "cake" LEFT JOIN "bakery" ON "cake"."bakery_id" = "bakery"."id" WHERE "cake"."id" = {item.id} OR "cake"."id" IN ({..cake_ids})"# )) .one(db) .await?; ``` -------------------------------- ### Run Migration via sea-orm-cli Source: https://www.sea-ql.org/SeaORM/docs/migration/running-migration Execute migration commands using the `sea-orm-cli`. Ensure `DATABASE_URL` is set in your environment. ```bash sea-orm-cli migrate COMMAND ``` ```bash sea-orm-cli migrate COMMAND -d ./other/migration/dir ``` -------------------------------- ### Offset-based Pagination with SeaORM Source: https://www.sea-ql.org/SeaORM/docs/internal-design/diesel Demonstrates offset-based pagination using SeaORM's `paginate` method. Requires a database connection and the number of posts per page. ```rust let paginator = Post::find() .order_by_asc(post::Column::Id) .paginate(db, posts_per_page); let num_pages = paginator.num_pages().await?; let posts: Vec = paginator.fetch_page(current_page).await?; ``` -------------------------------- ### Configure Database Connection Options Source: https://www.sea-ql.org/SeaORM/docs/install-and-config/connection Configure advanced connection options such as pool sizes, timeouts, and logging using `ConnectOptions`. This allows fine-grained control over the database connection pool. ```rust let mut opt = ConnectOptions::new("protocol://username:password@host/database"); opt.max_connections(100) .min_connections(5) .connect_timeout(Duration::from_secs(8)) .acquire_timeout(Duration::from_secs(8)) .idle_timeout(Duration::from_secs(8)) .max_lifetime(Duration::from_secs(8)) .sqlx_logging(false) // disable SQLx logging .sqlx_logging_level(log::LevelFilter::Info) .set_schema_search_path("my_schema"); // set default Postgres schema let db = Database::connect(opt).await?; ``` -------------------------------- ### Conditionally Select Columns - SeaORM Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/custom-select This example demonstrates how to conditionally select all columns except a specific one using iterator filtering. ```rust assert_eq!( cake::Entity::find() .select_only() .columns(cake::Column::iter().filter(|col| match col { cake::Column::Id => false, _ => true, })) .build(DbBackend::Postgres) .to_string(), r#"SELECT \"cake\".\"name\" FROM \"cake\""# ); ``` -------------------------------- ### SQLite File Connection String (Create if not exists) Source: https://www.sea-ql.org/SeaORM/docs/install-and-config/connection Connection string for SQLite, creating the database file if it does not exist. ```rust sqlite://path/to/db.sqlite?mode=rwc ``` -------------------------------- ### Join with Alias in SeaORM Source: https://www.sea-ql.org/SeaORM/docs/relation/nested-selects Use the `alias` attribute when joining the same table more than once to distinguish between them. This example demonstrates selecting columns from an aliased nested relation. ```rust #[derive(DerivePartialModel)] #[sea_orm(entity = "cake::Entity")] struct CakeFactory { id: i32, name: String, #[sea_orm(nested, alias = "factory")] bakery: Option, } #[derive(DerivePartialModel)] #[sea_orm(entity = "bakery::Entity")] struct Factory { id: i32, #[sea_orm(from_col = "name")] plant: String, } let cake_factory: CakeFactory = cake::Entity::find() .join_as( JoinType::LeftJoin, cake::Relation::Bakery.def(), "factory", ) .order_by_asc(cake::Column::Id) .into_partial_model() .one(db) .await? .unwrap(); ``` ```sql SELECT "cake"."id" AS "id", "cake"."name" AS "name", "factory"."id" AS "bakery_id", "factory"."name" AS "bakery_plant" FROM "cake" LEFT JOIN "bakery" AS "factory" ON "cake"."bakery_id" = "factory"."id" ORDER BY "cake"."id" ASC LIMIT 1 ``` -------------------------------- ### Generate GraphQL Project with Seaography CLI Source: https://www.sea-ql.org/SeaORM/docs/graph-ql/getting-started Generate a new GraphQL project using the Seaography CLI, specifying the output directory, entities directory, and web framework (e.g., Axum). ```bash seaography-cli --output-dir . --entities ./src/entities --framework axum sea-orm-seaography-example ``` -------------------------------- ### Group By a single column in SeaORM Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/aggregate-function Groups query results by a specified column. This example demonstrates grouping by the 'name' column of the 'cake' entity. ```rust assert_eq!( cake::Entity::find() .select_only() .column(cake::Column::Name) .group_by(cake::Column::Name) .build(DbBackend::Postgres) .to_string(), r#"SELECT \"cake\"\."name\" FROM \"cake\" GROUP BY \"cake\"\."name\""# ); ``` -------------------------------- ### SQL Actions for Replacing Posts Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/nested-active-model Illustrates the SQL queries generated when replacing a user's posts. ```sql SELECT FROM post WHERE user_id = bob.id DELETE FROM post WHERE id = 2 ``` -------------------------------- ### Enum Alias for Multiple Entities Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/advanced-joins Provides an example of using an enum to define aliases for multiple entities or their related concepts, enhancing code organization. ```rust #[derive(DeriveIden, Clone, Copy)] pub enum Prod { Base, Frame, Package, } ``` -------------------------------- ### Insert One Record - SeaORM Source: https://www.sea-ql.org/SeaORM/docs/basic-crud/insert Insert an active model and get back a fresh Model. Its value is retrieved from the database, so any auto-generated fields will be populated. ```rust let pear = fruit::ActiveModel { name: Set("Pear".to_owned()), ..Default::default() // all other attributes are `NotSet` }; let pear: fruit::Model = pear.insert(db).await?; ``` -------------------------------- ### Run Migration via SeaSchema Migrator CLI Source: https://www.sea-ql.org/SeaORM/docs/migration/running-migration Execute migrations by running the migrator CLI defined in `migration/main.rs`. Navigate to the migration directory first. ```bash cd migration cargo run -- COMMAND ``` -------------------------------- ### Generate CREATE TABLE for PostgreSQL Source: https://www.sea-ql.org/SeaORM/docs/schema-statement/create-table Demonstrates generating the SQL CREATE TABLE statement for PostgreSQL using Schema::create_table_from_entity. ```rust use sea_orm::{tests_cfg::*, DbBackend, Schema, Statement}; let db_postgres = DbBackend::Postgres; let schema = Schema::new(db_postgres); assert_eq!( db_postgres.build(&schema.create_table_from_entity(CakeFillingPrice)), Statement::from_string( db_postgres, [ r#"CREATE TABLE "public"."cake_filling_price" ("#, r#""cake_id" integer NOT NULL,"#, r#""filling_id" integer NOT NULL,"#, r#""price" decimal NOT NULL,"#, r# ``` ```rust use sea_orm::{tests_cfg::*, DbBackend, Schema, Statement}; let db_mysql = DbBackend::MySql; let schema = Schema::new(db_mysql); assert_eq!( db_mysql.build(&schema.create_table_from_entity(CakeFillingPrice)), Statement::from_string( db_mysql, [ "CREATE TABLE `cake_filling_price` (", "`cake_id` int NOT NULL,", "`filling_id` int NOT NULL,", "`price` decimal NOT NULL,", "PRIMARY KEY `pk-cake_filling_price` (`cake_id`, `filling_id`)", "CONSTRAINT `fk-cake_filling_price-cake_id-filling_id` FOREIGN KEY (`cake_id`, `filling_id`) REFERENCES `cake_filling` (`cake_id`, `filling_id`)" ] .join(" ") ) ); ``` -------------------------------- ### Lazy Loading with find_linked Source: https://www.sea-ql.org/SeaORM/docs/relation/complex-relations Use the `find_linked` method with a `Linked` implementation to lazily load related entities. This example finds fillings that can be filled into a specific cake. ```rust let cake_model = cake::Model { id: 12, name: "Chocolate".into(), }; assert_eq!( cake_model .find_linked(cake::CakeToFilling) .build(DbBackend::MySql) .to_string(), [ "SELECT `filling`.`id`, `filling`.`name`, `filling`.`vendor_id`", "FROM `filling`", "INNER JOIN `cake_filling` AS `r0` ON `r0`.`filling_id` = `filling`.`id`", "INNER JOIN `cake` AS `r1` ON `r1`.`id` = `r0`.`cake_id`", "WHERE `r1`.`id` = 12", ] .join(" ") ); ``` -------------------------------- ### Having clause with aggregate function comparison in SeaORM Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/aggregate-function Applies conditions to aggregate function results within the `HAVING` clause. This example filters groups where the 'count' is greater than 6. ```rust assert_eq!( cake::Entity::find() .select_only() .column_as(cake::Column::Id.count(), "count") .column_as(cake::Column::Id.sum(), "sum_of_id") .group_by(cake::Column::Name) .having(Expr::col("count").gt(6)) .build(DbBackend::MySql) .to_string(), "SELECT COUNT(`cake`.`id`) AS `count`, SUM(`cake`.`id`) AS `sum_of_id` FROM `cake` GROUP BY `cake`.`name` HAVING `count` > 6" ); ``` -------------------------------- ### Migration Directory Structure Source: https://www.sea-ql.org/SeaORM/docs/migration/setting-up-migration Understand the standard file structure created for the migration directory. ```text migration ├── Cargo.toml ├── README.md └── src ├── lib.rs # Migrator API, for integration ├── m20220101_000001_create_table.rs # A sample migration file └── main.rs # Migrator CLI, for running manually ``` -------------------------------- ### Having clause with equality conditions in SeaORM Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/aggregate-function Filters grouped results based on conditions applied after aggregation. This example shows filtering cakes by ID using the `having` method. ```rust assert_eq!( cake::Entity::find() .having(cake::Column::Id.eq(4)) .having(cake::Column::Id.eq(5)) .build(DbBackend::MySql) .to_string(), "SELECT `cake`.`id`, `cake`.`name` FROM `cake` HAVING `cake`.`id` = 4 AND `cake`.`id` = 5" ); ``` -------------------------------- ### Fluent conditional query with `apply_if` Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/conditional-expression Apply an operation to a `QueryStatement` only if an `Option` is `Some(_)`, keeping the query expression fluent. This example demonstrates applying filters and limits conditionally. ```rust use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend}; assert_eq!( cake::Entity::find() .apply_if(Some(3), |mut query, v| { query.filter(cake::Column::Id.eq(v)) }) .apply_if(Some(100), QuerySelect::limit) .apply_if(None, QuerySelect::offset::>) // no-op .build(DbBackend::Postgres) .to_string(), r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "cake"."id" = 3 LIMIT 100"# ); ``` -------------------------------- ### Create Index Schema Source: https://www.sea-ql.org/SeaORM/docs/migration/writing-migration Use `sea_query::Index::create()` to define a new index for a table. ```rust manager.create_index(sea_query::Index::create()..) ``` -------------------------------- ### Load Related Entities with Additional Filter Source: https://www.sea-ql.org/SeaORM/docs/relation/model-loader Apply filters to the related entities during loading by using a query builder for the related entity. This example loads only fruits that are in stock. ```rust let fruits_in_stock: Vec> = cakes.load_many( fruit::Entity::find().filter(fruit::Column::Stock.gt(0i32)), db ).await?; ``` -------------------------------- ### Eager Loading with find_also_linked Source: https://www.sea-ql.org/SeaORM/docs/relation/complex-relations Employ `find_also_linked` for eager loading of related entities when using a `Linked` trait. This example demonstrates eager loading of fillings associated with cakes. ```rust assert_eq!( cake::Entity::find() .find_also_linked(links::CakeToFilling) .build(DbBackend::MySql) .to_string(), [ "SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,", "`r1`.`id` AS `B_id`, `r1`.`name` AS `B_name`, `r1`.`vendor_id` AS `B_vendor_id`", "FROM `cake`", "LEFT JOIN `cake_filling` AS `r0` ON `cake`.`id` = `r0`.`cake_id`", "LEFT JOIN `filling` AS `r1` ON `r0`.`filling_id` = `r1`.`id`", ] .join(" ") ); ``` -------------------------------- ### Access GraphQL Playground Source: https://www.sea-ql.org/SeaORM/docs/graph-ql/getting-started Open your web browser to the specified URL to access the GraphQL Playground for interacting with your API. ```bash http://localhost:8000 ``` -------------------------------- ### Cursor-based Pagination with SeaORM Source: https://www.sea-ql.org/SeaORM/docs/internal-design/diesel Illustrates cursor-based pagination using SeaORM's `cursor_by` method. Allows filtering results with `after` and `before` conditions. ```rust let mut cursor = post::Entity::find().cursor_by(post::Column::Id); // Filter paginated result by "post"."id" > 1 AND "post"."id" < 100 cursor.after(1).before(100); // Get first 10 rows (order by "post"."id" ASC) let posts: Vec = cursor.first(10).all(db).await? ``` -------------------------------- ### Insert many and return primary keys Source: https://www.sea-ql.org/SeaORM/docs/basic-crud/insert Use `exec_with_returning_keys` to insert multiple models and retrieve only their primary keys. This is an efficient way to get identifiers after a bulk insert. ```rust assert_eq!( cakes_bakers::Entity::insert_many([ cakes_bakers::ActiveModel { cake_id: Set(1), baker_id: Set(2), }, cakes_bakers::ActiveModel { cake_id: Set(2), baker_id: Set(1), }, ]) .exec_with_returning_keys(db) .await .unwrap(), [(1, 2), (2, 1)] ); ``` -------------------------------- ### Synchronize Database Schema with Entity Definitions Source: https://www.sea-ql.org/SeaORM/docs/generate-entity/entity-first Add this to your `main.rs` after connecting to the database to synchronize the schema. Requires `schema-sync` and `entity-registry` feature flags. ```rust let db = &Database::connect(db_url).await?; // synchronizes database schema with entity definitions db.get_schema_registry("my_crate::entity::*").sync(db).await?; ``` -------------------------------- ### Create Table Schema Source: https://www.sea-ql.org/SeaORM/docs/migration/writing-migration Define a new table schema using `Table::create()`. Use `if_not_exists()` to prevent errors if the table already exists. Remember to import schema helpers. ```rust use sea_orm_migration::{prelude::*, schema::*}; // Defining the table schema manager .create_table( Table::create() .table("post") .if_not_exists() .col(pk_auto("id")) .col(string("title")) .col(string("text")) .col(enumeration_null("category", "category", ["Feed", "Store"])) ) .await ``` -------------------------------- ### Accessing Arrow Schema Methods Source: https://www.sea-ql.org/SeaORM/docs/data-science/arrow-parquet The `ArrowSchema` trait provides methods to get the schema, convert models to Arrow batches, and convert Arrow batches back to models. ```rust use sea_orm::ArrowSchema; let schema = measurement::Entity::arrow_schema(); let batch = measurement::ActiveModel::to_arrow(&models, &schema)?; let models = measurement::ActiveModel::from_arrow(&batch)?; ``` -------------------------------- ### Execute Unprepared SQL Statement Source: https://www.sea-ql.org/SeaORM/docs/basic-crud/raw-sql Execute unprepared SQL statements directly using `ConnectionTrait::execute_unprepared`. Useful for commands like `CREATE EXTENSION`. ```rust let exec_res: ExecResult = db.execute_unprepared("CREATE EXTENSION IF NOT EXISTS citext").await?; ``` -------------------------------- ### Define Composite Foreign Key Relation (Composite A) Source: https://www.sea-ql.org/SeaORM/docs/relation/one-to-many Define a one-to-one relation from 'composite_a' to 'composite_b' using `has_one`. This example sets up composite unique keys for the foreign key. ```rust #[sea_orm::model] #[sea_orm(table_name = "composite_a")] pub struct Model { #[sea_orm(primary_key)] pub id: i32, #[sea_orm(unique_key = "pair")] pub left_id: i32, #[sea_orm(unique_key = "pair")] pub right_id: i32, #[sea_orm(has_one)] pub b: Option, } ``` -------------------------------- ### Configure Database URL Source: https://www.sea-ql.org/SeaORM/docs/generate-entity/sea-orm-cli Set the DATABASE_URL environment variable or create a .env file in your project root to specify your database connection details. ```dotenv DATABASE_URL=protocol://username:password@localhost/database ``` -------------------------------- ### Implement ActiveModelBehavior with Custom Hooks Source: https://www.sea-ql.org/SeaORM/docs/generate-entity/entity-format Implement custom logic for database operations using ActiveModelBehavior hooks. This example shows custom validation in `before_save` and default behavior for other hooks. ```rust #[async_trait] impl ActiveModelBehavior for ActiveModel { /// Create a new ActiveModel with default values. Also used by `Default::default()`. fn new() -> Self { Self { uuid: Set(Uuid::new_v4()), ..ActiveModelTrait::default() } } /// Will be triggered before insert / update async fn before_save(self, db: &C, insert: bool) -> Result where C: ConnectionTrait, { if self.price.as_ref() <= &0.0 { Err(DbErr::Custom(format!( "[before_save] Invalid Price, insert:જી", insert ))) } else { Ok(self) } } /// Will be triggered after insert / update async fn after_save(model: Model, db: &C, insert: bool) -> Result where C: ConnectionTrait, { Ok(model) } /// Will be triggered before delete async fn before_delete(self, db: &C) -> Result where C: ConnectionTrait, { Ok(self) } /// Will be triggered after delete async fn after_delete(self, db: &C) -> Result where C: ConnectionTrait, { Ok(self) } } ``` -------------------------------- ### Manually Register Entities for Schema Builder Source: https://www.sea-ql.org/SeaORM/docs/generate-entity/entity-first Manually register entities with the schema builder if not using the automatic registry. This example registers `comment`, `post`, `profile`, and `user` entities. ```rust db.get_schema_builder() .register(comment::Entity) .register(post::Entity) .register(profile::Entity) .register(user::Entity) .sync(db) .await?; ``` -------------------------------- ### Add Resources and Permissions Source: https://www.sea-ql.org/SeaORM/docs/sea-orm-pro/role-based-access-control Adds all relevant database tables as resources and generates default CRUD permissions for them. The wildcard '*' can be used to represent all resources. ```rust let mut context = RbacContext::load(db).await?; let tables = [ baker::Entity.table_name(), bakery::Entity.table_name(), cake::Entity.table_name(), cakes_bakers::Entity.table_name(), customer::Entity.table_name(), lineitem::Entity.table_name(), order::Entity.table_name(), "*", // WILDCARD ]; context.add_tables(db, &tables).await?; context.add_crud_permissions(db).await?; ``` -------------------------------- ### Insert with On Conflict - Update Column - SeaORM Source: https://www.sea-ql.org/SeaORM/docs/basic-crud/insert Insert an active model with on conflict behavior, updating a specific column if a conflict occurs. This example demonstrates building the SQL for PostgreSQL. ```rust let orange = cake::ActiveModel { id: ActiveValue::set(2), name: ActiveValue::set("Orange".to_owned()), }; assert_eq!( cake::Entity::insert(orange) .on_conflict( // on conflict do update sea_query::OnConflict::column(cake::Column::Name) .update_column(cake::Column::Name) .to_owned() ) .build(DbBackend::Postgres) .to_string(), r#"INSERT INTO "cake" ("id", "name") VALUES (2, 'Orange') ON CONFLICT ("name") DO UPDATE SET "name" = "excluded"."name""#, ); ``` -------------------------------- ### Execute Raw SQL Statements in Migrations Source: https://www.sea-ql.org/SeaORM/docs/migration/writing-migration Use `execute_unprepared` for SQL statements without value bindings and `execute_raw` with `Statement::from_sql_and_values` for statements containing value bindings. This approach bypasses SeaQuery's multi-backend compatibility. ```rust use sea_orm::Statement; use sea_orm_migration::prelude::*; #[derive(DeriveMigrationName)] pub struct Migration; #[async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { let db = manager.get_connection(); // Use `execute_unprepared` if the SQL statement doesn't have value bindings db.execute_unprepared( "CREATE TABLE `cake` ( `id` int NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` varchar(255) NOT NULL" ) .await?; // Construct a `Statement` if the SQL contains value bindings db.execute_raw(Statement::from_sql_and_values( manager.get_database_backend(), r#"INSERT INTO `cake` (`name`) VALUES (?)"#, ["Cheese Cake".into()] )).await?; Ok(()) } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { manager .get_connection() .execute_unprepared("DROP TABLE `cake`") .await?; Ok(()) } } ``` -------------------------------- ### Inspect Raw SQL from Queries Source: https://www.sea-ql.org/SeaORM/docs/basic-crud/raw-sql Use `build` and `to_string` methods on query operations to generate database-specific raw SQL for debugging. ```rust use sea_orm::{DbBackend, QueryTrait}; assert_eq!( cake_filling::Entity::find_by_id((6, 8)) .build(DbBackend::MySql) .to_string(), [ "SELECT `cake_filling`.`cake_id`, `cake_filling`.`filling_id` FROM `cake_filling`", "WHERE `cake_filling`.`cake_id` = 6 AND `cake_filling`.`filling_id` = 8", ].join(" ") ); ``` -------------------------------- ### Insert with On Conflict - Do Nothing - SeaORM Source: https://www.sea-ql.org/SeaORM/docs/basic-crud/insert Insert an active model with on conflict behavior, specifically to do nothing if a conflict occurs on the specified column. This example demonstrates building the SQL for PostgreSQL. ```rust let orange = cake::ActiveModel { id: ActiveValue::set(2), name: ActiveValue::set("Orange".to_owned()), }; assert_eq!( cake::Entity::insert(orange.clone()) .on_conflict( // on conflict do nothing sea_query::OnConflict::column(cake::Column::Name) .do_nothing() .to_owned() ) .build(DbBackend::Postgres) .to_string(), r#"INSERT INTO "cake" ("id", "name") VALUES (2, 'Orange') ON CONFLICT ("name") DO NOTHING"#, ); ``` -------------------------------- ### Paginate Entities with Entity Loader Source: https://www.sea-ql.org/SeaORM/docs/relation/entity-loader Illustrates how to use the `paginate` method of the Entity Loader to fetch entities in batches. This is useful for handling large datasets efficiently by retrieving them page by page. ```rust let mut paginator = user::Entity::load() .with(profile::Entity) .order_by_asc(user::COLUMN.id) .paginate(db, 10); while let Some(users) = paginator.fetch_and_next().await? { for user in users { // user: user::ModelEx with profile loaded } } ``` -------------------------------- ### Define ProductHistory Model and Relation Source: https://www.sea-ql.org/SeaORM/docs/advanced-query/advanced-joins Defines the `ProductHistory` model with its attributes and establishes a `belongs_to` relationship with the `BaseProduct` entity. This setup is crucial for defining how `ProductHistory` relates to `BaseProduct` in the database. ```rust #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "product_history")] pub struct Model { #[sea_orm(primary_key)] #[serde(skip)] pub id: i32, pub product_id: i64, pub from: DateTime, pub until: DateTime, pub name: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( belongs_to = "super::base_product::Entity", from = "Column::ProductId", to = "super::base_product::Column::Id", on_update = "NoAction", on_delete = "Cascade" )] BaseProduct, } ```