This is an automated email from the ASF dual-hosted git repository.
zeroshade 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 e532053ec feat(c/driver_manager,rust/driver_manager): handle virtual
environments in driver manager (#3320)
e532053ec is described below
commit e532053ece6659c4d2e460914929632e7e4fa865
Author: Matt Topol <[email protected]>
AuthorDate: Wed Aug 27 13:04:27 2025 -0400
feat(c/driver_manager,rust/driver_manager): handle virtual environments in
driver manager (#3320)
Updates the driver manager logic to handle virtual environments used by
venv and conda.
venv will set a `VIRTUAL_ENV` environment variable while conda will set
`CONDA_PREFIX`. If these environment variables are set, then they are
added to the search list of `get_search_paths` / `GetSearchPaths` when
the `LOAD_FLAG_SEARCH_ENV` flag is set.
Also updates the docs to mention this.
---------
Co-authored-by: Ian Cook <[email protected]>
---
c/driver_manager/CMakeLists.txt | 5 +
c/driver_manager/adbc_driver_manager.cc | 140 ++++++++++++++++-----
c/driver_manager/adbc_driver_manager_test.cc | 45 +++----
c/include/arrow-adbc/adbc_driver_manager.h | 30 ++++-
docs/source/format/driver_manifests.rst | 37 ++++--
glib/adbc-glib/database.h | 8 +-
go/adbc/drivermgr/adbc_driver_manager.cc | 140 ++++++++++++++++-----
go/adbc/drivermgr/arrow-adbc/adbc_driver_manager.h | 30 ++++-
.../adbc_driver_manager/_lib.pxd | 4 +
.../adbc_driver_manager/_lib.pyx | 9 ++
r/adbcdrivermanager/R/driver_void.R | 15 +--
r/adbcdrivermanager/man/adbc_driver_load.Rd | 6 +-
r/adbcdrivermanager/man/adbc_load_flags.Rd | 11 +-
r/adbcdrivermanager/src/Makevars | 3 +-
r/adbcdrivermanager/src/Makevars.win | 3 +-
r/adbcdrivermanager/src/init.c | 5 +-
r/adbcdrivermanager/src/radbc.cc | 9 +-
rust/driver_manager/build.rs | 26 ++++
rust/driver_manager/src/lib.rs | 130 ++++++++++++++++---
19 files changed, 510 insertions(+), 146 deletions(-)
diff --git a/c/driver_manager/CMakeLists.txt b/c/driver_manager/CMakeLists.txt
index 21054eed6..64ba340a3 100644
--- a/c/driver_manager/CMakeLists.txt
+++ b/c/driver_manager/CMakeLists.txt
@@ -69,6 +69,11 @@ foreach(LIB_TARGET ${ADBC_LIBRARIES})
${REPOSITORY_ROOT}/c/vendor
${REPOSITORY_ROOT}/c/driver)
target_compile_definitions(${LIB_TARGET} PRIVATE ADBC_EXPORTING)
+ if("$ENV{CONDA_BUILD}" STREQUAL "1")
+ target_compile_definitions(${LIB_TARGET} PRIVATE ADBC_CONDA_BUILD=1)
+ else()
+ target_compile_definitions(${LIB_TARGET} PRIVATE ADBC_CONDA_BUILD=0)
+ endif()
endforeach()
if(ADBC_BUILD_TESTS)
diff --git a/c/driver_manager/adbc_driver_manager.cc
b/c/driver_manager/adbc_driver_manager.cc
index 3044199f2..29bb5bf4a 100644
--- a/c/driver_manager/adbc_driver_manager.cc
+++ b/c/driver_manager/adbc_driver_manager.cc
@@ -159,7 +159,7 @@ std::wstring Utf8Decode(const std::string& str) {
#else
using char_type = char;
-#endif
+#endif // _WIN32
// Driver state
struct DriverInfo {
@@ -239,7 +239,7 @@ AdbcStatusCode LoadDriverFromRegistry(HKEY root, const
std::wstring& driver_name
}
return ADBC_STATUS_OK;
}
-#endif
+#endif // _WIN32
AdbcStatusCode LoadDriverManifest(const std::filesystem::path& driver_manifest,
DriverInfo& info, struct AdbcError* error) {
@@ -273,14 +273,39 @@ AdbcStatusCode LoadDriverManifest(const
std::filesystem::path& driver_manifest,
return ADBC_STATUS_OK;
}
+std::vector<std::filesystem::path> GetEnvPaths(const char_type* env_var) {
+#ifdef _WIN32
+ size_t required_size;
+
+ _wgetenv_s(&required_size, NULL, 0, env_var);
+ if (required_size == 0) {
+ return {};
+ }
+
+ std::wstring path_var;
+ path_var.resize(required_size);
+ _wgetenv_s(&required_size, path_var.data(), required_size, env_var);
+ auto path = Utf8Encode(path_var);
+#else
+ const char* path_var = std::getenv(env_var);
+ if (!path_var) {
+ return {};
+ }
+ std::string path(path_var);
+#endif // _WIN32
+ return InternalAdbcParsePath(path);
+}
+
std::vector<std::filesystem::path> GetSearchPaths(const AdbcLoadFlags levels) {
std::vector<std::filesystem::path> paths;
if (levels & ADBC_LOAD_FLAG_SEARCH_ENV) {
+#ifdef _WIN32
+ static const wchar_t* env_var = L"ADBC_CONFIG_PATH";
+#else
+ static const char* env_var = "ADBC_CONFIG_PATH";
+#endif // _WIN32
// Check the ADBC_CONFIG_PATH environment variable
- const char* env_path = std::getenv("ADBC_CONFIG_PATH");
- if (env_path) {
- paths = InternalAdbcParsePath(env_path);
- }
+ paths = GetEnvPaths(env_var);
}
if (levels & ADBC_LOAD_FLAG_SEARCH_USER) {
@@ -305,7 +330,7 @@ std::vector<std::filesystem::path> GetSearchPaths(const
AdbcLoadFlags levels) {
if (std::filesystem::exists(system_config_dir)) {
paths.push_back(system_config_dir);
}
-#endif
+#endif // defined(__APPLE__)
}
return paths;
@@ -319,7 +344,7 @@ bool HasExtension(const std::filesystem::path& path, const
std::string& ext) {
_wcsnicmp(path_ext.data(), wext.data(), wext.size()) == 0;
#else
return path.extension() == ext;
-#endif
+#endif // _WIN32
}
/// A driver DLL.
@@ -344,9 +369,10 @@ struct ManagedLibrary {
// release() from the DLL - how to handle this?
}
- AdbcStatusCode GetDriverInfo(const std::string_view driver_name,
- const AdbcLoadFlags load_options, DriverInfo&
info,
- struct AdbcError* error) {
+ AdbcStatusCode GetDriverInfo(
+ const std::string_view driver_name, const AdbcLoadFlags load_options,
+ const std::vector<std::filesystem::path>& additional_search_paths,
DriverInfo& info,
+ struct AdbcError* error) {
if (driver_name.empty()) {
SetError(error, "Driver name is empty");
return ADBC_STATUS_INVALID_ARGUMENT;
@@ -405,7 +431,7 @@ struct ManagedLibrary {
static const std::string kPlatformLibrarySuffix = ".dylib";
#else
static const std::string kPlatformLibrarySuffix = ".so";
-#endif
+#endif // defined(_WIN32)
if (HasExtension(driver_path, kPlatformLibrarySuffix)) {
info.lib_path = driver_path;
return Load(driver_path.c_str(), error);
@@ -418,7 +444,7 @@ struct ManagedLibrary {
// not an absolute path, no extension. Let's search the configured paths
// based on the options
- return FindDriver(driver_path, load_options, info, error);
+ return FindDriver(driver_path, load_options, additional_search_paths,
info, error);
}
AdbcStatusCode SearchPaths(const std::filesystem::path& driver_path,
@@ -446,27 +472,52 @@ struct ManagedLibrary {
return ADBC_STATUS_NOT_FOUND;
}
- AdbcStatusCode FindDriver(const std::filesystem::path& driver_path,
- const AdbcLoadFlags load_options, DriverInfo& info,
- struct AdbcError* error) {
+ AdbcStatusCode FindDriver(
+ const std::filesystem::path& driver_path, const AdbcLoadFlags
load_options,
+ const std::vector<std::filesystem::path>& additional_search_paths,
DriverInfo& info,
+ struct AdbcError* error) {
if (driver_path.empty()) {
SetError(error, "Driver path is empty");
return ADBC_STATUS_INVALID_ARGUMENT;
}
+ {
+ // First search the paths in the env var `ADBC_CONFIG_PATH`.
+ // Then search the runtime application-defined additional search paths.
+ auto search_paths = GetSearchPaths(load_options &
ADBC_LOAD_FLAG_SEARCH_ENV);
+ search_paths.insert(search_paths.end(), additional_search_paths.begin(),
+ additional_search_paths.end());
+
+#if ADBC_CONDA_BUILD
+ // Then, if this is a conda build, search in the conda environment if
+ // it is activated.
+ if (load_options & ADBC_LOAD_FLAG_SEARCH_ENV) {
#ifdef _WIN32
- // windows is slightly more complex since we also need to check registry
keys
- // so we can't just grab the search paths only.
- if (load_options & ADBC_LOAD_FLAG_SEARCH_ENV) {
- auto search_paths = GetSearchPaths(ADBC_LOAD_FLAG_SEARCH_ENV);
+ const wchar_t* conda_name = L"CONDA_PREFIX";
+#else
+ const char* conda_name = "CONDA_PREFIX";
+#endif // _WIN32
+ auto venv = GetEnvPaths(conda_name);
+ if (!venv.empty()) {
+ for (const auto& venv_path : venv) {
+ search_paths.push_back(venv_path / "etc" / "adbc");
+ }
+ }
+ }
+#endif // ADBC_CONDA_BUILD
+
auto status = SearchPaths(driver_path, search_paths, info, error);
if (status == ADBC_STATUS_OK) {
return status;
}
}
+ // We searched environment paths and additional search paths (if they
+ // exist), so now search the rest.
+#ifdef _WIN32
+ // On Windows, check registry keys, not just search paths.
if (load_options & ADBC_LOAD_FLAG_SEARCH_USER) {
- // Check the user registry for the driver
+ // Check the user registry for the driver.
auto status =
LoadDriverFromRegistry(HKEY_CURRENT_USER, driver_path.native(),
info, error);
if (status == ADBC_STATUS_OK) {
@@ -481,7 +532,7 @@ struct ManagedLibrary {
}
if (load_options & ADBC_LOAD_FLAG_SEARCH_SYSTEM) {
- // Check the system registry for the driver
+ // Check the system registry for the driver.
auto status =
LoadDriverFromRegistry(HKEY_LOCAL_MACHINE, driver_path.native(),
info, error);
if (status == ADBC_STATUS_OK) {
@@ -498,17 +549,17 @@ struct ManagedLibrary {
info.lib_path = driver_path;
return Load(driver_path.c_str(), error);
#else
- // Otherwise, search the configured paths
- auto search_paths = GetSearchPaths(load_options);
+ // Otherwise, search the configured paths.
+ auto search_paths = GetSearchPaths(load_options &
~ADBC_LOAD_FLAG_SEARCH_ENV);
auto status = SearchPaths(driver_path, search_paths, info, error);
if (status == ADBC_STATUS_NOT_FOUND) {
// If we reach here, we didn't find the driver in any of the paths
- // so let's just attempt to load it as default behavior
+ // so let's just attempt to load it as default behavior.
info.lib_path = driver_path;
return Load(driver_path.c_str(), error);
}
return status;
-#endif
+#endif // _WIN32
}
AdbcStatusCode Load(const char_type* library, struct AdbcError* error) {
@@ -991,6 +1042,7 @@ struct TempDatabase {
std::string entrypoint;
AdbcDriverInitFunc init_func = nullptr;
AdbcLoadFlags load_flags = ADBC_LOAD_FLAG_ALLOW_RELATIVE_PATHS;
+ std::string additional_search_path_list;
};
/// Temporary state while the database is being configured.
@@ -1043,7 +1095,7 @@ std::filesystem::path InternalAdbcUserConfigDir() {
if (!config_dir.empty()) {
config_dir /= "adbc";
}
-#endif
+#endif // defined(_WIN32)
return config_dir;
}
@@ -1362,6 +1414,22 @@ AdbcStatusCode
AdbcDriverManagerDatabaseSetLoadFlags(struct AdbcDatabase* databa
return ADBC_STATUS_OK;
}
+AdbcStatusCode AdbcDriverManagerDatabaseSetAdditionalSearchPathList(
+ struct AdbcDatabase* database, const char* path_list, struct AdbcError*
error) {
+ if (database->private_driver) {
+ SetError(error, "Cannot SetAdditionalSearchPathList after
AdbcDatabaseInit");
+ return ADBC_STATUS_INVALID_STATE;
+ }
+
+ TempDatabase* args = reinterpret_cast<TempDatabase*>(database->private_data);
+ if (path_list) {
+ args->additional_search_path_list.assign(path_list);
+ } else {
+ args->additional_search_path_list.clear();
+ }
+ return ADBC_STATUS_OK;
+}
+
AdbcStatusCode AdbcDriverManagerDatabaseSetInitFunc(struct AdbcDatabase*
database,
AdbcDriverInitFunc
init_func,
struct AdbcError* error) {
@@ -1399,10 +1467,12 @@ AdbcStatusCode AdbcDatabaseInit(struct AdbcDatabase*
database, struct AdbcError*
} else if (!args->entrypoint.empty()) {
status = AdbcFindLoadDriver(args->driver.c_str(), args->entrypoint.c_str(),
ADBC_VERSION_1_1_0, args->load_flags,
+ args->additional_search_path_list.data(),
database->private_driver, error);
} else {
- status = AdbcFindLoadDriver(args->driver.c_str(), nullptr,
ADBC_VERSION_1_1_0,
- args->load_flags, database->private_driver,
error);
+ status = AdbcFindLoadDriver(
+ args->driver.c_str(), nullptr, ADBC_VERSION_1_1_0, args->load_flags,
+ args->additional_search_path_list.data(), database->private_driver,
error);
}
if (status != ADBC_STATUS_OK) {
@@ -2134,6 +2204,7 @@ const char* AdbcStatusCodeMessage(AdbcStatusCode code) {
AdbcStatusCode AdbcFindLoadDriver(const char* driver_name, const char*
entrypoint,
const int version, const AdbcLoadFlags
load_options,
+ const char* additional_search_path_list,
void* raw_driver, struct AdbcError* error) {
AdbcDriverInitFunc init_func = nullptr;
std::string error_message;
@@ -2163,7 +2234,13 @@ AdbcStatusCode AdbcFindLoadDriver(const char*
driver_name, const char* entrypoin
info.entrypoint = entrypoint;
}
- AdbcStatusCode status = library.GetDriverInfo(driver_name, load_options,
info, error);
+ std::vector<std::filesystem::path> additional_paths;
+ if (additional_search_path_list) {
+ additional_paths = InternalAdbcParsePath(additional_search_path_list);
+ }
+
+ AdbcStatusCode status =
+ library.GetDriverInfo(driver_name, load_options, additional_paths, info,
error);
if (status != ADBC_STATUS_OK) {
driver->release = nullptr;
return status;
@@ -2205,7 +2282,8 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name,
const char* entrypoint,
// but don't enable searching for manifests by default. It will need to be
explicitly
// enabled by calling AdbcFindLoadDriver directly.
return AdbcFindLoadDriver(driver_name, entrypoint, version,
- ADBC_LOAD_FLAG_ALLOW_RELATIVE_PATHS, raw_driver,
error);
+ ADBC_LOAD_FLAG_ALLOW_RELATIVE_PATHS, nullptr,
raw_driver,
+ error);
}
AdbcStatusCode AdbcLoadDriverFromInitFunc(AdbcDriverInitFunc init_func, int
version,
diff --git a/c/driver_manager/adbc_driver_manager_test.cc
b/c/driver_manager/adbc_driver_manager_test.cc
index 4d3ec15a8..57fbfb20d 100644
--- a/c/driver_manager/adbc_driver_manager_test.cc
+++ b/c/driver_manager/adbc_driver_manager_test.cc
@@ -457,7 +457,7 @@ class DriverManifest : public ::testing::Test {
TEST_F(DriverManifest, LoadDriverEnv) {
ASSERT_THAT(AdbcFindLoadDriver("sqlite", nullptr, ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
Not(IsOkStatus(&error)));
std::ofstream test_manifest_file(temp_dir / "sqlite.toml");
@@ -468,7 +468,7 @@ TEST_F(DriverManifest, LoadDriverEnv) {
SetConfigPath(temp_dir.string().c_str());
ASSERT_THAT(AdbcFindLoadDriver("sqlite", nullptr, ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
IsOkStatus(&error));
ASSERT_TRUE(std::filesystem::remove(temp_dir / "sqlite.toml"));
@@ -478,7 +478,7 @@ TEST_F(DriverManifest, LoadDriverEnv) {
TEST_F(DriverManifest, LoadNonAsciiPath) {
ASSERT_THAT(AdbcFindLoadDriver("sqlite", nullptr, ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
Not(IsOkStatus(&error)));
#ifdef _WIN32
@@ -497,7 +497,7 @@ TEST_F(DriverManifest, LoadNonAsciiPath) {
SetConfigPath(non_ascii_dir.string().c_str());
ASSERT_THAT(AdbcFindLoadDriver("sqlite", nullptr, ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
IsOkStatus(&error));
ASSERT_TRUE(std::filesystem::remove(non_ascii_dir / "sqlite.toml"));
@@ -515,7 +515,7 @@ TEST_F(DriverManifest, DisallowEnvConfig) {
auto load_options = ADBC_LOAD_FLAG_DEFAULT & ~ADBC_LOAD_FLAG_SEARCH_ENV;
ASSERT_THAT(AdbcFindLoadDriver("sqlite", nullptr, ADBC_VERSION_1_1_0,
load_options,
- &driver, &error),
+ nullptr, &driver, &error),
Not(IsOkStatus(&error)));
ASSERT_TRUE(std::filesystem::remove(temp_dir / "sqlite.toml"));
@@ -543,7 +543,7 @@ TEST_F(DriverManifest, ConfigEntrypoint) {
test_manifest_file.close();
ASSERT_THAT(AdbcFindLoadDriver(filepath.string().data(), nullptr,
ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
Not(IsOkStatus(&error)));
ASSERT_TRUE(std::filesystem::remove(filepath));
@@ -557,7 +557,7 @@ TEST_F(DriverManifest, LoadAbsolutePath) {
test_manifest_file.close();
ASSERT_THAT(AdbcFindLoadDriver(filepath.string().data(), nullptr,
ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
IsOkStatus(&error));
ASSERT_TRUE(std::filesystem::remove(filepath));
@@ -573,7 +573,7 @@ TEST_F(DriverManifest, LoadAbsolutePathNoExtension) {
auto noext = filepath;
noext.replace_extension(); // Remove the .toml extension
ASSERT_THAT(AdbcFindLoadDriver(noext.string().data(), nullptr,
ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
IsOkStatus(&error));
ASSERT_TRUE(std::filesystem::remove(filepath));
@@ -585,13 +585,14 @@ TEST_F(DriverManifest, LoadRelativePath) {
test_manifest_file << simple_manifest;
test_manifest_file.close();
- ASSERT_THAT(
- AdbcFindLoadDriver("sqlite.toml", nullptr, ADBC_VERSION_1_1_0, 0,
&driver, &error),
- IsStatus(ADBC_STATUS_INVALID_ARGUMENT, &error));
+ ASSERT_THAT(AdbcFindLoadDriver("sqlite.toml", nullptr, ADBC_VERSION_1_1_0,
0, nullptr,
+ &driver, &error),
+ IsStatus(ADBC_STATUS_INVALID_ARGUMENT, &error));
- ASSERT_THAT(AdbcFindLoadDriver("sqlite.toml", nullptr, ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_ALLOW_RELATIVE_PATHS, &driver,
&error),
- IsOkStatus(&error));
+ ASSERT_THAT(
+ AdbcFindLoadDriver("sqlite.toml", nullptr, ADBC_VERSION_1_1_0,
+ ADBC_LOAD_FLAG_ALLOW_RELATIVE_PATHS, nullptr,
&driver, &error),
+ IsOkStatus(&error));
ASSERT_TRUE(std::filesystem::remove("sqlite.toml"));
}
@@ -609,7 +610,7 @@ TEST_F(DriverManifest, ManifestMissingDriver) {
// Attempt to load the driver
ASSERT_THAT(AdbcFindLoadDriver(filepath.string().data(), nullptr,
ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
IsStatus(ADBC_STATUS_NOT_FOUND, &error));
ASSERT_TRUE(std::filesystem::remove(filepath));
@@ -634,7 +635,7 @@ TEST_F(DriverManifest, ManifestWrongArch) {
// Attempt to load the driver
ASSERT_THAT(AdbcFindLoadDriver(filepath.string().data(), nullptr,
ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
IsStatus(ADBC_STATUS_NOT_FOUND, &error));
ASSERT_TRUE(std::filesystem::remove(filepath));
@@ -645,7 +646,7 @@ TEST_F(DriverManifest, ManifestWrongArch) {
#ifdef ADBC_DRIVER_MANAGER_TEST_MANIFEST_USER_LEVEL
TEST_F(DriverManifest, LoadUserLevelManifest) {
ASSERT_THAT(AdbcFindLoadDriver("adbc-test-sqlite", nullptr,
ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
Not(IsOkStatus(&error)));
auto user_config_dir = InternalAdbcUserConfigDir();
@@ -662,12 +663,12 @@ TEST_F(DriverManifest, LoadUserLevelManifest) {
// fail to load if flag doesn't have ADBC_LOAD_FLAG_SEARCH_USER
ASSERT_THAT(AdbcFindLoadDriver("adbc-test-sqlite", nullptr,
ADBC_VERSION_1_1_0, 0,
- &driver, &error),
+ nullptr, &driver, &error),
Not(IsOkStatus(&error)));
// succeed with default load options
ASSERT_THAT(AdbcFindLoadDriver("adbc-test-sqlite", nullptr,
ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
IsOkStatus(&error));
ASSERT_TRUE(std::filesystem::remove(user_config_dir /
"adbc-test-sqlite.toml"));
@@ -682,7 +683,7 @@ TEST_F(DriverManifest, LoadUserLevelManifest) {
#ifdef ADBC_DRIVER_MANAGER_TEST_MANIFEST_SYSTEM_LEVEL
TEST_F(DriverManifest, LoadSystemLevelManifest) {
ASSERT_THAT(AdbcFindLoadDriver("adbc-test-sqlite", nullptr,
ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
Not(IsOkStatus(&error)));
auto system_config_dir = std::filesystem::path("/etc/adbc");
@@ -699,12 +700,12 @@ TEST_F(DriverManifest, LoadSystemLevelManifest) {
// fail to load if flag doesn't have ADBC_LOAD_FLAG_SEARCH_SYSTEM
ASSERT_THAT(AdbcFindLoadDriver("adbc-test-sqlite", nullptr,
ADBC_VERSION_1_1_0, 0,
- &driver, &error),
+ nullptr, &driver, &error),
Not(IsOkStatus(&error)));
// succeed with default load options
ASSERT_THAT(AdbcFindLoadDriver("adbc-test-sqlite", nullptr,
ADBC_VERSION_1_1_0,
- ADBC_LOAD_FLAG_DEFAULT, &driver, &error),
+ ADBC_LOAD_FLAG_DEFAULT, nullptr, &driver,
&error),
IsOkStatus(&error));
ASSERT_TRUE(std::filesystem::remove(system_config_dir /
"adbc-test-sqlite.toml"));
diff --git a/c/include/arrow-adbc/adbc_driver_manager.h
b/c/include/arrow-adbc/adbc_driver_manager.h
index 9cd0fa1d0..62591da4d 100644
--- a/c/include/arrow-adbc/adbc_driver_manager.h
+++ b/c/include/arrow-adbc/adbc_driver_manager.h
@@ -80,10 +80,10 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name,
const char* entrypoint,
/// a shared library. Erroring if this fails.
///
/// If the passed in driver_name does not have an extension and is not an
absolute path:
-/// - The load_options parameter will control whether the driver manager will
search
-/// the ADBC_CONFIG_PATH environment variable, the user configuration
directory, and/or
-/// the system level directory of /etc/adbc for either a manifest file or a
shared
-/// library.
+/// - The load_options parameter will control whether the driver manager will
search the
+/// environment variable ADBC_CONFIG_PATH and (if built or installed with
conda) the
+/// conda environment, the user-level configuration, and/or the system-level
+/// configuration for either a manifest file or a shared library.
/// - For each path to be searched, it will first look for
<path>/<driver_name>.toml. If
/// that file exists, it will attempt to parse the manifest and load the
driver
/// specified within it, erroring if this fails.
@@ -101,12 +101,15 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name,
const char* entrypoint,
/// entrypoint based on the driver name.
/// \param[in] version The ADBC revision to attempt to initialize.
/// \param[in] load_options bit mask of AdbcLoadFlags to control the
directories searched
+/// \param[in] additional_search_path_list A list of additional paths to
search for
+/// delimited by the OS specific path list separator.
/// \param[out] driver The table of function pointers to initialize
/// \param[out] error An optional location to return an error message
ADBC_EXPORT
AdbcStatusCode AdbcFindLoadDriver(const char* driver_name, const char*
entrypoint,
const int version, const AdbcLoadFlags
load_options,
- void* driver, struct AdbcError* error);
+ const char* additional_search_path_list,
void* driver,
+ struct AdbcError* error);
/// \brief Common entry point for drivers via the driver manager.
///
@@ -151,6 +154,23 @@ AdbcStatusCode
AdbcDriverManagerDatabaseSetLoadFlags(struct AdbcDatabase* databa
AdbcLoadFlags flags,
struct AdbcError* error);
+/// \brief Set an additional manifest search path list for the driver manager.
+///
+/// This is an extension to the ADBC API. The driver manager shims
+/// the AdbcDatabase* functions to allow you to specify the
+/// driver/entrypoint dynamically. This function lets you explicitly
+/// set a path list at runtime for additional paths to search when
+/// looking for a driver manifest. While users can add additional
+/// paths via the ADBC_CONFIG_PATH environment variable, this allows
+/// an application to specify search paths at runtime which are not tied
+/// to the load flags.
+///
+/// Calling this function with NULL as the `path_list` will clear any
+/// previously set additional search paths.
+ADBC_EXPORT
+AdbcStatusCode AdbcDriverManagerDatabaseSetAdditionalSearchPathList(
+ struct AdbcDatabase* database, const char* path_list, struct AdbcError*
error);
+
/// \brief Get a human-friendly description of a status code.
ADBC_EXPORT
const char* AdbcStatusCodeMessage(AdbcStatusCode code);
diff --git a/docs/source/format/driver_manifests.rst
b/docs/source/format/driver_manifests.rst
index 9dcdfcbf2..9efd279dd 100644
--- a/docs/source/format/driver_manifests.rst
+++ b/docs/source/format/driver_manifests.rst
@@ -351,7 +351,8 @@ to control which directories will be searched for
manifests, with the behavior b
The type :c:type:`AdbcLoadFlags` is a set of bitflags to control the
directories to be searched. The flags are
- * :c:macro:`ADBC_LOAD_FLAG_SEARCH_ENV` - search the environment
variable ``ADBC_CONFIG_PATH``
+ * :c:macro:`ADBC_LOAD_FLAG_SEARCH_ENV` - search the directory paths in
the environment variable
+ ``ADBC_CONFIG_PATH`` and (when built or installed with conda) search
in the conda environment
* :c:macro:`ADBC_LOAD_FLAG_SEARCH_USER` - search the user configuration
directory
* :c:macro:`ADBC_LOAD_FLAG_SEARCH_SYSTEM` - search the system
configuration directory
* :c:macro:`ADBC_LOAD_FLAG_ALLOW_RELATIVE_PATHS` - allow a relative
path to be provided
@@ -364,7 +365,8 @@ to control which directories will be searched for
manifests, with the behavior b
The type ``GADBCLoadFlags`` is a set of bitflags to control the
directories to be searched. The flags are
- * ``GADBC_LOAD_SEARCH_ENV`` - search the environment variable
``ADBC_CONFIG_PATH``
+ * ``GADBC_LOAD_SEARCH_ENV`` - search the directory paths in the
environment variable
+ ``ADBC_CONFIG_PATH`` and (when built or installed with conda) search
in the conda environment
* ``GADBC_LOAD_FLAG_SEARCH_USER`` - search the user configuration
directory
* ``GADBC_LOAD_FLAG_SEARCH_SYSTEM`` - search the system configuration
directory
* ``GADBC_LOAD_FLAG_ALLOW_RELATIVE_PATHS`` - allow a relative path to
be provided
@@ -380,7 +382,8 @@ to control which directories will be searched for
manifests, with the behavior b
``drivermgr.LoadFlagsOptionKey`` with the value being the
``strconv.Itoa`` of the flags you want to use when you call ``NewDatabase``
or ``NewDatabaseWithContext``. The flags are defined in the
``drivermgr`` package as constants:
- * ``drivermgr.LoadFlagsSearchEnv`` - search the environment variable
``ADBC_CONFIG_PATH``
+ * ``drivermgr.LoadFlagsSearchEnv`` - search the directory paths in the
environment variable
+ ``ADBC_CONFIG_PATH``
* ``drivermgr.LoadFlagsSearchUser`` - search the user configuration
directory
* ``drivermgr.LoadFlagsSearchSystem`` - search the system configuration
directory
* ``drivermgr.LoadFlagsAllowRelativePaths`` - allow a relative path to
be used
@@ -403,7 +406,8 @@ to control which directories will be searched for
manifests, with the behavior b
The class ``ADBC::LoadFlags`` is a set of bitflags to control the
directories to be searched. The flags are
- * ``ADBC::LoadFlags::SEARCH_ENV`` - search the environment variable
``ADBC_CONFIG_PATH``
+ * ``ADBC::LoadFlags::SEARCH_ENV`` - search the directory paths in the
environment variable
+ ``ADBC_CONFIG_PATH`` and (when built or installed with conda) search
in the conda environment
* ``ADBC::LoadFlags::SEARCH_USER`` - search the user configuration
directory
* ``ADBC::LoadFlags::SEARCH_SYSTEM`` - search the system configuration
directory
* ``ADBC::LoadFlags::ALLOW_RELATIVE_PATHS`` - allow a relative path to
be provided
@@ -419,7 +423,8 @@ to control which directories will be searched for
manifests, with the behavior b
The ``ManagedDriver`` type has a method ``load_dynamic_from_name``
which takes an optional ``load_flags`` parameter. The flags as a ``u32`` with
the type ``adbc_core::driver_manager::LoadFlags``, which has the
following constants:
- * ``LOAD_FLAG_SEARCH_ENV`` - search the environment variable
``ADBC_CONFIG_PATH``
+ * ``LOAD_FLAG_SEARCH_ENV`` - search the directory paths in the
environment variable
+ ``ADBC_CONFIG_PATH`` and (when built or installed with conda) search
in the conda environment
* ``LOAD_FLAG_SEARCH_USER`` - search the user configuration directory
* ``LOAD_FLAG_SEARCH_SYSTEM`` - search the system configuration
directory
* ``LOAD_FLAG_ALLOW_RELATIVE_PATHS`` - allow a relative path to be used
@@ -431,9 +436,15 @@ Unix-like Platforms
For Unix-like platforms, (e.g. Linux, macOS), the driver manager will search
the following directories based on the options provided, in
the given order:
-#. If the ``LOAD_FLAG_SEARCH_ENV`` load option is set, then the environment
variable ``ADBC_CONFIG_PATH`` will be searched
+#. If the ``LOAD_FLAG_SEARCH_ENV`` load option is set, then the paths in the
environment variable ``ADBC_CONFIG_PATH`` will be searched
- * ``ADBC_CONFIG_PATH`` is a colon-separated list of directories to search
for ``${name}.toml``
+ * ``ADBC_CONFIG_PATH`` is a colon-separated list of directories
+
+#. If additional search paths have been specified, those will be searched
+
+ * The Python driver manager automatically adds ``$VIRTUAL_ENV/etc/adbc`` to
the search paths when running in a ``venv`` virtual environment
+
+#. If the driver manager was built or installed with conda and the
``LOAD_FLAG_SEARCH_ENV`` load option is set, ``$CONDA_PREFIX/etc/adbc`` will be
searched
#. If the ``LOAD_FLAG_SEARCH_USER`` load option is set, then a user-level
configuration directory will be searched
@@ -452,9 +463,15 @@ Windows
Things are slightly different on Windows, where the driver manager will also
search for driver information in the registry just as
would happen for ODBC drivers. The search for a manifest on Windows would be
the following:
-#. If the ``LOAD_FLAG_SEARCH_ENV`` load option is set, then the environment
variable ``ADBC_CONFIG_PATH`` will be searched
+#. If the ``LOAD_FLAG_SEARCH_ENV`` load option is set, then the paths in the
environment variable ``ADBC_CONFIG_PATH`` will be searched
+
+ * ``ADBC_CONFIG_PATH`` is a semicolon-separated list of directories
+
+#. If additional search paths have been specified, those will be searched
+
+ * The Python driver manager automatically adds ``$VIRTUAL_ENV\etc\adbc`` to
the search paths when running in a ``venv`` virtual environment
- * ``ADBC_CONFIG_PATH`` is a semicolon-separated list of directories to
search for ``${name}.toml``
+#. If the driver manager was built or installed with conda and the
``LOAD_FLAG_SEARCH_ENV`` load option is set, ``$CONDA_PREFIX\etc\adbc`` will be
searched
#. If the ``LOAD_FLAG_SEARCH_USER`` load option is set, then a user-level
configuration is searched for
@@ -467,7 +484,7 @@ would happen for ODBC drivers. The search for a manifest on
Windows would be the
* ``entrypoint`` - the entrypoint to use for the driver if a non-default
entrypoint is needed
* ``driver`` - the path to the driver shared library
- * If no registry key is found, then the directory
``%LOCAL_APPDATA%\ADBC\drivers`` is searched for ``${name}.toml``
+ * If no registry key is found, then the directory
``%LOCAL_APPDATA%\ADBC\drivers`` is searched
#. If the ``LOAD_FLAG_SEARCH_SYSTEM`` load option is set, the driver manager
will search for a system-level configuration
diff --git a/glib/adbc-glib/database.h b/glib/adbc-glib/database.h
index 85ae59e0d..8efe4b6cb 100644
--- a/glib/adbc-glib/database.h
+++ b/glib/adbc-glib/database.h
@@ -27,9 +27,11 @@ G_BEGIN_DECLS
/**
* GADBCLoadFlags:
- * @GADBC_LOAD_SEARCH_ENV: Check the ADBC_CONFIG_PATH environment variable.
- * @GADBC_LOAD_SEARCH_USER: Check the user configuration directory.
- * @GADBC_LOAD_SEARCH_SYSTEM: Check the system configuration directory.
+ * @GADBC_LOAD_SEARCH_ENV: Search the directory paths in the environment
+ * variable ADBC_CONFIG_PATH and (when built or installed with conda)
+ * search in the conda environment
+ * @GADBC_LOAD_SEARCH_USER: Search the user configuration directory.
+ * @GADBC_LOAD_SEARCH_SYSTEM: Search the system configuration directory.
* @GADBC_LOAD_ALLOW_RELATIVE_PATHS: Allow relative driver paths.
*
* The flags are used by gadbc_database_set_load_flags().
diff --git a/go/adbc/drivermgr/adbc_driver_manager.cc
b/go/adbc/drivermgr/adbc_driver_manager.cc
index 3044199f2..9f5cbdbc9 100644
--- a/go/adbc/drivermgr/adbc_driver_manager.cc
+++ b/go/adbc/drivermgr/adbc_driver_manager.cc
@@ -159,7 +159,7 @@ std::wstring Utf8Decode(const std::string& str) {
#else
using char_type = char;
-#endif
+#endif // _WIN32
// Driver state
struct DriverInfo {
@@ -239,7 +239,7 @@ AdbcStatusCode LoadDriverFromRegistry(HKEY root, const
std::wstring& driver_name
}
return ADBC_STATUS_OK;
}
-#endif
+#endif // _WIN32
AdbcStatusCode LoadDriverManifest(const std::filesystem::path& driver_manifest,
DriverInfo& info, struct AdbcError* error) {
@@ -273,14 +273,39 @@ AdbcStatusCode LoadDriverManifest(const
std::filesystem::path& driver_manifest,
return ADBC_STATUS_OK;
}
+std::vector<std::filesystem::path> GetEnvPaths(const char_type* env_var) {
+#ifdef _WIN32
+ size_t required_size;
+
+ _wgetenv_s(&required_size, NULL, 0, env_var);
+ if (required_size == 0) {
+ return {};
+ }
+
+ std::wstring path_var;
+ path_var.resize(required_size);
+ _wgetenv_s(&required_size, path_var.data(), required_size, env_var);
+ auto path = Utf8Encode(path_var);
+#else
+ const char* path_var = std::getenv(env_var);
+ if (!path_var) {
+ return {};
+ }
+ std::string path(path_var);
+#endif
+ return InternalAdbcParsePath(path);
+}
+
std::vector<std::filesystem::path> GetSearchPaths(const AdbcLoadFlags levels) {
std::vector<std::filesystem::path> paths;
if (levels & ADBC_LOAD_FLAG_SEARCH_ENV) {
+#ifdef _WIN32
+ static const wchar_t* env_var = L"ADBC_CONFIG_PATH";
+#else
+ static const char* env_var = "ADBC_CONFIG_PATH";
+#endif
// Check the ADBC_CONFIG_PATH environment variable
- const char* env_path = std::getenv("ADBC_CONFIG_PATH");
- if (env_path) {
- paths = InternalAdbcParsePath(env_path);
- }
+ paths = GetEnvPaths(env_var);
}
if (levels & ADBC_LOAD_FLAG_SEARCH_USER) {
@@ -305,7 +330,7 @@ std::vector<std::filesystem::path> GetSearchPaths(const
AdbcLoadFlags levels) {
if (std::filesystem::exists(system_config_dir)) {
paths.push_back(system_config_dir);
}
-#endif
+#endif // defined(__APPLE__)
}
return paths;
@@ -319,7 +344,7 @@ bool HasExtension(const std::filesystem::path& path, const
std::string& ext) {
_wcsnicmp(path_ext.data(), wext.data(), wext.size()) == 0;
#else
return path.extension() == ext;
-#endif
+#endif // _WIN32
}
/// A driver DLL.
@@ -344,9 +369,10 @@ struct ManagedLibrary {
// release() from the DLL - how to handle this?
}
- AdbcStatusCode GetDriverInfo(const std::string_view driver_name,
- const AdbcLoadFlags load_options, DriverInfo&
info,
- struct AdbcError* error) {
+ AdbcStatusCode GetDriverInfo(
+ const std::string_view driver_name, const AdbcLoadFlags load_options,
+ const std::vector<std::filesystem::path>& additional_search_paths,
DriverInfo& info,
+ struct AdbcError* error) {
if (driver_name.empty()) {
SetError(error, "Driver name is empty");
return ADBC_STATUS_INVALID_ARGUMENT;
@@ -405,7 +431,7 @@ struct ManagedLibrary {
static const std::string kPlatformLibrarySuffix = ".dylib";
#else
static const std::string kPlatformLibrarySuffix = ".so";
-#endif
+#endif // defined(_WIN32)
if (HasExtension(driver_path, kPlatformLibrarySuffix)) {
info.lib_path = driver_path;
return Load(driver_path.c_str(), error);
@@ -418,7 +444,7 @@ struct ManagedLibrary {
// not an absolute path, no extension. Let's search the configured paths
// based on the options
- return FindDriver(driver_path, load_options, info, error);
+ return FindDriver(driver_path, load_options, additional_search_paths,
info, error);
}
AdbcStatusCode SearchPaths(const std::filesystem::path& driver_path,
@@ -446,27 +472,52 @@ struct ManagedLibrary {
return ADBC_STATUS_NOT_FOUND;
}
- AdbcStatusCode FindDriver(const std::filesystem::path& driver_path,
- const AdbcLoadFlags load_options, DriverInfo& info,
- struct AdbcError* error) {
+ AdbcStatusCode FindDriver(
+ const std::filesystem::path& driver_path, const AdbcLoadFlags
load_options,
+ const std::vector<std::filesystem::path>& additional_search_paths,
DriverInfo& info,
+ struct AdbcError* error) {
if (driver_path.empty()) {
SetError(error, "Driver path is empty");
return ADBC_STATUS_INVALID_ARGUMENT;
}
+ {
+ // First search the paths in the env var `ADBC_CONFIG_PATH`.
+ // Then search the runtime application-defined additional search paths.
+ auto search_paths = GetSearchPaths(load_options &
ADBC_LOAD_FLAG_SEARCH_ENV);
+ search_paths.insert(search_paths.end(), additional_search_paths.begin(),
+ additional_search_paths.end());
+
+#if ADBC_CONDA_BUILD
+ // Then, if this is a conda build, search in the conda environment if
+ // it is activated.
+ if (load_options & ADBC_LOAD_FLAG_SEARCH_ENV) {
#ifdef _WIN32
- // windows is slightly more complex since we also need to check registry
keys
- // so we can't just grab the search paths only.
- if (load_options & ADBC_LOAD_FLAG_SEARCH_ENV) {
- auto search_paths = GetSearchPaths(ADBC_LOAD_FLAG_SEARCH_ENV);
+ const wchar_t* conda_name = L"CONDA_PREFIX";
+#else
+ const char* conda_name = "CONDA_PREFIX";
+#endif // _WIN32
+ auto venv = GetEnvPaths(conda_name);
+ if (!venv.empty()) {
+ for (const auto& venv_path : venv) {
+ search_paths.push_back(venv_path / "etc" / "adbc");
+ }
+ }
+ }
+#endif // ADBC_CONDA_BUILD
+
auto status = SearchPaths(driver_path, search_paths, info, error);
if (status == ADBC_STATUS_OK) {
return status;
}
}
+ // We searched environment paths and additional search paths (if they
+ // exist), so now search the rest.
+#ifdef _WIN32
+ // On Windows, check registry keys, not just search paths.
if (load_options & ADBC_LOAD_FLAG_SEARCH_USER) {
- // Check the user registry for the driver
+ // Check the user registry for the driver.
auto status =
LoadDriverFromRegistry(HKEY_CURRENT_USER, driver_path.native(),
info, error);
if (status == ADBC_STATUS_OK) {
@@ -481,7 +532,7 @@ struct ManagedLibrary {
}
if (load_options & ADBC_LOAD_FLAG_SEARCH_SYSTEM) {
- // Check the system registry for the driver
+ // Check the system registry for the driver.
auto status =
LoadDriverFromRegistry(HKEY_LOCAL_MACHINE, driver_path.native(),
info, error);
if (status == ADBC_STATUS_OK) {
@@ -498,17 +549,17 @@ struct ManagedLibrary {
info.lib_path = driver_path;
return Load(driver_path.c_str(), error);
#else
- // Otherwise, search the configured paths
- auto search_paths = GetSearchPaths(load_options);
+ // Otherwise, search the configured paths.
+ auto search_paths = GetSearchPaths(load_options &
~ADBC_LOAD_FLAG_SEARCH_ENV);
auto status = SearchPaths(driver_path, search_paths, info, error);
if (status == ADBC_STATUS_NOT_FOUND) {
// If we reach here, we didn't find the driver in any of the paths
- // so let's just attempt to load it as default behavior
+ // so let's just attempt to load it as default behavior.
info.lib_path = driver_path;
return Load(driver_path.c_str(), error);
}
return status;
-#endif
+#endif // _WIN32
}
AdbcStatusCode Load(const char_type* library, struct AdbcError* error) {
@@ -991,6 +1042,7 @@ struct TempDatabase {
std::string entrypoint;
AdbcDriverInitFunc init_func = nullptr;
AdbcLoadFlags load_flags = ADBC_LOAD_FLAG_ALLOW_RELATIVE_PATHS;
+ std::string additional_search_path_list;
};
/// Temporary state while the database is being configured.
@@ -1043,7 +1095,7 @@ std::filesystem::path InternalAdbcUserConfigDir() {
if (!config_dir.empty()) {
config_dir /= "adbc";
}
-#endif
+#endif // defined(_WIN32)
return config_dir;
}
@@ -1362,6 +1414,22 @@ AdbcStatusCode
AdbcDriverManagerDatabaseSetLoadFlags(struct AdbcDatabase* databa
return ADBC_STATUS_OK;
}
+AdbcStatusCode AdbcDriverManagerDatabaseSetAdditionalSearchPathList(
+ struct AdbcDatabase* database, const char* path_list, struct AdbcError*
error) {
+ if (database->private_driver) {
+ SetError(error, "Cannot SetAdditionalSearchPathList after
AdbcDatabaseInit");
+ return ADBC_STATUS_INVALID_STATE;
+ }
+
+ TempDatabase* args = reinterpret_cast<TempDatabase*>(database->private_data);
+ if (path_list) {
+ args->additional_search_path_list.assign(path_list);
+ } else {
+ args->additional_search_path_list.clear();
+ }
+ return ADBC_STATUS_OK;
+}
+
AdbcStatusCode AdbcDriverManagerDatabaseSetInitFunc(struct AdbcDatabase*
database,
AdbcDriverInitFunc
init_func,
struct AdbcError* error) {
@@ -1399,10 +1467,12 @@ AdbcStatusCode AdbcDatabaseInit(struct AdbcDatabase*
database, struct AdbcError*
} else if (!args->entrypoint.empty()) {
status = AdbcFindLoadDriver(args->driver.c_str(), args->entrypoint.c_str(),
ADBC_VERSION_1_1_0, args->load_flags,
+ args->additional_search_path_list.data(),
database->private_driver, error);
} else {
- status = AdbcFindLoadDriver(args->driver.c_str(), nullptr,
ADBC_VERSION_1_1_0,
- args->load_flags, database->private_driver,
error);
+ status = AdbcFindLoadDriver(
+ args->driver.c_str(), nullptr, ADBC_VERSION_1_1_0, args->load_flags,
+ args->additional_search_path_list.data(), database->private_driver,
error);
}
if (status != ADBC_STATUS_OK) {
@@ -2134,6 +2204,7 @@ const char* AdbcStatusCodeMessage(AdbcStatusCode code) {
AdbcStatusCode AdbcFindLoadDriver(const char* driver_name, const char*
entrypoint,
const int version, const AdbcLoadFlags
load_options,
+ const char* additional_search_path_list,
void* raw_driver, struct AdbcError* error) {
AdbcDriverInitFunc init_func = nullptr;
std::string error_message;
@@ -2163,7 +2234,13 @@ AdbcStatusCode AdbcFindLoadDriver(const char*
driver_name, const char* entrypoin
info.entrypoint = entrypoint;
}
- AdbcStatusCode status = library.GetDriverInfo(driver_name, load_options,
info, error);
+ std::vector<std::filesystem::path> additional_paths;
+ if (additional_search_path_list) {
+ additional_paths = InternalAdbcParsePath(additional_search_path_list);
+ }
+
+ AdbcStatusCode status =
+ library.GetDriverInfo(driver_name, load_options, additional_paths, info,
error);
if (status != ADBC_STATUS_OK) {
driver->release = nullptr;
return status;
@@ -2205,7 +2282,8 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name,
const char* entrypoint,
// but don't enable searching for manifests by default. It will need to be
explicitly
// enabled by calling AdbcFindLoadDriver directly.
return AdbcFindLoadDriver(driver_name, entrypoint, version,
- ADBC_LOAD_FLAG_ALLOW_RELATIVE_PATHS, raw_driver,
error);
+ ADBC_LOAD_FLAG_ALLOW_RELATIVE_PATHS, nullptr,
raw_driver,
+ error);
}
AdbcStatusCode AdbcLoadDriverFromInitFunc(AdbcDriverInitFunc init_func, int
version,
diff --git a/go/adbc/drivermgr/arrow-adbc/adbc_driver_manager.h
b/go/adbc/drivermgr/arrow-adbc/adbc_driver_manager.h
index 9cd0fa1d0..62591da4d 100644
--- a/go/adbc/drivermgr/arrow-adbc/adbc_driver_manager.h
+++ b/go/adbc/drivermgr/arrow-adbc/adbc_driver_manager.h
@@ -80,10 +80,10 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name,
const char* entrypoint,
/// a shared library. Erroring if this fails.
///
/// If the passed in driver_name does not have an extension and is not an
absolute path:
-/// - The load_options parameter will control whether the driver manager will
search
-/// the ADBC_CONFIG_PATH environment variable, the user configuration
directory, and/or
-/// the system level directory of /etc/adbc for either a manifest file or a
shared
-/// library.
+/// - The load_options parameter will control whether the driver manager will
search the
+/// environment variable ADBC_CONFIG_PATH and (if built or installed with
conda) the
+/// conda environment, the user-level configuration, and/or the system-level
+/// configuration for either a manifest file or a shared library.
/// - For each path to be searched, it will first look for
<path>/<driver_name>.toml. If
/// that file exists, it will attempt to parse the manifest and load the
driver
/// specified within it, erroring if this fails.
@@ -101,12 +101,15 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name,
const char* entrypoint,
/// entrypoint based on the driver name.
/// \param[in] version The ADBC revision to attempt to initialize.
/// \param[in] load_options bit mask of AdbcLoadFlags to control the
directories searched
+/// \param[in] additional_search_path_list A list of additional paths to
search for
+/// delimited by the OS specific path list separator.
/// \param[out] driver The table of function pointers to initialize
/// \param[out] error An optional location to return an error message
ADBC_EXPORT
AdbcStatusCode AdbcFindLoadDriver(const char* driver_name, const char*
entrypoint,
const int version, const AdbcLoadFlags
load_options,
- void* driver, struct AdbcError* error);
+ const char* additional_search_path_list,
void* driver,
+ struct AdbcError* error);
/// \brief Common entry point for drivers via the driver manager.
///
@@ -151,6 +154,23 @@ AdbcStatusCode
AdbcDriverManagerDatabaseSetLoadFlags(struct AdbcDatabase* databa
AdbcLoadFlags flags,
struct AdbcError* error);
+/// \brief Set an additional manifest search path list for the driver manager.
+///
+/// This is an extension to the ADBC API. The driver manager shims
+/// the AdbcDatabase* functions to allow you to specify the
+/// driver/entrypoint dynamically. This function lets you explicitly
+/// set a path list at runtime for additional paths to search when
+/// looking for a driver manifest. While users can add additional
+/// paths via the ADBC_CONFIG_PATH environment variable, this allows
+/// an application to specify search paths at runtime which are not tied
+/// to the load flags.
+///
+/// Calling this function with NULL as the `path_list` will clear any
+/// previously set additional search paths.
+ADBC_EXPORT
+AdbcStatusCode AdbcDriverManagerDatabaseSetAdditionalSearchPathList(
+ struct AdbcDatabase* database, const char* path_list, struct AdbcError*
error);
+
/// \brief Get a human-friendly description of a status code.
ADBC_EXPORT
const char* AdbcStatusCodeMessage(AdbcStatusCode code);
diff --git a/python/adbc_driver_manager/adbc_driver_manager/_lib.pxd
b/python/adbc_driver_manager/adbc_driver_manager/_lib.pxd
index 013acf8e0..a7b41e1ea 100644
--- a/python/adbc_driver_manager/adbc_driver_manager/_lib.pxd
+++ b/python/adbc_driver_manager/adbc_driver_manager/_lib.pxd
@@ -298,3 +298,7 @@ cdef extern from "arrow-adbc/adbc_driver_manager.h":
CAdbcDatabase* database,
CAdbcLoadFlags flags,
CAdbcError* error)
+ CAdbcStatusCode AdbcDriverManagerDatabaseSetAdditionalSearchPathList(
+ CAdbcDatabase* database,
+ const char* path_list,
+ CAdbcError* error)
diff --git a/python/adbc_driver_manager/adbc_driver_manager/_lib.pyx
b/python/adbc_driver_manager/adbc_driver_manager/_lib.pyx
index 3da101ab4..c18cd62c1 100644
--- a/python/adbc_driver_manager/adbc_driver_manager/_lib.pyx
+++ b/python/adbc_driver_manager/adbc_driver_manager/_lib.pyx
@@ -564,6 +564,15 @@ cdef class AdbcDatabase(_AdbcHandle):
&self.database, c_key, c_value, &c_error)
check_error(status, &c_error)
+ # check if we're running in a venv
+ if sys.prefix != sys.base_prefix:
+ # if we're in a venv, add the venv prefix to the search path list
+ status = AdbcDriverManagerDatabaseSetAdditionalSearchPathList(
+ &self.database, _to_bytes(os.path.join(sys.prefix, 'etc/adbc'),
+ "sys.prefix"),
+ &c_error)
+ check_error(status, &c_error)
+
with nogil:
status = AdbcDatabaseInit(&self.database, &c_error)
check_error(status, &c_error)
diff --git a/r/adbcdrivermanager/R/driver_void.R
b/r/adbcdrivermanager/R/driver_void.R
index a2510841b..23ea7c865 100644
--- a/r/adbcdrivermanager/R/driver_void.R
+++ b/r/adbcdrivermanager/R/driver_void.R
@@ -96,11 +96,11 @@ adbc_driver <- function(x, entrypoint = NULL, ...,
#' @export
#'
adbc_driver_load <- function(x, entrypoint, version, driver, error,
- load_flags = adbc_load_flags()) {
+ load_flags = adbc_load_flags(),
additional_search_path_list = NULL) {
if (inherits(x, "adbc_driver_init_func")) {
.Call(RAdbcLoadDriverFromInitFunc, x, version, driver, error)
} else {
- .Call(RAdbcLoadDriver, x, entrypoint, version, load_flags, driver, error)
+ .Call(RAdbcLoadDriver, x, entrypoint, version, load_flags,
additional_search_path_list, driver, error)
}
}
@@ -108,12 +108,13 @@ adbc_driver_load <- function(x, entrypoint, version,
driver, error,
#'
#' Options that indicate where to look for driver manifests. Manifests
#' (.toml files) can be installed at the system level, the user level,
-#' and/or location(s) specified by the ADBC_CONFIG_PATH environment variable.
-#' See the ADBC documentation for details regarding the locations of the
-#' user and system paths on various platforms.
+#' in location(s) specified by the ADBC_CONFIG_PATH environment variable,
+#' and/or in a conda environment. See the ADBC documentation for details
+#' regarding the locations of the user and system paths on various platforms.
#'
-#' @param search_env Search for manifest files in the directories specified by
-#' the ADBC_CONFIG_PATH environment variable.
+#' @param search_env Search for manifest files in the directories specified in
+#' the ADBC_CONFIG_PATH environment variable and (when installed with conda)
+#' in the conda environment.
#' @param search_user Search for manifest files in the designated directory
#' for user ADBC driver installs.
#' @param search_system Search for manifest files in the designtaed directory
diff --git a/r/adbcdrivermanager/man/adbc_driver_load.Rd
b/r/adbcdrivermanager/man/adbc_driver_load.Rd
index c721027c7..a154746ff 100644
--- a/r/adbcdrivermanager/man/adbc_driver_load.Rd
+++ b/r/adbcdrivermanager/man/adbc_driver_load.Rd
@@ -10,8 +10,8 @@ adbc_driver_load(
version,
driver,
error,
- load_flags = adbc_load_flags()
-)
+ load_flags = adbc_load_flags(),
+ additional_search_path_list = NULL)
}
\arguments{
\item{x, entrypoint}{An ADBC driver may be defined either as an init function
@@ -26,6 +26,8 @@ must be an external pointer to a DL_FUNC with the type
\item{error}{An external pointer to an \code{AdbcError} or NULL}
\item{load_flags}{Integer flags generated by
\code{\link[=adbc_load_flags]{adbc_load_flags()}}}
+
+\item{additional_search_path_list}{A path list of additional locations to
search for driver manifests}
}
\value{
An integer ADBC status code
diff --git a/r/adbcdrivermanager/man/adbc_load_flags.Rd
b/r/adbcdrivermanager/man/adbc_load_flags.Rd
index 6b49a5af8..4dec948f8 100644
--- a/r/adbcdrivermanager/man/adbc_load_flags.Rd
+++ b/r/adbcdrivermanager/man/adbc_load_flags.Rd
@@ -12,8 +12,9 @@ adbc_load_flags(
)
}
\arguments{
-\item{search_env}{Search for manifest files in the directories specified by
-the ADBC_CONFIG_PATH environment variable.}
+\item{search_env}{Search for manifest files in the directories specified in
+the ADBC_CONFIG_PATH environment variable and (when installed with conda)
+in the conda environment.}
\item{search_user}{Search for manifest files in the designated directory
for user ADBC driver installs.}
@@ -30,7 +31,7 @@ An integer flag value for use in \code{adbc_driver()}
\description{
Options that indicate where to look for driver manifests. Manifests
(.toml files) can be installed at the system level, the user level,
-and/or location(s) specified by the ADBC_CONFIG_PATH environment variable.
-See the ADBC documentation for details regarding the locations of the
-user and system paths on various platforms.
+in location(s) specified by the ADBC_CONFIG_PATH environment variable,
+and/or in a conda environment. See the ADBC documentation for details
+regarding the locations of the user and system paths on various platforms.
}
diff --git a/r/adbcdrivermanager/src/Makevars b/r/adbcdrivermanager/src/Makevars
index 6011ee79e..c04d29064 100644
--- a/r/adbcdrivermanager/src/Makevars
+++ b/r/adbcdrivermanager/src/Makevars
@@ -16,7 +16,8 @@
# under the License.
CXX_STD = CXX17
-PKG_CPPFLAGS=-I../src/c/include -I../src/c -I../src/c/vendor -DADBC_EXPORT=""
-D_LIBCPP_DISABLE_AVAILABILITY
+CONDA_BUILD ?= "0"
+PKG_CPPFLAGS=-I../src/c/include -I../src/c -I../src/c/vendor -DADBC_EXPORT=""
-D_LIBCPP_DISABLE_AVAILABILITY -DADBC_CONDA_BUILD=$(CONDA_BUILD)
OBJECTS = driver_test.o \
error.o \
diff --git a/r/adbcdrivermanager/src/Makevars.win
b/r/adbcdrivermanager/src/Makevars.win
index fe0f01afb..688de0c2c 100644
--- a/r/adbcdrivermanager/src/Makevars.win
+++ b/r/adbcdrivermanager/src/Makevars.win
@@ -16,7 +16,8 @@
# under the License.
CXX_STD = CXX17
-PKG_CPPFLAGS=-I../src/c/include -I../src/c -I../src/c/vendor -DADBC_EXPORT=""
+CONDA_BUILD ?= "0"
+PKG_CPPFLAGS=-I../src/c/include -I../src/c -I../src/c/vendor -DADBC_EXPORT=""
-DADBC_CONDA_BUILD=$(CONDA_BUILD)
PKG_LIBS=-lshell32 -ladvapi32 -luuid
OBJECTS = driver_test.o \
diff --git a/r/adbcdrivermanager/src/init.c b/r/adbcdrivermanager/src/init.c
index fb2d1a6ae..a062d7150 100644
--- a/r/adbcdrivermanager/src/init.c
+++ b/r/adbcdrivermanager/src/init.c
@@ -48,7 +48,8 @@ SEXP RAdbcStatementGetOptionDouble(SEXP statement_xptr, SEXP
key_sexp, SEXP erro
SEXP RAdbcCurrentArch(void);
SEXP RAdbcAllocateDriver(void);
SEXP RAdbcLoadDriver(SEXP driver_name_sexp, SEXP entrypoint_sexp, SEXP
version_sexp,
- SEXP load_flags_sexp, SEXP driver_sexp, SEXP error_sexp);
+ SEXP load_flags_sexp, SEXP
additional_search_path_list_sexp,
+ SEXP driver_sexp, SEXP error_sexp);
SEXP RAdbcLoadDriverFromInitFunc(SEXP driver_init_func_xptr, SEXP version_sexp,
SEXP driver_sexp, SEXP error_sexp);
SEXP RAdbcDatabaseNew(SEXP driver_init_func_xptr, SEXP load_flags_sexp);
@@ -130,7 +131,7 @@ static const R_CallMethodDef CallEntries[] = {
{"RAdbcStatementGetOptionDouble", (DL_FUNC)&RAdbcStatementGetOptionDouble,
3},
{"RAdbcCurrentArch", (DL_FUNC)&RAdbcCurrentArch, 0},
{"RAdbcAllocateDriver", (DL_FUNC)&RAdbcAllocateDriver, 0},
- {"RAdbcLoadDriver", (DL_FUNC)&RAdbcLoadDriver, 6},
+ {"RAdbcLoadDriver", (DL_FUNC)&RAdbcLoadDriver, 7},
{"RAdbcLoadDriverFromInitFunc", (DL_FUNC)&RAdbcLoadDriverFromInitFunc, 4},
{"RAdbcDatabaseNew", (DL_FUNC)&RAdbcDatabaseNew, 2},
{"RAdbcMoveDatabase", (DL_FUNC)&RAdbcMoveDatabase, 1},
diff --git a/r/adbcdrivermanager/src/radbc.cc b/r/adbcdrivermanager/src/radbc.cc
index c07ab1d07..3010c5964 100644
--- a/r/adbcdrivermanager/src/radbc.cc
+++ b/r/adbcdrivermanager/src/radbc.cc
@@ -117,12 +117,15 @@ extern "C" SEXP RAdbcAllocateDriver(void) {
}
extern "C" SEXP RAdbcLoadDriver(SEXP driver_name_sexp, SEXP entrypoint_sexp,
- SEXP version_sexp, SEXP load_flags_sexp, SEXP
driver_sexp,
+ SEXP version_sexp, SEXP load_flags_sexp,
+ SEXP additional_search_path_list_sexp, SEXP
driver_sexp,
SEXP error_sexp) {
const char* driver_name = adbc_as_const_char(driver_name_sexp);
const char* entrypoint = adbc_as_const_char(entrypoint_sexp, /*nullable*/
true);
int version = adbc_as_int(version_sexp);
int load_flags = adbc_as_int(load_flags_sexp);
+ const char* additional_search_path_list =
+ adbc_as_const_char(additional_search_path_list_sexp, /*nullable*/ true);
if (TYPEOF(driver_sexp) != EXTPTRSXP) {
Rf_error("driver must be an externalptr");
@@ -138,8 +141,8 @@ extern "C" SEXP RAdbcLoadDriver(SEXP driver_name_sexp, SEXP
entrypoint_sexp,
Rf_error("error must be an externalptr");
}
- int status =
- AdbcFindLoadDriver(driver_name, entrypoint, version, load_flags, driver,
error);
+ int status = AdbcFindLoadDriver(driver_name, entrypoint, version, load_flags,
+ additional_search_path_list, driver, error);
return Rf_ScalarInteger(status);
}
diff --git a/rust/driver_manager/build.rs b/rust/driver_manager/build.rs
new file mode 100644
index 000000000..ba20b6103
--- /dev/null
+++ b/rust/driver_manager/build.rs
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::env;
+
+fn main() {
+ println!("cargo::rustc-check-cfg=cfg(conda_build)");
+ let is_conda_build = env::var("CONDA_BUILD").unwrap_or_default() == "1";
+ if is_conda_build {
+ println!("cargo::rustc-cfg=conda_build");
+ }
+}
diff --git a/rust/driver_manager/src/lib.rs b/rust/driver_manager/src/lib.rs
index 21f08251a..834aaf2ae 100644
--- a/rust/driver_manager/src/lib.rs
+++ b/rust/driver_manager/src/lib.rs
@@ -310,6 +310,7 @@ impl ManagedDriver {
entrypoint: Option<&[u8]>,
version: AdbcVersion,
load_flags: LoadFlags,
+ additional_search_paths: Option<Vec<PathBuf>>,
) -> Result<Self> {
let driver_path = Path::new(name.as_ref());
let allow_relative = load_flags & LOAD_FLAG_ALLOW_RELATIVE_PATHS != 0;
@@ -334,7 +335,13 @@ impl ManagedDriver {
Self::load_dynamic_from_filename(driver_path, entrypoint, version)
} else {
- Self::find_driver(driver_path, entrypoint, version, load_flags)
+ Self::find_driver(
+ driver_path,
+ entrypoint,
+ version,
+ load_flags,
+ additional_search_paths,
+ )
}
}
@@ -481,6 +488,7 @@ impl ManagedDriver {
entrypoint: Option<&[u8]>,
version: AdbcVersion,
load_flags: LoadFlags,
+ additional_search_paths: Option<Vec<PathBuf>>,
) -> Result<Self> {
if load_flags & LOAD_FLAG_SEARCH_ENV != 0 {
if let Ok(result) = Self::search_path_list(
@@ -493,6 +501,29 @@ impl ManagedDriver {
}
}
+ // the logic we want is that we first search ADBC_CONFIG_PATH if set,
+ // then we search the additional search paths if they exist. Finally,
+ // we will search CONDA_PREFIX if built with conda_build before moving
on.
+ if let Some(additional_search_paths) = additional_search_paths {
+ if let Ok(result) =
+ Self::search_path_list(driver_path, additional_search_paths,
entrypoint, version)
+ {
+ return Ok(result);
+ }
+ }
+
+ #[cfg(conda_build)]
+ if load_flags & LOAD_FLAG_SEARCH_ENV != 0 {
+ if let Some(conda_prefix) = env::var_os("CONDA_PREFIX") {
+ let conda_path =
PathBuf::from(conda_prefix).join("etc").join("adbc");
+ if let Ok(result) =
+ Self::search_path_list(driver_path, vec![conda_path],
entrypoint, version)
+ {
+ return Ok(result);
+ }
+ }
+ }
+
if load_flags & LOAD_FLAG_SEARCH_USER != 0 {
// first check registry for the driver, then check the user config
path
if let Ok(result) = load_driver_from_registry(
@@ -542,13 +573,24 @@ impl ManagedDriver {
entrypoint: Option<&[u8]>,
version: AdbcVersion,
load_flags: LoadFlags,
+ additional_search_paths: Option<Vec<PathBuf>>,
) -> Result<Self> {
- if let Ok(result) = Self::search_path_list(
- driver_path,
- get_search_paths(load_flags),
- entrypoint,
- version,
- ) {
+ let mut path_list = get_search_paths(load_flags &
LOAD_FLAG_SEARCH_ENV);
+
+ if let Some(additional_search_paths) = additional_search_paths {
+ path_list.extend(additional_search_paths);
+ }
+
+ #[cfg(conda_build)]
+ if load_flags & LOAD_FLAG_SEARCH_ENV != 0 {
+ if let Some(conda_prefix) = env::var_os("CONDA_PREFIX") {
+ let conda_path =
PathBuf::from(conda_prefix).join("etc").join("adbc");
+ path_list.push(conda_path);
+ }
+ }
+
+ path_list.extend(get_search_paths(load_flags & !LOAD_FLAG_SEARCH_ENV));
+ if let Ok(result) = Self::search_path_list(driver_path, path_list,
entrypoint, version) {
return Ok(result);
}
@@ -1949,6 +1991,7 @@ mod tests {
None,
AdbcVersion::V100,
LOAD_FLAG_SEARCH_ENV,
+ None,
)
.unwrap_err();
assert_eq!(err.status, Status::NotFound);
@@ -1966,6 +2009,7 @@ mod tests {
None,
AdbcVersion::V100,
LOAD_FLAG_SEARCH_ENV,
+ None,
)
.unwrap();
},
@@ -1990,8 +2034,14 @@ mod tests {
.unwrap();
with_var("ADBC_CONFIG_PATH", Some(&path_os_string), || {
- ManagedDriver::load_from_name("sqlite", None, AdbcVersion::V100,
LOAD_FLAG_SEARCH_ENV)
- .unwrap();
+ ManagedDriver::load_from_name(
+ "sqlite",
+ None,
+ AdbcVersion::V100,
+ LOAD_FLAG_SEARCH_ENV,
+ None,
+ )
+ .unwrap();
});
tmp_dir
@@ -2014,6 +2064,7 @@ mod tests {
None,
AdbcVersion::V100,
LOAD_FLAG_SEARCH_ENV,
+ None,
)
.unwrap();
},
@@ -2036,9 +2087,14 @@ mod tests {
Some(manifest_path.parent().unwrap().as_os_str()),
|| {
let load_flags = LOAD_FLAG_DEFAULT & !LOAD_FLAG_SEARCH_ENV;
- let err =
- ManagedDriver::load_from_name("sqlite", None,
AdbcVersion::V100, load_flags)
- .unwrap_err();
+ let err = ManagedDriver::load_from_name(
+ "sqlite",
+ None,
+ AdbcVersion::V100,
+ load_flags,
+ None,
+ )
+ .unwrap_err();
assert_eq!(err.status, Status::NotFound);
},
);
@@ -2048,14 +2104,40 @@ mod tests {
.expect("Failed to close/remove temporary directory");
}
+ #[test]
+ #[cfg_attr(not(feature = "driver_manager_test_lib"), ignore)]
+ fn test_load_additional_path() {
+ let p = PathBuf::from("majestik møøse/sqlite.toml");
+ let (tmp_dir, manifest_path) = write_manifest_to_tempfile(p,
simple_manifest());
+
+ ManagedDriver::load_from_name(
+ "sqlite",
+ None,
+ AdbcVersion::V100,
+ LOAD_FLAG_SEARCH_ENV,
+ Some(vec![manifest_path.parent().unwrap().to_path_buf()]),
+ )
+ .unwrap();
+
+ tmp_dir
+ .close()
+ .expect("Failed to close/remove temporary directory");
+ }
+
#[test]
#[cfg_attr(not(feature = "driver_manager_test_lib"), ignore)]
fn test_load_absolute_path() {
let (tmp_dir, manifest_path) =
write_manifest_to_tempfile(PathBuf::from("sqlite.toml"),
simple_manifest());
- ManagedDriver::load_from_name(manifest_path, None, AdbcVersion::V100,
LOAD_FLAG_DEFAULT)
- .unwrap();
+ ManagedDriver::load_from_name(
+ manifest_path,
+ None,
+ AdbcVersion::V100,
+ LOAD_FLAG_DEFAULT,
+ None,
+ )
+ .unwrap();
tmp_dir
.close()
@@ -2069,8 +2151,14 @@ mod tests {
write_manifest_to_tempfile(PathBuf::from("sqlite.toml"),
simple_manifest());
manifest_path.set_extension("");
- ManagedDriver::load_from_name(manifest_path, None, AdbcVersion::V100,
LOAD_FLAG_DEFAULT)
- .unwrap();
+ ManagedDriver::load_from_name(
+ manifest_path,
+ None,
+ AdbcVersion::V100,
+ LOAD_FLAG_DEFAULT,
+ None,
+ )
+ .unwrap();
tmp_dir
.close()
@@ -2083,8 +2171,8 @@ mod tests {
std::fs::write(PathBuf::from("sqlite.toml"), simple_manifest())
.expect("Failed to write driver manager manifest to file");
- let err =
- ManagedDriver::load_from_name("sqlite.toml", None,
AdbcVersion::V100, 0).unwrap_err();
+ let err = ManagedDriver::load_from_name("sqlite.toml", None,
AdbcVersion::V100, 0, None)
+ .unwrap_err();
assert_eq!(err.status, Status::InvalidArguments);
ManagedDriver::load_from_name(
@@ -2092,6 +2180,7 @@ mod tests {
None,
AdbcVersion::V100,
LOAD_FLAG_ALLOW_RELATIVE_PATHS,
+ None,
)
.unwrap();
@@ -2112,6 +2201,7 @@ mod tests {
None,
AdbcVersion::V100,
LOAD_FLAG_DEFAULT,
+ None,
)
.unwrap_err();
assert_eq!(err.status, Status::InvalidArguments);
@@ -2143,6 +2233,7 @@ mod tests {
None,
AdbcVersion::V100,
LOAD_FLAG_DEFAULT,
+ None,
)
.unwrap_err();
assert_eq!(err.status, Status::InvalidArguments);
@@ -2167,6 +2258,7 @@ mod tests {
None,
AdbcVersion::V110,
LOAD_FLAG_DEFAULT,
+ None,
)
.unwrap_err();
assert_eq!(err.status, Status::NotFound);
@@ -2189,6 +2281,7 @@ mod tests {
None,
AdbcVersion::V110,
LOAD_FLAG_DEFAULT & !LOAD_FLAG_SEARCH_USER,
+ None,
)
.unwrap_err();
assert_eq!(err.status, Status::NotFound);
@@ -2199,6 +2292,7 @@ mod tests {
None,
AdbcVersion::V110,
LOAD_FLAG_SEARCH_USER,
+ None,
)
.unwrap();