Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions c/driver/framework/base_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

#include <arrow-adbc/adbc.h>

#include "fmt/core.h"

#include "driver/framework/status.h"

/// \file base.h ADBC Driver Framework
Expand All @@ -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.
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 0 additions & 4 deletions c/driver/framework/status.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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) \
Expand All @@ -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 { \
Expand Down
2 changes: 1 addition & 1 deletion c/driver/postgresql/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 0 additions & 1 deletion c/driver/postgresql/result_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#include <string>
#include <vector>

#define ADBC_FRAMEWORK_USE_FMT
#include "driver/framework/status.h"
#include "error.h"

Expand Down
2 changes: 1 addition & 1 deletion c/driver/sqlite/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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)
1 change: 0 additions & 1 deletion c/driver/sqlite/sqlite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
71 changes: 71 additions & 0 deletions c/driver/sqlite/sqlite_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
20 changes: 10 additions & 10 deletions c/subprojects/fmt.wrap
Original file line number Diff line number Diff line change
@@ -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
10 changes: 8 additions & 2 deletions docs/source/cpp/recipe_driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions python/adbc_driver_sqlite/tests/test_lowlevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion r/adbcdrivermanager/src/Makevars
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
2 changes: 1 addition & 1 deletion r/adbcdrivermanager/src/Makevars.win
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
32 changes: 17 additions & 15 deletions r/adbcdrivermanager/tests/testthat/test-options.R
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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),
Expand Down
Loading