From 618ebefe36cbd3f9c45a2fef439aba27fc3caf7d Mon Sep 17 00:00:00 2001 From: Reverier-Xu Date: Tue, 28 Feb 2023 13:59:36 +0800 Subject: [PATCH 1/4] Support `None` value for unselected Optional columns, closes #1507 --- src/executor/query.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/executor/query.rs b/src/executor/query.rs index 6f4573064..0ed766fec 100644 --- a/src/executor/query.rs +++ b/src/executor/query.rs @@ -140,6 +140,7 @@ impl TryGetable for Option { match T::try_get_by(res, index) { Ok(v) => Ok(Some(v)), Err(TryGetError::Null(_)) => Ok(None), + Err(TryGetError::DbErr(DbErr::Query(RuntimeErr::SqlxError(ColumnNotFound(_))))) => Ok(None), Err(e) => Err(e), } } @@ -482,6 +483,7 @@ impl TryGetable for Decimal { #[cfg(feature = "with-bigdecimal")] use bigdecimal::BigDecimal; +use sqlx::Error::ColumnNotFound; #[cfg(feature = "with-bigdecimal")] impl TryGetable for BigDecimal { From 8e24ef630047b4790d2d1a462134ade2affd688a Mon Sep 17 00:00:00 2001 From: Reverier-Xu Date: Tue, 28 Feb 2023 13:59:36 +0800 Subject: [PATCH 2/4] Support `None` value for unselected Optional columns, closes #1507 --- src/executor/query.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/executor/query.rs b/src/executor/query.rs index 6f4573064..2b91d6d4a 100644 --- a/src/executor/query.rs +++ b/src/executor/query.rs @@ -140,6 +140,7 @@ impl TryGetable for Option { match T::try_get_by(res, index) { Ok(v) => Ok(Some(v)), Err(TryGetError::Null(_)) => Ok(None), + Err(TryGetError::DbErr(DbErr::Query(RuntimeErr::SqlxError(sqlx::Error::ColumnNotFound(_))))) => Ok(None), Err(e) => Err(e), } } From 5efb47e6278d24b4502b9992e3b3381a640bf2e4 Mon Sep 17 00:00:00 2001 From: Reverier-Xu Date: Tue, 7 Mar 2023 12:16:59 +0800 Subject: [PATCH 3/4] fix rustfmt and cfg control issues --- src/executor/query.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/executor/query.rs b/src/executor/query.rs index 2b91d6d4a..d4a9108e8 100644 --- a/src/executor/query.rs +++ b/src/executor/query.rs @@ -140,7 +140,10 @@ impl TryGetable for Option { match T::try_get_by(res, index) { Ok(v) => Ok(Some(v)), Err(TryGetError::Null(_)) => Ok(None), - Err(TryGetError::DbErr(DbErr::Query(RuntimeErr::SqlxError(sqlx::Error::ColumnNotFound(_))))) => Ok(None), + #[cfg(feature = "sqlx-dep")] + Err(TryGetError::DbErr(DbErr::Query(RuntimeErr::SqlxError( + sqlx::Error::ColumnNotFound(_), + )))) => Ok(None), Err(e) => Err(e), } } From 79ee0d05117ebbe6093b61a9e01824e409e2b4a8 Mon Sep 17 00:00:00 2001 From: Reverier-Xu Date: Tue, 7 Mar 2023 12:17:17 +0800 Subject: [PATCH 4/4] add test case for #1513 --- tests/query_tests.rs | 45 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/tests/query_tests.rs b/tests/query_tests.rs index 9d22c7b04..d613a6a82 100644 --- a/tests/query_tests.rs +++ b/tests/query_tests.rs @@ -2,7 +2,7 @@ pub mod common; pub use common::{bakery_chain::*, setup::*, TestContext}; pub use sea_orm::entity::*; -pub use sea_orm::{ConnectionTrait, QueryFilter}; +pub use sea_orm::{ConnectionTrait, QueryFilter, QuerySelect}; // Run the test locally: // DATABASE_URL="mysql://root:@localhost" cargo test --features sqlx-mysql,runtime-async-std --test query_tests @@ -222,3 +222,46 @@ pub async fn find_all_filter_with_results() { ctx.delete().await; } + +#[sea_orm_macros::test] +#[cfg(any( + feature = "sqlx-mysql", + feature = "sqlx-sqlite", + feature = "sqlx-postgres" +))] +pub async fn select_only_exclude_option_fields() { + let ctx = TestContext::new("select_only_exclude_option_fields").await; + create_tables(&ctx.db).await.unwrap(); + + let _ = customer::ActiveModel { + name: Set("Alice".to_owned()), + notes: Set(Some("Want to communicate with Bob".to_owned())), + ..Default::default() + } + .save(&ctx.db) + .await + .expect("could not insert customer"); + + let _ = customer::ActiveModel { + name: Set("Bob".to_owned()), + notes: Set(Some("Just listening".to_owned())), + ..Default::default() + } + .save(&ctx.db) + .await + .expect("could not insert customer"); + + let customers = Customer::find() + .select_only() + .column(customer::Column::Id) + .column(customer::Column::Name) + .all(&ctx.db) + .await + .unwrap(); + + assert_eq!(customers.len(), 2); + assert_eq!(customers[0].notes, None); + assert_eq!(customers[1].notes, None); + + ctx.delete().await; +}