This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new 049b3366e fix(rust/ffi): set rows_affected to -1 on the query path of 
ExecuteQuery (#4469)
049b3366e is described below

commit 049b3366efcbc5b809440df0f307425895ccbf91
Author: Fredrik Fornwall <[email protected]>
AuthorDate: Wed Jul 8 01:56:44 2026 +0200

    fix(rust/ffi): set rows_affected to -1 on the query path of ExecuteQuery 
(#4469)
    
    Closes #4468.
    
    Signed-off-by: Fredrik Fornwall <[email protected]>
---
 rust/driver/dummy/tests/driver_exporter_dummy.rs | 68 ++++++++++++++++++++++++
 rust/ffi/src/driver_exporter.rs                  |  3 ++
 2 files changed, 71 insertions(+)

diff --git a/rust/driver/dummy/tests/driver_exporter_dummy.rs 
b/rust/driver/dummy/tests/driver_exporter_dummy.rs
index b64d2016c..b9bc98941 100644
--- a/rust/driver/dummy/tests/driver_exporter_dummy.rs
+++ b/rust/driver/dummy/tests/driver_exporter_dummy.rs
@@ -19,20 +19,24 @@
 /// directly using the Rust API (native) and through the exported driver via 
the
 /// driver manager (exported). That allows us to test that data correctly 
round-trip
 /// between C and Rust.
+use std::ffi::CString;
 use std::ops::Deref;
 use std::sync::Arc;
 
+use arrow_array::ffi_stream::FFI_ArrowArrayStream;
 use arrow_array::{Array, Float64Array, Int64Array, RecordBatch, 
RecordBatchReader, StringArray};
 use arrow_schema::{DataType, Field, Schema};
 use arrow_select::concat::concat_batches;
 
 use adbc_core::Statement;
+use adbc_core::constants::ADBC_STATUS_OK;
 use adbc_core::options::{
     AdbcVersion, InfoCode, IngestMode, IsolationLevel, ObjectDepth, 
OptionConnection,
     OptionDatabase, OptionStatement,
 };
 use adbc_core::{Connection, Database, Driver, Optionable, schemas};
 use adbc_driver_manager::{ManagedConnection, ManagedDatabase, ManagedDriver, 
ManagedStatement};
+use adbc_ffi::{FFI_AdbcConnection, FFI_AdbcDatabase, FFI_AdbcError, 
FFI_AdbcStatement, FFIDriver};
 
 use adbc_dummy::{DummyConnection, DummyDatabase, DummyDriver, DummyStatement, 
SingleBatchReader};
 
@@ -590,6 +594,70 @@ fn test_statement_execute_query() {
     assert_eq!(exported_data, native_data);
 }
 
+// Driven at the C ABI (unlike the other tests): the driver manager passes a 
NULL
+// `rows_affected` on the query path, so the -1 the exporter must write there 
is not
+// observable through the high-level `Statement::execute`.
+#[test]
+fn test_statement_execute_query_sets_rows_affected() {
+    let driver = DummyDriver::ffi_driver();
+    let mut error = FFI_AdbcError::default();
+    let err = &mut error as *mut FFI_AdbcError;
+
+    unsafe {
+        let mut database = FFI_AdbcDatabase::default();
+        assert_eq!(
+            driver.DatabaseNew.unwrap()(&mut database, err),
+            ADBC_STATUS_OK
+        );
+        assert_eq!(
+            driver.DatabaseInit.unwrap()(&mut database, err),
+            ADBC_STATUS_OK
+        );
+
+        let mut connection = FFI_AdbcConnection::default();
+        assert_eq!(
+            driver.ConnectionNew.unwrap()(&mut connection, err),
+            ADBC_STATUS_OK
+        );
+        assert_eq!(
+            driver.ConnectionInit.unwrap()(&mut connection, &mut database, 
err),
+            ADBC_STATUS_OK
+        );
+
+        let mut statement = FFI_AdbcStatement::default();
+        assert_eq!(
+            driver.StatementNew.unwrap()(&mut connection, &mut statement, err),
+            ADBC_STATUS_OK
+        );
+        let query = CString::new("SELECT 1").unwrap();
+        assert_eq!(
+            driver.StatementSetSqlQuery.unwrap()(&mut statement, 
query.as_ptr(), err),
+            ADBC_STATUS_OK
+        );
+
+        // Seed `rows_affected` with a value the exporter must overwrite with 
-1.
+        let mut stream = FFI_ArrowArrayStream::empty();
+        let mut rows_affected: i64 = 42;
+        assert_eq!(
+            driver.StatementExecuteQuery.unwrap()(
+                &mut statement,
+                &mut stream,
+                &mut rows_affected,
+                err,
+            ),
+            ADBC_STATUS_OK
+        );
+        assert_eq!(
+            rows_affected, -1,
+            "a query must report rows_affected = -1 (not known), not a stale 
value"
+        );
+
+        driver.StatementRelease.unwrap()(&mut statement, err);
+        driver.ConnectionRelease.unwrap()(&mut connection, err);
+        driver.DatabaseRelease.unwrap()(&mut database, err);
+    }
+}
+
 #[test]
 fn test_statement_execute_schema() {
     let (_, _, _, mut exported_statement) = get_exported();
diff --git a/rust/ffi/src/driver_exporter.rs b/rust/ffi/src/driver_exporter.rs
index 1a41d100b..b1bb5e90a 100644
--- a/rust/ffi/src/driver_exporter.rs
+++ b/rust/ffi/src/driver_exporter.rs
@@ -1728,6 +1728,9 @@ extern "C" fn statement_execute_query<DriverType: Driver 
+ 'static>(
             let reader = Box::new(reader);
             let reader = FFI_ArrowArrayStream::new(reader);
             unsafe { std::ptr::write_unaligned(out, reader) };
+            if !rows_affected.is_null() {
+                unsafe { std::ptr::write_unaligned(rows_affected, -1) };
+            }
         } else {
             let rows_affected_value = check_err!(statement.execute_update(), 
error).unwrap_or(-1);
             if !rows_affected.is_null() {

Reply via email to