diff --git a/sqlx-core/src/postgres/executor.rs b/sqlx-core/src/postgres/executor.rs index 2c457eae..67be5c61 100644 --- a/sqlx-core/src/postgres/executor.rs +++ b/sqlx-core/src/postgres/executor.rs @@ -272,7 +272,8 @@ impl super::PgConnection { }; let result = match self.step().await? { - Some(Step::RowDesc(desc)) => desc, + Some(Step::RowDesc(desc)) => Some(desc), + Some(Step::NoData) => None, step => { return Err(protocol_err!("expected RowDescription; received {:?}", step).into()); @@ -287,7 +288,8 @@ impl super::PgConnection { .collect::>() .into_boxed_slice(), result_columns: result - .fields + .map(|r| r.fields) + .unwrap_or_default() .into_vec() .into_iter() // TODO: Should [Column] just wrap [protocol::Field] ? diff --git a/sqlx-macros/src/query_macros/query.rs b/sqlx-macros/src/query_macros/query.rs index 3e4628e7..a0377341 100644 --- a/sqlx-macros/src/query_macros/query.rs +++ b/sqlx-macros/src/query_macros/query.rs @@ -25,11 +25,32 @@ where let args = args::quote_args(&input, &describe)?; + let arg_names = &input.arg_names; + let args_count = arg_names.len(); + let arg_indices = (0..args_count).map(|i| syn::Index::from(i)); + let arg_indices_2 = arg_indices.clone(); + let db_path = ::quotable_path(); + if describe.result_columns.is_empty() { - return Ok(quote! {{ - #args - sqlx::query_as_mapped(#sql, |_| Ok(())).bind_all(args) - }}); + return Ok(quote! { + macro_rules! macro_result { + (#($#arg_names:expr),*) => {{ + use sqlx::arguments::Arguments as _; + + #args + + let mut query_args = <#db_path as sqlx::Database>::Arguments::default(); + query_args.reserve( + #args_count, + 0 #(+ sqlx::encode::Encode::<#db_path>::size_hint(args.#arg_indices))* + ); + + #(query_args.add(args.#arg_indices_2);)* + + sqlx::query_as_mapped(#sql, |_| Ok(())).bind_all(query_args) + } + }} + }); } let columns = output::columns_to_rust(&describe)?; @@ -50,11 +71,6 @@ where .collect::(); let output = output::quote_query_as::(sql, &record_type, &columns); - let arg_names = &input.arg_names; - let args_count = arg_names.len(); - let arg_indices = (0..args_count).map(|i| syn::Index::from(i)); - let arg_indices_2 = arg_indices.clone(); - let db_path = ::quotable_path(); Ok(quote! { macro_rules! macro_result { diff --git a/tests/postgres-macros.rs b/tests/postgres-macros.rs index 54dd5c49..7ff30ec9 100644 --- a/tests/postgres-macros.rs +++ b/tests/postgres-macros.rs @@ -1,4 +1,4 @@ -use sqlx::{Connect, PgConnection}; +use sqlx::{Connect, Executor, PgConnection}; #[cfg_attr(feature = "runtime-async-std", async_std::test)] #[cfg_attr(feature = "runtime-tokio", tokio::test)] @@ -19,7 +19,19 @@ async fn test_query() -> anyhow::Result<()> { #[cfg_attr(feature = "runtime-async-std", async_std::test)] #[cfg_attr(feature = "runtime-tokio", tokio::test)] -async fn test_query_file() -> anyhow::Result<()> { +async fn test_no_result() -> anyhow::Result<()> { + let mut conn = connect().await?; + + let _ = sqlx::query!("DELETE FROM pg_enum") + .execute(&mut conn) + .await?; + + Ok(()) +} + +#[cfg_attr(feature = "runtime-async-std", async_std::test)] +#[cfg_attr(feature = "runtime-tokio", tokio::test)] +async fn _file() -> anyhow::Result<()> { let mut conn = connect().await?; let account = sqlx::query_file!("tests/test-query.sql")