From d111df8a86fc650b77c0b10268f47a1a31c8abac Mon Sep 17 00:00:00 2001 From: Chris Rudd Date: Wed, 5 Feb 2025 15:30:02 -0600 Subject: [PATCH] RunQueryDsl: match same trait constraints as diesel This resolves issue https://github.com/weiznich/diesel_async/issues/142 As it more closely matches the Ts that diesel::RunQueryDsl is implemented for as opposed to all Ts --- src/run_query_dsl/mod.rs | 8 +- tests/lib.rs | 1 + tests/run_query_dsl_impl_match.rs | 148 ++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 tests/run_query_dsl_impl_match.rs diff --git a/src/run_query_dsl/mod.rs b/src/run_query_dsl/mod.rs index f3767ee..7dd2d22 100644 --- a/src/run_query_dsl/mod.rs +++ b/src/run_query_dsl/mod.rs @@ -66,7 +66,7 @@ pub mod methods { /// to call `load` from generic code. /// /// [`RunQueryDsl`]: super::RunQueryDsl - pub trait LoadQuery<'query, Conn: AsyncConnection, U> { + pub trait LoadQuery<'query, Conn: AsyncConnection, U>: RunQueryDsl { /// The future returned by [`LoadQuery::internal_load`] type LoadFuture<'conn>: Future>> + Send where @@ -85,7 +85,7 @@ pub mod methods { Conn: AsyncConnection, U: Send, DB: Backend + 'static, - T: AsQuery + Send + 'query, + T: AsQuery + RunQueryDsl + Send + 'query, T::Query: QueryFragment + QueryId + Send + 'query, T::SqlType: CompatibleType, U: FromSqlRow + Send + 'static, @@ -641,7 +641,9 @@ pub trait RunQueryDsl: Sized { } } -impl RunQueryDsl for T {} +// Note: Match the same types that diesel::RunQueryDsl applies to this +// seems safe currently, as the trait imposes no restrictions based on Conn, only on T. +impl RunQueryDsl for T where T: diesel::query_builder::AsQuery {} /// Sugar for types which implement both `AsChangeset` and `Identifiable` /// diff --git a/tests/lib.rs b/tests/lib.rs index 22701c8..578f56c 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -10,6 +10,7 @@ mod custom_types; mod instrumentation; #[cfg(any(feature = "bb8", feature = "deadpool", feature = "mobc"))] mod pooling; +mod run_query_dsl_impl_match; #[cfg(feature = "async-connection-wrapper")] mod sync_wrapper; mod type_check; diff --git a/tests/run_query_dsl_impl_match.rs b/tests/run_query_dsl_impl_match.rs new file mode 100644 index 0000000..f028963 --- /dev/null +++ b/tests/run_query_dsl_impl_match.rs @@ -0,0 +1,148 @@ +use super::{connection, users, User}; +use diesel::prelude::*; +use diesel_async::RunQueryDsl; + +#[derive(Debug, QueryableByName, PartialEq)] +struct CountType { + #[diesel(sql_type = diesel::sql_types::BigInt)] + pub count: i64, +} + +#[tokio::test] +async fn test_boxed_sql() { + use diesel::query_builder::BoxedSqlQuery; + + let mut con = connection().await; + + let boxed: BoxedSqlQuery<_, _> = + diesel::sql_query("select count(*) as count from users").into_boxed(); + + let result = boxed.get_result::(&mut con).await.unwrap(); + + assert_eq!(result.count, 0); +} + +#[tokio::test] +async fn test_select_statement() { + use diesel::query_builder::SelectStatement; + + let mut con = connection().await; + + let select: SelectStatement<_, _, _, _, _, _, _> = users::table.select(User::as_select()); + + let result = select.get_results(&mut con).await.unwrap(); + + assert_eq!(result.len(), 0); +} + +#[tokio::test] +async fn test_sql_query() { + use diesel::query_builder::SqlQuery; + + let mut con = connection().await; + + let sql: SqlQuery<_> = diesel::sql_query("select count(*) as count from users"); + + let result: CountType = sql.get_result(&mut con).await.unwrap(); + + assert_eq!(result.count, 0); +} + +#[tokio::test] +async fn test_unchecked_bind() { + use diesel::expression::UncheckedBind; + use diesel::sql_types::{BigInt, Text}; + + let mut con = connection().await; + + let unchecked: UncheckedBind<_, _> = + diesel::dsl::sql::("SELECT count(id) FROM users WHERE name = ") + .bind::("Bob"); + + let result = unchecked.get_result(&mut con).await; + + assert_eq!(Ok(0), result); +} + +#[tokio::test] +async fn test_alias() { + use diesel::query_source::Alias; + + let mut con = connection().await; + + let aliased: Alias<_> = diesel::alias!(users as other); + + let result = aliased.get_results::(&mut con).await.unwrap(); + + assert_eq!(result.len(), 0); +} + +#[tokio::test] +async fn test_boxed_select() { + use diesel::query_builder::BoxedSelectStatement; + + let mut con = connection().await; + + let select: BoxedSelectStatement<_, _, _, _> = + users::table.select(User::as_select()).into_boxed(); + + let result = select.get_results(&mut con).await.unwrap(); + + assert_eq!(result.len(), 0); +} + +#[tokio::test] +async fn test_sql_literal() { + use diesel::expression::SqlLiteral; + use diesel::sql_types::Integer; + + let mut con = connection().await; + + let literal: SqlLiteral<_> = diesel::dsl::sql::("SELECT 6"); + + let result = literal.get_result(&mut con).await; + + assert_eq!(Ok(6), result); +} + +#[tokio::test] +async fn test_delete() { + use diesel::query_builder::DeleteStatement; + + let mut con = connection().await; + + let delete: DeleteStatement<_, _, _> = diesel::delete(users::table); + + let result = delete.execute(&mut con).await; + + assert_eq!(Ok(0), result); +} + +#[tokio::test] +async fn test_insert_statement() { + use diesel::query_builder::InsertStatement; + + let mut con = connection().await; + + let inserted_names: InsertStatement<_, _, _, _> = + diesel::insert_into(users::table).values(users::name.eq("Timmy")); + + let result = inserted_names.execute(&mut con).await; + + assert_eq!(Ok(1), result); +} + +#[tokio::test] +async fn test_update_statement() { + use diesel::query_builder::UpdateStatement; + + let mut con = connection().await; + + let update: UpdateStatement<_, _, _, _> = diesel::update(users::table) + .set(users::name.eq("Jim")) + .filter(users::name.eq("Sean")); + + let result = update.execute(&mut con).await; + + assert_eq!(Ok(0), result); +}