diff --git a/src/executor/query.rs b/src/executor/query.rs index 964559453..3c1a9184d 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 000000000..173efc93f --- /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, 2, 3], + 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, 2, 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, 2, 3])) + .exec(db) + .await?; + + assert_eq!(update_res, updated_active_model); + + assert_eq!( + Entity::find() + .filter(Column::Id.eq(vec![1, 2, 3])) + .one(db) + .await?, + Some(Model { + id: vec![1, 2, 3], + 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 000000000..7578e3c85 --- /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 1e709edfc..186256ae3 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 7e6f6424b..fe1c7ea3c 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> { @@ -10,6 +12,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 +103,23 @@ 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 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(primary_key_col.not_null().primary_key()) + .col( + ColumnDef::new(byte_primary_key::Column::Value) + .string() + .not_null(), + ) + .to_owned(); + + create_table_without_asserts(db, &stmt).await +} diff --git a/tests/common/setup/mod.rs b/tests/common/setup/mod.rs index bbe8baa77..dfa1e29c5 100644 --- a/tests/common/setup/mod.rs +++ b/tests/common/setup/mod.rs @@ -82,6 +82,19 @@ pub async fn create_table( 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 }