From 52e95c1ce1621fdf0b033b9771f6e06671eb803c Mon Sep 17 00:00:00 2001
From: David Li
Date: Tue, 4 Aug 2026 10:54:04 +0900
Subject: [PATCH 1/2] feat(c/driver/sqlite): ensure batch rows option can be
retrieved
The getter existed, but the framework needed to be extended to also
allow fetching it as a string, and tests were added.
Closes #3456.
Assisted-by: GPT-5.6 Sol
---
c/driver/framework/base_driver.h | 16 +++--
c/driver/sqlite/sqlite_test.cc | 71 +++++++++++++++++++
.../adbc_driver_sqlite/tests/test_lowlevel.py | 7 ++
3 files changed, 90 insertions(+), 4 deletions(-)
diff --git a/c/driver/framework/base_driver.h b/c/driver/framework/base_driver.h
index bebdffea6b..c0edad79a8 100644
--- a/c/driver/framework/base_driver.h
+++ b/c/driver/framework/base_driver.h
@@ -169,11 +169,19 @@ class Option {
return std::visit(
[&](auto&& value) -> AdbcStatusCode {
using T = std::decay_t;
- if constexpr (std::is_same_v) {
- size_t value_size_with_terminator = value.size() + 1;
+ if constexpr (std::is_same_v || std::is_same_v) {
+ std::string formatted;
+ std::string_view string_value;
+ if constexpr (std::is_same_v) {
+ string_value = value;
+ } else {
+ formatted = std::to_string(value);
+ string_value = formatted;
+ }
+ size_t value_size_with_terminator = string_value.size() + 1;
if (*length >= value_size_with_terminator) {
- std::memcpy(out, value.data(), value.size());
- out[value.size()] = 0;
+ std::memcpy(out, string_value.data(), string_value.size());
+ out[string_value.size()] = 0;
}
*length = value_size_with_terminator;
return ADBC_STATUS_OK;
diff --git a/c/driver/sqlite/sqlite_test.cc b/c/driver/sqlite/sqlite_test.cc
index 243449eb07..77ad60e857 100644
--- a/c/driver/sqlite/sqlite_test.cc
+++ b/c/driver/sqlite/sqlite_test.cc
@@ -454,6 +454,77 @@ TEST(SqliteUriWrapper, SqliteUriFilename) {
adbc_validation::IsOkStatus(&error));
}
+TEST(SqliteOptions, BatchRowsGetOption) {
+ struct AdbcError error = ADBC_ERROR_INIT;
+ adbc_validation::Handle database;
+ adbc_validation::Handle connection;
+ adbc_validation::Handle statement;
+ constexpr const char* kBatchRows = "adbc.sqlite.query.batch_rows";
+
+ ASSERT_THAT(AdbcDatabaseNew(&database.value, &error),
+ adbc_validation::IsOkStatus(&error));
+
+ int64_t int_value = 0;
+ ASSERT_THAT(AdbcDatabaseGetOptionInt(&database.value, kBatchRows, &int_value, &error),
+ adbc_validation::IsOkStatus(&error));
+ EXPECT_EQ(1024, int_value);
+
+ char too_small[2] = {'x', 'x'};
+ size_t length = sizeof(too_small);
+ ASSERT_THAT(
+ AdbcDatabaseGetOption(&database.value, kBatchRows, too_small, &length, &error),
+ adbc_validation::IsOkStatus(&error));
+ EXPECT_EQ(5, length);
+ EXPECT_THAT(too_small, ::testing::ElementsAre('x', 'x'));
+
+ ASSERT_THAT(AdbcDatabaseSetOption(&database.value, kBatchRows, "41", &error),
+ adbc_validation::IsOkStatus(&error));
+ char string_value[3] = {};
+ length = sizeof(string_value);
+ ASSERT_THAT(
+ AdbcDatabaseGetOption(&database.value, kBatchRows, string_value, &length, &error),
+ adbc_validation::IsOkStatus(&error));
+ EXPECT_EQ(3, length);
+ EXPECT_STREQ("41", string_value);
+
+ ASSERT_THAT(AdbcDatabaseInit(&database.value, &error),
+ adbc_validation::IsOkStatus(&error));
+ ASSERT_THAT(AdbcConnectionNew(&connection.value, &error),
+ adbc_validation::IsOkStatus(&error));
+ ASSERT_THAT(AdbcConnectionInit(&connection.value, &database.value, &error),
+ adbc_validation::IsOkStatus(&error));
+ ASSERT_THAT(
+ AdbcConnectionGetOptionInt(&connection.value, kBatchRows, &int_value, &error),
+ adbc_validation::IsOkStatus(&error));
+ EXPECT_EQ(41, int_value);
+
+ ASSERT_THAT(AdbcStatementNew(&connection.value, &statement.value, &error),
+ adbc_validation::IsOkStatus(&error));
+ ASSERT_THAT(AdbcStatementGetOptionInt(&statement.value, kBatchRows, &int_value, &error),
+ adbc_validation::IsOkStatus(&error));
+ EXPECT_EQ(41, int_value);
+
+ ASSERT_THAT(AdbcStatementSetOptionInt(&statement.value, kBatchRows, 42, &error),
+ adbc_validation::IsOkStatus(&error));
+ char statement_value[3] = {};
+ length = sizeof(statement_value);
+ ASSERT_THAT(AdbcStatementGetOption(&statement.value, kBatchRows, statement_value,
+ &length, &error),
+ adbc_validation::IsOkStatus(&error));
+ EXPECT_EQ(3, length);
+ EXPECT_STREQ("42", statement_value);
+
+ ASSERT_THAT(AdbcStatementSetOption(&statement.value, "adbc.statement.bind_by_name",
+ ADBC_OPTION_VALUE_ENABLED, &error),
+ adbc_validation::IsOkStatus(&error));
+ char bind_by_name[sizeof(ADBC_OPTION_VALUE_ENABLED)] = {};
+ length = sizeof(bind_by_name);
+ ASSERT_THAT(AdbcStatementGetOption(&statement.value, "adbc.statement.bind_by_name",
+ bind_by_name, &length, &error),
+ adbc_validation::IsOkStatus(&error));
+ EXPECT_STREQ(ADBC_OPTION_VALUE_ENABLED, bind_by_name);
+}
+
class SqliteStatementTest : public ::testing::Test,
public adbc_validation::StatementTest {
public:
diff --git a/python/adbc_driver_sqlite/tests/test_lowlevel.py b/python/adbc_driver_sqlite/tests/test_lowlevel.py
index 9c8afcac3b..f1f2174a6f 100644
--- a/python/adbc_driver_sqlite/tests/test_lowlevel.py
+++ b/python/adbc_driver_sqlite/tests/test_lowlevel.py
@@ -49,6 +49,13 @@ def test_options(sqlite):
adbc_driver_sqlite.StatementOptions.BATCH_ROWS.value: "1",
}
)
+ assert (
+ stmt.get_option(adbc_driver_sqlite.StatementOptions.BATCH_ROWS.value) == "1"
+ )
+ assert (
+ stmt.get_option_int(adbc_driver_sqlite.StatementOptions.BATCH_ROWS.value)
+ == 1
+ )
stmt.set_sql_query("SELECT 1")
stream, _ = stmt.execute_query()
reader = pyarrow.RecordBatchReader._import_from_c(stream.address)
From 1c30ea75e19f75bdaa4d52b53c8a8d71d084bca3 Mon Sep 17 00:00:00 2001
From: David Li
Date: Tue, 4 Aug 2026 13:47:50 +0900
Subject: [PATCH 2/2] fix r
---
r/adbcdrivermanager/tests/testthat/test-options.R | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/r/adbcdrivermanager/tests/testthat/test-options.R b/r/adbcdrivermanager/tests/testthat/test-options.R
index 8d978f838c..d13068162a 100644
--- a/r/adbcdrivermanager/tests/testthat/test-options.R
+++ b/r/adbcdrivermanager/tests/testthat/test-options.R
@@ -251,34 +251,31 @@ test_that("void driver errors getting bytes option of incorrect type", {
)
})
-test_that("void driver errors getting integer option of incorrect type", {
+test_that("void driver errors getting integer option as bytes", {
db <- adbc_database_init(adbc_driver_void())
adbc_database_set_options(db, list("some_key" = 123L))
- expect_error(
- adbc_database_get_option(db, "some_key"),
- class = "adbc_status_not_found"
- )
-
expect_error(
adbc_database_get_option_bytes(db, "some_key"),
class = "adbc_status_not_found"
)
-
-
})
test_that("void driver can get integer option of compatible type", {
db <- adbc_database_init(adbc_driver_void())
adbc_database_set_options(db, list("some_key" = 123L))
+ expect_identical(
+ adbc_database_get_option(db, "some_key"),
+ "123"
+ )
+
expect_identical(
adbc_database_get_option_double(db, "some_key"),
123.0
)
})
-
test_that("void driver errors getting double option of incorrect type", {
db <- adbc_database_init(adbc_driver_void())
adbc_database_set_options(db, list("some_key" = 123.4))