From 892c0fe57dca0783be6050eee455b62b3b460bd2 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 2 Nov 2021 14:56:29 +0800 Subject: [PATCH 1/2] Support `Vec` primary key --- src/executor/query.rs | 2 + tests/byte_primary_key_tests.rs | 74 +++++++++++++++++++++++ tests/common/features/byte_primary_key.rs | 14 +++++ tests/common/features/mod.rs | 2 + tests/common/features/schema.rs | 20 ++++++ 5 files changed, 112 insertions(+) create mode 100644 tests/byte_primary_key_tests.rs create mode 100644 tests/common/features/byte_primary_key.rs diff --git a/src/executor/query.rs b/src/executor/query.rs index 96455945..3c1a9184 100644 --- a/src/executor/query.rs +++ b/src/executor/query.rs @@ -539,5 +539,7 @@ macro_rules! try_from_u64_string { try_from_u64_string!(String); +try_from_u64_err!(Vec); + #[cfg(feature = "with-uuid")] try_from_u64_err!(uuid::Uuid); diff --git a/tests/byte_primary_key_tests.rs b/tests/byte_primary_key_tests.rs new file mode 100644 index 00000000..cb3ab775 --- /dev/null +++ b/tests/byte_primary_key_tests.rs @@ -0,0 +1,74 @@ +pub mod common; + +pub use common::{features::*, setup::*, TestContext}; +use pretty_assertions::assert_eq; +use sea_orm::{entity::prelude::*, entity::*, DatabaseConnection}; + +#[sea_orm_macros::test] +#[cfg(any( + feature = "sqlx-mysql", + feature = "sqlx-sqlite", + feature = "sqlx-postgres" +))] +async fn main() -> Result<(), DbErr> { + let ctx = TestContext::new("byte_primary_key_tests").await; + create_tables(&ctx.db).await?; + create_and_update(&ctx.db).await?; + ctx.delete().await; + + Ok(()) +} + +pub async fn create_and_update(db: &DatabaseConnection) -> Result<(), DbErr> { + use common::features::byte_primary_key::*; + + let model = Model { + id: vec![1], + value: "First Row".to_owned(), + }; + + let res = Entity::insert(model.clone().into_active_model()) + .exec(db) + .await?; + + assert_eq!(Entity::find().one(db).await?, Some(model.clone())); + + assert_eq!(res.last_insert_id, model.id); + + let updated_active_model = ActiveModel { + value: Set("First Row (Updated)".to_owned()), + ..model.clone().into_active_model() + }; + + let update_res = Entity::update(updated_active_model.clone()) + .filter(Column::Id.eq(vec![1, 4])) + .exec(db) + .await; + + assert_eq!( + update_res, + Err(DbErr::RecordNotFound( + "None of the database rows are affected".to_owned() + )) + ); + + let update_res = Entity::update(updated_active_model.clone()) + .filter(Column::Id.eq(vec![1])) + .exec(db) + .await?; + + assert_eq!(update_res, updated_active_model); + + assert_eq!( + Entity::find() + .filter(Column::Id.eq(vec![1])) + .one(db) + .await?, + Some(Model { + id: vec![1], + value: "First Row (Updated)".to_owned(), + }) + ); + + Ok(()) +} diff --git a/tests/common/features/byte_primary_key.rs b/tests/common/features/byte_primary_key.rs new file mode 100644 index 00000000..7578e3c8 --- /dev/null +++ b/tests/common/features/byte_primary_key.rs @@ -0,0 +1,14 @@ +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "byte_primary_key")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: Vec, + pub value: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/tests/common/features/mod.rs b/tests/common/features/mod.rs index 1e709edf..186256ae 100644 --- a/tests/common/features/mod.rs +++ b/tests/common/features/mod.rs @@ -1,10 +1,12 @@ pub mod applog; +pub mod byte_primary_key; pub mod metadata; pub mod repository; pub mod schema; pub mod self_join; pub use applog::Entity as Applog; +pub use byte_primary_key::Entity as BytePrimaryKey; pub use metadata::Entity as Metadata; pub use repository::Entity as Repository; pub use schema::*; diff --git a/tests/common/features/schema.rs b/tests/common/features/schema.rs index 7e6f6424..b6cecab0 100644 --- a/tests/common/features/schema.rs +++ b/tests/common/features/schema.rs @@ -10,6 +10,7 @@ pub async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> { create_metadata_table(db).await?; create_repository_table(db).await?; create_self_join_table(db).await?; + create_byte_primary_key_table(db).await?; Ok(()) } @@ -100,3 +101,22 @@ pub async fn create_self_join_table(db: &DbConn) -> Result { create_table(db, &stmt, SelfJoin).await } + +pub async fn create_byte_primary_key_table(db: &DbConn) -> Result { + let stmt = sea_query::Table::create() + .table(byte_primary_key::Entity) + .col( + ColumnDef::new(byte_primary_key::Column::Id) + .binary() + .not_null() + .primary_key(), + ) + .col( + ColumnDef::new(byte_primary_key::Column::Value) + .string() + .not_null(), + ) + .to_owned(); + + create_table(db, &stmt, BytePrimaryKey).await +} From d22ff0db5e513fabc6ef789f30296df4766bf8a9 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 2 Nov 2021 18:35:36 +0800 Subject: [PATCH 2/2] Fixup --- tests/byte_primary_key_tests.rs | 10 +++++----- tests/common/features/schema.rs | 21 ++++++++++++--------- tests/common/setup/mod.rs | 21 ++++++++++++++------- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/tests/byte_primary_key_tests.rs b/tests/byte_primary_key_tests.rs index cb3ab775..173efc93 100644 --- a/tests/byte_primary_key_tests.rs +++ b/tests/byte_primary_key_tests.rs @@ -23,7 +23,7 @@ pub async fn create_and_update(db: &DatabaseConnection) -> Result<(), DbErr> { use common::features::byte_primary_key::*; let model = Model { - id: vec![1], + id: vec![1, 2, 3], value: "First Row".to_owned(), }; @@ -41,7 +41,7 @@ pub async fn create_and_update(db: &DatabaseConnection) -> Result<(), DbErr> { }; let update_res = Entity::update(updated_active_model.clone()) - .filter(Column::Id.eq(vec![1, 4])) + .filter(Column::Id.eq(vec![1, 2, 4])) .exec(db) .await; @@ -53,7 +53,7 @@ pub async fn create_and_update(db: &DatabaseConnection) -> Result<(), DbErr> { ); let update_res = Entity::update(updated_active_model.clone()) - .filter(Column::Id.eq(vec![1])) + .filter(Column::Id.eq(vec![1, 2, 3])) .exec(db) .await?; @@ -61,11 +61,11 @@ pub async fn create_and_update(db: &DatabaseConnection) -> Result<(), DbErr> { assert_eq!( Entity::find() - .filter(Column::Id.eq(vec![1])) + .filter(Column::Id.eq(vec![1, 2, 3])) .one(db) .await?, Some(Model { - id: vec![1], + id: vec![1, 2, 3], value: "First Row (Updated)".to_owned(), }) ); diff --git a/tests/common/features/schema.rs b/tests/common/features/schema.rs index b6cecab0..fe1c7ea3 100644 --- a/tests/common/features/schema.rs +++ b/tests/common/features/schema.rs @@ -1,8 +1,10 @@ pub use super::super::bakery_chain::*; use super::*; -use crate::common::setup::create_table; -use sea_orm::{error::*, sea_query, DatabaseConnection, DbConn, ExecResult}; +use crate::common::setup::{create_table, create_table_without_asserts}; +use sea_orm::{ + error::*, sea_query, ConnectionTrait, DatabaseConnection, DbBackend, DbConn, ExecResult, +}; use sea_query::{ColumnDef, ForeignKeyCreateStatement}; pub async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> { @@ -103,14 +105,15 @@ pub async fn create_self_join_table(db: &DbConn) -> Result { } pub async fn create_byte_primary_key_table(db: &DbConn) -> Result { + let mut primary_key_col = ColumnDef::new(byte_primary_key::Column::Id); + match db.get_database_backend() { + DbBackend::MySql => primary_key_col.binary_len(3), + DbBackend::Sqlite | DbBackend::Postgres => primary_key_col.binary(), + }; + let stmt = sea_query::Table::create() .table(byte_primary_key::Entity) - .col( - ColumnDef::new(byte_primary_key::Column::Id) - .binary() - .not_null() - .primary_key(), - ) + .col(primary_key_col.not_null().primary_key()) .col( ColumnDef::new(byte_primary_key::Column::Value) .string() @@ -118,5 +121,5 @@ pub async fn create_byte_primary_key_table(db: &DbConn) -> Result( where E: EntityTrait, { + let builder = db.get_database_backend(); + assert_eq!( + builder.build(&Schema::create_table_from_entity(entity)), + builder.build(create) + ); + + create_table_without_asserts(db, create).await +} + +pub async fn create_table_without_asserts( + db: &DbConn, + create: &TableCreateStatement, +) -> Result { let builder = db.get_database_backend(); if builder != DbBackend::Sqlite { let stmt = builder.build( @@ -92,11 +105,5 @@ where ); db.execute(stmt).await?; } - - let stmt = builder.build(create); - assert_eq!( - builder.build(&Schema::create_table_from_entity(entity)), - stmt - ); - db.execute(stmt).await + db.execute(builder.build(create)).await }