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() {