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 c7c43b5c5 feat(c/driver/sqlite): ensure batch rows option can be 
retrieved (#4645)
c7c43b5c5 is described below

commit c7c43b5c58d69287cad4702097b911e7b1a89e66
Author: David Li <[email protected]>
AuthorDate: Tue Sep 8 08:31:32 2026 +0900

    feat(c/driver/sqlite): ensure batch rows option can be retrieved (#4645)
    
    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 <[email protected]>
---
 c/driver/framework/base_driver.h                  | 25 ++++++--
 c/driver/framework/status.h                       |  4 --
 c/driver/postgresql/meson.build                   |  2 +-
 c/driver/postgresql/result_helper.cc              |  1 -
 c/driver/sqlite/meson.build                       |  2 +-
 c/driver/sqlite/sqlite.cc                         |  1 -
 c/driver/sqlite/sqlite_test.cc                    | 71 +++++++++++++++++++++++
 c/subprojects/fmt.wrap                            | 20 +++----
 docs/source/cpp/recipe_driver/CMakeLists.txt      | 10 +++-
 python/adbc_driver_sqlite/tests/test_lowlevel.py  |  7 +++
 r/adbcdrivermanager/src/Makevars                  |  2 +-
 r/adbcdrivermanager/src/Makevars.win              |  2 +-
 r/adbcdrivermanager/tests/testthat/test-options.R | 32 +++++-----
 13 files changed, 136 insertions(+), 43 deletions(-)

diff --git a/c/driver/framework/base_driver.h b/c/driver/framework/base_driver.h
index bebdffea6..578bb3066 100644
--- a/c/driver/framework/base_driver.h
+++ b/c/driver/framework/base_driver.h
@@ -30,6 +30,8 @@
 
 #include <arrow-adbc/adbc.h>
 
+#include "fmt/core.h"
+
 #include "driver/framework/status.h"
 
 /// \file base.h ADBC Driver Framework
@@ -54,8 +56,7 @@ enum class LifecycleState {
   kInitialized,
 };
 
-/// \brief A typed option value wrapper. It currently does not attempt
-/// conversion (i.e., getting a double option as a string).
+/// \brief A typed option value wrapper. Attempts some conversions between 
types.
 class Option {
  public:
   /// \brief The option is unset.
@@ -169,11 +170,23 @@ class Option {
       return std::visit(
           [&](auto&& value) -> AdbcStatusCode {
             using T = std::decay_t<decltype(value)>;
-            if constexpr (std::is_same_v<T, std::string>) {
-              size_t value_size_with_terminator = value.size() + 1;
+            if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, 
int64_t> ||
+                          std::is_same_v<T, double>) {
+              std::string_view string_value;
+              std::string allocated_value;
+              if constexpr (std::is_same_v<T, int64_t>) {
+                allocated_value = fmt::format("{}", value);
+                string_value = allocated_value;
+              } else if constexpr (std::is_same_v<T, double>) {
+                allocated_value = fmt::format("{}", value);
+                string_value = allocated_value;
+              } else {
+                string_value = value;
+              }
+              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/framework/status.h b/c/driver/framework/status.h
index 1fac2272a..6cb400314 100644
--- a/c/driver/framework/status.h
+++ b/c/driver/framework/status.h
@@ -26,10 +26,8 @@
 #include <variant>
 #include <vector>
 
-#if defined(ADBC_FRAMEWORK_USE_FMT)
 #include <fmt/core.h>
 #include <fmt/format.h>
-#endif
 
 #include <arrow-adbc/adbc.h>
 
@@ -326,7 +324,6 @@ STATUS_CTOR(Unknown, UNKNOWN)
 
 }  // namespace adbc::driver::status
 
-#if defined(ADBC_FRAMEWORK_USE_FMT)
 namespace adbc::driver::status::fmt {
 
 #define STATUS_CTOR(NAME, CODE)                                                
         \
@@ -348,7 +345,6 @@ STATUS_CTOR(Unknown, UNKNOWN)
 #undef STATUS_CTOR
 
 }  // namespace adbc::driver::status::fmt
-#endif
 
 #define UNWRAP_ERRNO_IMPL(NAME, CODE, RHS)                                     
          \
   do {                                                                         
          \
diff --git a/c/driver/postgresql/meson.build b/c/driver/postgresql/meson.build
index 7af8f849d..fcb87c01a 100644
--- a/c/driver/postgresql/meson.build
+++ b/c/driver/postgresql/meson.build
@@ -70,7 +70,7 @@ foreach name, conf : postgres_tests
         sources: conf['sources'],
         include_directories: [include_dir, driver_dir, c_dir, safe_math_dir],
         link_with: [adbc_common_lib, adbc_postgres_driver_lib],
-        dependencies: [libpq_dep, adbc_validation_dep],
+        dependencies: [libpq_dep, adbc_validation_dep, fmt_dep],
         cpp_args: cpp_args,
     )
     test('adbc-' + name, exc)
diff --git a/c/driver/postgresql/result_helper.cc 
b/c/driver/postgresql/result_helper.cc
index 2557e8f94..1fcc42a9c 100644
--- a/c/driver/postgresql/result_helper.cc
+++ b/c/driver/postgresql/result_helper.cc
@@ -27,7 +27,6 @@
 #include <string>
 #include <vector>
 
-#define ADBC_FRAMEWORK_USE_FMT
 #include "driver/framework/status.h"
 #include "error.h"
 
diff --git a/c/driver/sqlite/meson.build b/c/driver/sqlite/meson.build
index 6ddc91d03..c34b02486 100644
--- a/c/driver/sqlite/meson.build
+++ b/c/driver/sqlite/meson.build
@@ -49,6 +49,6 @@ exc = executable(
     sources: ['sqlite_test.cc'],
     include_directories: [include_dir, c_dir, driver_dir],
     link_with: [adbc_common_lib, adbc_sqlite3_driver_lib],
-    dependencies: [sqlite3_dep, adbc_validation_dep],
+    dependencies: [sqlite3_dep, adbc_validation_dep, fmt_dep],
 )
 test('adbc-driver-sqlite', exc)
diff --git a/c/driver/sqlite/sqlite.cc b/c/driver/sqlite/sqlite.cc
index 62dec5ab2..6aea5ee14 100644
--- a/c/driver/sqlite/sqlite.cc
+++ b/c/driver/sqlite/sqlite.cc
@@ -26,7 +26,6 @@
 #include <sqlite3.h>
 #include <nanoarrow/nanoarrow.hpp>
 
-#define ADBC_FRAMEWORK_USE_FMT
 #include "driver/framework/base_driver.h"
 #include "driver/framework/connection.h"
 #include "driver/framework/database.h"
diff --git a/c/driver/sqlite/sqlite_test.cc b/c/driver/sqlite/sqlite_test.cc
index 243449eb0..77ad60e85 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<struct AdbcDatabase> database;
+  adbc_validation::Handle<struct AdbcConnection> connection;
+  adbc_validation::Handle<struct AdbcStatement> 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/c/subprojects/fmt.wrap b/c/subprojects/fmt.wrap
index 4e9646010..7e9c5c42b 100644
--- a/c/subprojects/fmt.wrap
+++ b/c/subprojects/fmt.wrap
@@ -1,13 +1,13 @@
 [wrap-file]
-directory = fmt-10.2.0
-source_url = https://github.com/fmtlib/fmt/archive/10.2.0.tar.gz
-source_filename = fmt-10.2.0.tar.gz
-source_hash = 3ca91733a7313a8ad41c0885929415f8ec0a2a31d4dc7e27e9331412f4ca26ac
-patch_filename = fmt_10.2.0-2_patch.zip
-patch_url = https://wrapdb.mesonbuild.com/v2/fmt_10.2.0-2/get_patch
-patch_hash = 2428c3a386a8390c76378f81ef804a297f4edc3b789499dd56629b7902b8ddb7
-source_fallback_url = 
https://github.com/mesonbuild/wrapdb/releases/download/fmt_10.2.0-2/fmt-10.2.0.tar.gz
-wrapdb_version = 10.2.0-2
+directory = fmt-12.0.0
+source_url = https://github.com/fmtlib/fmt/archive/12.0.0.tar.gz
+source_filename = fmt-12.0.0.tar.gz
+source_hash = aa3e8fbb6a0066c03454434add1f1fc23299e85758ceec0d7d2d974431481e40
+source_fallback_url = 
https://github.com/mesonbuild/wrapdb/releases/download/fmt_12.0.0-1/fmt-12.0.0.tar.gz
+patch_filename = fmt_12.0.0-1_patch.zip
+patch_url = https://wrapdb.mesonbuild.com/v2/fmt_12.0.0-1/get_patch
+patch_hash = 307f288ebf3850abf2f0c50ac1fb07de97df9538d39146d802f3c0d6cada8998
+wrapdb_version = 12.0.0-1
 
 [provide]
-fmt = fmt_dep
+dependency_names = fmt
diff --git a/docs/source/cpp/recipe_driver/CMakeLists.txt 
b/docs/source/cpp/recipe_driver/CMakeLists.txt
index b4c6b0619..aae426f30 100644
--- a/docs/source/cpp/recipe_driver/CMakeLists.txt
+++ b/docs/source/cpp/recipe_driver/CMakeLists.txt
@@ -29,6 +29,12 @@ set(CMAKE_CXX_STANDARD 17)
 set(NANOARROW_IPC ON)
 set(NANOARROW_NAMESPACE "DriverExamplePrivate")
 set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+fetchcontent_declare(fmt
+                     GIT_REPOSITORY https://github.com/fmtlib/fmt
+                     GIT_TAG 1be298e1bd68957e4cd352e1f676f00e07dcfb57) # 12.2.0
+fetchcontent_makeavailable(fmt)
+
 fetchcontent_declare(nanoarrow
                      GIT_REPOSITORY 
https://github.com/apache/arrow-nanoarrow.git
                      GIT_TAG apache-arrow-nanoarrow-0.9.0
@@ -43,11 +49,11 @@ add_library(adbc_driver_framework 
../../../../c/driver/framework/utility.cc
                                   ../../../../c/driver/framework/objects.cc)
 target_include_directories(adbc_driver_framework PRIVATE ../../../../c
                                                          ../../../../c/include)
-target_link_libraries(adbc_driver_framework PRIVATE 
nanoarrow::nanoarrow_static)
+target_link_libraries(adbc_driver_framework PRIVATE fmt::fmt 
nanoarrow::nanoarrow_static)
 
 add_library(driver_example SHARED driver_example.cc)
 target_include_directories(driver_example PRIVATE ../../../../c 
../../../../c/include)
-target_link_libraries(driver_example PRIVATE adbc_driver_framework
+target_link_libraries(driver_example PRIVATE adbc_driver_framework fmt::fmt
                                              nanoarrow::nanoarrow_ipc)
 
 install(TARGETS driver_example)
diff --git a/python/adbc_driver_sqlite/tests/test_lowlevel.py 
b/python/adbc_driver_sqlite/tests/test_lowlevel.py
index 9c8afcac3..f1f2174a6 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)
diff --git a/r/adbcdrivermanager/src/Makevars b/r/adbcdrivermanager/src/Makevars
index 5476c6e35..f17dd3681 100644
--- a/r/adbcdrivermanager/src/Makevars
+++ b/r/adbcdrivermanager/src/Makevars
@@ -17,7 +17,7 @@
 
 CXX_STD = CXX20
 CONDA_BUILD ?= "0"
-PKG_CPPFLAGS=-I../src/c/include -I../src/c -I../src/c/vendor -DADBC_EXPORT="" 
-DADBC_CONDA_BUILD=$(CONDA_BUILD)
+PKG_CPPFLAGS=-I../src/c/include -I../src/c -I../src/c/vendor 
-I../src/c/vendor/fmt/include -DADBC_EXPORT="" 
-DADBC_CONDA_BUILD=$(CONDA_BUILD) -DFMT_HEADER_ONLY=1
 
 OBJECTS = driver_test.o \
     error.o \
diff --git a/r/adbcdrivermanager/src/Makevars.win 
b/r/adbcdrivermanager/src/Makevars.win
index 6a086d369..ac0c8cec9 100644
--- a/r/adbcdrivermanager/src/Makevars.win
+++ b/r/adbcdrivermanager/src/Makevars.win
@@ -17,7 +17,7 @@
 
 CXX_STD = CXX20
 CONDA_BUILD ?= "0"
-PKG_CPPFLAGS=-I../src/c/include -I../src/c -I../src/c/vendor -DADBC_EXPORT="" 
-DADBC_CONDA_BUILD=$(CONDA_BUILD)
+PKG_CPPFLAGS=-I../src/c/include -I../src/c -I../src/c/vendor 
-I../src/c/vendor/fmt/include -DADBC_EXPORT="" 
-DADBC_CONDA_BUILD=$(CONDA_BUILD) -DFMT_HEADER_ONLY=1
 PKG_LIBS=-lshell32 -ladvapi32 -luuid
 
 OBJECTS = driver_test.o \
diff --git a/r/adbcdrivermanager/tests/testthat/test-options.R 
b/r/adbcdrivermanager/tests/testthat/test-options.R
index 8d978f838..dc8c2f295 100644
--- a/r/adbcdrivermanager/tests/testthat/test-options.R
+++ b/r/adbcdrivermanager/tests/testthat/test-options.R
@@ -251,43 +251,35 @@ 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", {
+test_that("void driver errors getting double option as incompatible type", {
   db <- adbc_database_init(adbc_driver_void())
   adbc_database_set_options(db, list("some_key" = 123.4))
 
-  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"
@@ -299,6 +291,16 @@ test_that("void driver errors getting double option of 
incorrect type", {
   )
 })
 
+test_that("void driver can get double option of compatible type", {
+  db <- adbc_database_init(adbc_driver_void())
+  adbc_database_set_options(db, list("some_key" = 123.4))
+
+  expect_identical(
+    adbc_database_get_option(db, "some_key"),
+    "123.4"
+  )
+})
+
 test_that("key_value_options works", {
   expect_identical(
     key_value_options(NULL),

Reply via email to