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 6d458a2fd feat(c/driver_manager): improve error messages further 
(#3646)
6d458a2fd is described below

commit 6d458a2fd26c49d74c74576c7816d96faf9ddcf9
Author: David Li <[email protected]>
AuthorDate: Wed Oct 29 13:54:27 2025 +0900

    feat(c/driver_manager): improve error messages further (#3646)
    
    Now if you don't enable load flags, that is explicitly reported instead
    of sliently failing.
---
 c/driver_manager/CMakeLists.txt              |  2 +-
 c/driver_manager/adbc_driver_manager.cc      | 77 ++++++++++++++++++++++------
 c/driver_manager/adbc_driver_manager_test.cc | 18 +++++++
 go/adbc/drivermgr/adbc_driver_manager.cc     | 77 ++++++++++++++++++++++------
 4 files changed, 141 insertions(+), 33 deletions(-)

diff --git a/c/driver_manager/CMakeLists.txt b/c/driver_manager/CMakeLists.txt
index 7057cc78e..198c3f979 100644
--- a/c/driver_manager/CMakeLists.txt
+++ b/c/driver_manager/CMakeLists.txt
@@ -99,7 +99,7 @@ if(ADBC_BUILD_TESTS)
 
   if(ADBC_DRIVER_SQLITE)
     target_compile_definitions(adbc-driver-manager-test
-                               PRIVATE 
ADBC_DRIVER_MANAGER_TEST_LIB="${CMAKE_BINARY_DIR}/driver/sqlite/libadbc_driver_sqlite${CMAKE_SHARED_LIBRARY_SUFFIX}"
+                               PRIVATE 
ADBC_DRIVER_MANAGER_TEST_LIB="${CMAKE_BINARY_DIR}/driver/sqlite/${CMAKE_SHARED_LIBRARY_PREFIX}adbc_driver_sqlite${CMAKE_SHARED_LIBRARY_SUFFIX}"
     )
   endif()
   if(ADBC_DRIVER_MANAGER_TEST_MANIFEST_USER_LEVEL)
diff --git a/c/driver_manager/adbc_driver_manager.cc 
b/c/driver_manager/adbc_driver_manager.cc
index a8bac46b5..3beec2f0b 100644
--- a/c/driver_manager/adbc_driver_manager.cc
+++ b/c/driver_manager/adbc_driver_manager.cc
@@ -55,6 +55,10 @@ ADBC_EXPORT
 std::vector<std::filesystem::path> InternalAdbcParsePath(const 
std::string_view path);
 ADBC_EXPORT
 std::filesystem::path InternalAdbcUserConfigDir();
+#if !defined(_WIN32)
+ADBC_EXPORT
+std::filesystem::path InternalAdbcSystemConfigDir();
+#endif  // !defined(_WIN32)
 
 namespace {
 
@@ -68,7 +72,8 @@ enum class SearchPathSource {
   kConda,
   kUnset,
   kDoesNotExist,
-  kDisabled,
+  kDisabledAtCompileTime,
+  kDisabledAtRunTime,
   kOtherError,
 };
 
@@ -104,9 +109,12 @@ void AddSearchPathsToError(const SearchPaths& 
search_paths, std::string& error_m
         case SearchPathSource::kDoesNotExist:
           error_message += "does not exist: ";
           break;
-        case SearchPathSource::kDisabled:
+        case SearchPathSource::kDisabledAtCompileTime:
           error_message += "not enabled at build time: ";
           break;
+        case SearchPathSource::kDisabledAtRunTime:
+          error_message += "not enabled at run time: ";
+          break;
         case SearchPathSource::kOtherError:
           // Don't add any prefix
           break;
@@ -482,22 +490,14 @@ SearchPaths GetSearchPaths(const AdbcLoadFlags levels) {
     // System level behavior for Windows is to search the registry keys so we
     // only need to check for macOS and fall back to Unix-like behavior as long
     // as we're not on Windows
-#if defined(__APPLE__)
-    const std::filesystem::path system_config_dir(
-        "/Library/Application Support/ADBC/Drivers");
-    if (std::filesystem::exists(system_config_dir)) {
-      paths.emplace_back(SearchPathSource::kSystem, 
std::move(system_config_dir));
-    } else {
-      paths.emplace_back(SearchPathSource::kDoesNotExist, 
std::move(system_config_dir));
-    }
-#elif !defined(_WIN32)
-    const std::filesystem::path system_config_dir("/etc/adbc/drivers");
+#if !defined(_WIN32)
+    const std::filesystem::path system_config_dir = 
InternalAdbcSystemConfigDir();
     if (std::filesystem::exists(system_config_dir)) {
       paths.emplace_back(SearchPathSource::kSystem, 
std::move(system_config_dir));
     } else {
       paths.emplace_back(SearchPathSource::kDoesNotExist, 
std::move(system_config_dir));
     }
-#endif  // defined(__APPLE__)
+#endif  // !defined(_WIN32)
   }
 
   return paths;
@@ -630,7 +630,8 @@ struct ManagedLibrary {
     for (const auto& [source, search_path] : search_paths) {
       if (source == SearchPathSource::kRegistry || source == 
SearchPathSource::kUnset ||
           source == SearchPathSource::kDoesNotExist ||
-          source == SearchPathSource::kDisabled ||
+          source == SearchPathSource::kDisabledAtCompileTime ||
+          source == SearchPathSource::kDisabledAtRunTime ||
           source == SearchPathSource::kOtherError) {
         continue;
       }
@@ -713,7 +714,10 @@ struct ManagedLibrary {
       // First search the paths in the env var `ADBC_DRIVER_PATH`.
       // Then search the runtime application-defined additional search paths.
       search_paths = GetSearchPaths(load_options & ADBC_LOAD_FLAG_SEARCH_ENV);
-      if (search_paths.empty()) {
+      if (!(load_options & ADBC_LOAD_FLAG_SEARCH_ENV)) {
+        search_paths.emplace_back(SearchPathSource::kDisabledAtRunTime,
+                                  "ADBC_DRIVER_PATH (enable 
ADBC_LOAD_FLAG_SEARCH_ENV)");
+      } else if (search_paths.empty()) {
         search_paths.emplace_back(SearchPathSource::kUnset, 
"ADBC_DRIVER_PATH");
       }
       for (const auto& path : additional_search_paths) {
@@ -736,10 +740,14 @@ struct ManagedLibrary {
                                       venv_path / "etc" / "adbc" / "drivers");
           }
         }
+      } else {
+        search_paths.emplace_back(SearchPathSource::kDisabledAtRunTime,
+                                  "Conda prefix (enable 
ADBC_LOAD_FLAG_SEARCH_ENV)");
       }
 #else
       if (load_options & ADBC_LOAD_FLAG_SEARCH_ENV) {
-        search_paths.emplace_back(SearchPathSource::kDisabled, "Conda prefix");
+        search_paths.emplace_back(SearchPathSource::kDisabledAtCompileTime,
+                                  "Conda prefix");
       }
 #endif  // ADBC_CONDA_BUILD
 
@@ -776,6 +784,9 @@ struct ManagedLibrary {
         return status;
       }
       search_paths.insert(search_paths.end(), user_paths.begin(), 
user_paths.end());
+    } else {
+      search_paths.emplace_back(SearchPathSource::kDisabledAtRunTime,
+                                "HKEY_CURRENT_USER (enable 
ADBC_LOAD_FLAG_SEARCH_USER)");
     }
 
     if (load_options & ADBC_LOAD_FLAG_SEARCH_SYSTEM) {
@@ -800,6 +811,10 @@ struct ManagedLibrary {
         return status;
       }
       search_paths.insert(search_paths.end(), system_paths.begin(), 
system_paths.end());
+    } else {
+      search_paths.emplace_back(
+          SearchPathSource::kDisabledAtRunTime,
+          "HKEY_LOCAL_MACHINE (enable ADBC_LOAD_FLAG_SEARCH_SYSTEM)");
     }
 
     info.lib_path = driver_path;
@@ -810,6 +825,26 @@ struct ManagedLibrary {
         GetSearchPaths(load_options & ~ADBC_LOAD_FLAG_SEARCH_ENV);
     auto status = SearchPathsForDriver(driver_path, more_search_paths, info, 
error);
     if (status == ADBC_STATUS_NOT_FOUND) {
+      if (!(load_options & ADBC_LOAD_FLAG_SEARCH_USER)) {
+        std::filesystem::path user_config_dir = InternalAdbcUserConfigDir();
+        std::string message = "user config dir ";
+        message += user_config_dir.string();
+        message += " (enable ADBC_LOAD_FLAG_SEARCH_USER)";
+        more_search_paths.emplace_back(SearchPathSource::kDisabledAtRunTime,
+                                       std::move(message));
+      }
+      // Windows searches registry keys, so this only applies to other OSes
+#if !defined(_WIN32)
+      if (!(load_options & ADBC_LOAD_FLAG_SEARCH_SYSTEM)) {
+        std::filesystem::path system_config_dir = 
InternalAdbcSystemConfigDir();
+        std::string message = "system config dir ";
+        message += system_config_dir.string();
+        message += " (enable ADBC_LOAD_FLAG_SEARCH_SYSTEM)";
+        more_search_paths.emplace_back(SearchPathSource::kDisabledAtRunTime,
+                                       std::move(message));
+      }
+#endif  // !defined(_WIN32)
+
       // 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.
       search_paths.insert(search_paths.end(), more_search_paths.begin(),
@@ -1364,6 +1399,16 @@ std::filesystem::path InternalAdbcUserConfigDir() {
   return config_dir;
 }
 
+#if !defined(_WIN32)
+std::filesystem::path InternalAdbcSystemConfigDir() {
+#if defined(__APPLE__)
+  return std::filesystem::path("/Library/Application Support/ADBC/Drivers");
+#else
+  return std::filesystem::path("/etc/adbc/drivers");
+#endif  // defined(__APPLE__)
+}
+#endif  // !defined(_WIN32)
+
 std::vector<std::filesystem::path> InternalAdbcParsePath(const 
std::string_view path) {
   std::vector<std::filesystem::path> result;
   if (path.empty()) {
diff --git a/c/driver_manager/adbc_driver_manager_test.cc 
b/c/driver_manager/adbc_driver_manager_test.cc
index 18f5f7489..e0a904d09 100644
--- a/c/driver_manager/adbc_driver_manager_test.cc
+++ b/c/driver_manager/adbc_driver_manager_test.cc
@@ -1000,6 +1000,24 @@ TEST_F(DriverManifest, LoadSystemLevelManifest) {
 }
 #endif
 
+TEST_F(DriverManifest, AllDisabled) {
+  // Test that if the user doesn't set load flags, we properly flag this
+  ASSERT_THAT(AdbcFindLoadDriver("adbc-test-sqlite", nullptr, 
ADBC_VERSION_1_1_0, 0,
+                                 nullptr, &driver, &error),
+              IsStatus(ADBC_STATUS_NOT_FOUND, &error));
+  ASSERT_THAT(error.message,
+              ::testing::HasSubstr("not enabled at run time: ADBC_DRIVER_PATH 
(enable "
+                                   "ADBC_LOAD_FLAG_SEARCH_ENV)"));
+  ASSERT_THAT(error.message,
+              ::testing::HasSubstr("not enabled at run time: user config dir 
/home"));
+  ASSERT_THAT(error.message,
+              ::testing::HasSubstr(" (enable ADBC_LOAD_FLAG_SEARCH_USER)"));
+  ASSERT_THAT(error.message,
+              ::testing::HasSubstr("not enabled at run time: system config dir 
/"));
+  ASSERT_THAT(error.message,
+              ::testing::HasSubstr(" (enable ADBC_LOAD_FLAG_SEARCH_SYSTEM)"));
+}
+
 TEST_F(DriverManifest, CondaPrefix) {
 #if ADBC_CONDA_BUILD
   constexpr bool is_conda_build = true;
diff --git a/go/adbc/drivermgr/adbc_driver_manager.cc 
b/go/adbc/drivermgr/adbc_driver_manager.cc
index a8bac46b5..3beec2f0b 100644
--- a/go/adbc/drivermgr/adbc_driver_manager.cc
+++ b/go/adbc/drivermgr/adbc_driver_manager.cc
@@ -55,6 +55,10 @@ ADBC_EXPORT
 std::vector<std::filesystem::path> InternalAdbcParsePath(const 
std::string_view path);
 ADBC_EXPORT
 std::filesystem::path InternalAdbcUserConfigDir();
+#if !defined(_WIN32)
+ADBC_EXPORT
+std::filesystem::path InternalAdbcSystemConfigDir();
+#endif  // !defined(_WIN32)
 
 namespace {
 
@@ -68,7 +72,8 @@ enum class SearchPathSource {
   kConda,
   kUnset,
   kDoesNotExist,
-  kDisabled,
+  kDisabledAtCompileTime,
+  kDisabledAtRunTime,
   kOtherError,
 };
 
@@ -104,9 +109,12 @@ void AddSearchPathsToError(const SearchPaths& 
search_paths, std::string& error_m
         case SearchPathSource::kDoesNotExist:
           error_message += "does not exist: ";
           break;
-        case SearchPathSource::kDisabled:
+        case SearchPathSource::kDisabledAtCompileTime:
           error_message += "not enabled at build time: ";
           break;
+        case SearchPathSource::kDisabledAtRunTime:
+          error_message += "not enabled at run time: ";
+          break;
         case SearchPathSource::kOtherError:
           // Don't add any prefix
           break;
@@ -482,22 +490,14 @@ SearchPaths GetSearchPaths(const AdbcLoadFlags levels) {
     // System level behavior for Windows is to search the registry keys so we
     // only need to check for macOS and fall back to Unix-like behavior as long
     // as we're not on Windows
-#if defined(__APPLE__)
-    const std::filesystem::path system_config_dir(
-        "/Library/Application Support/ADBC/Drivers");
-    if (std::filesystem::exists(system_config_dir)) {
-      paths.emplace_back(SearchPathSource::kSystem, 
std::move(system_config_dir));
-    } else {
-      paths.emplace_back(SearchPathSource::kDoesNotExist, 
std::move(system_config_dir));
-    }
-#elif !defined(_WIN32)
-    const std::filesystem::path system_config_dir("/etc/adbc/drivers");
+#if !defined(_WIN32)
+    const std::filesystem::path system_config_dir = 
InternalAdbcSystemConfigDir();
     if (std::filesystem::exists(system_config_dir)) {
       paths.emplace_back(SearchPathSource::kSystem, 
std::move(system_config_dir));
     } else {
       paths.emplace_back(SearchPathSource::kDoesNotExist, 
std::move(system_config_dir));
     }
-#endif  // defined(__APPLE__)
+#endif  // !defined(_WIN32)
   }
 
   return paths;
@@ -630,7 +630,8 @@ struct ManagedLibrary {
     for (const auto& [source, search_path] : search_paths) {
       if (source == SearchPathSource::kRegistry || source == 
SearchPathSource::kUnset ||
           source == SearchPathSource::kDoesNotExist ||
-          source == SearchPathSource::kDisabled ||
+          source == SearchPathSource::kDisabledAtCompileTime ||
+          source == SearchPathSource::kDisabledAtRunTime ||
           source == SearchPathSource::kOtherError) {
         continue;
       }
@@ -713,7 +714,10 @@ struct ManagedLibrary {
       // First search the paths in the env var `ADBC_DRIVER_PATH`.
       // Then search the runtime application-defined additional search paths.
       search_paths = GetSearchPaths(load_options & ADBC_LOAD_FLAG_SEARCH_ENV);
-      if (search_paths.empty()) {
+      if (!(load_options & ADBC_LOAD_FLAG_SEARCH_ENV)) {
+        search_paths.emplace_back(SearchPathSource::kDisabledAtRunTime,
+                                  "ADBC_DRIVER_PATH (enable 
ADBC_LOAD_FLAG_SEARCH_ENV)");
+      } else if (search_paths.empty()) {
         search_paths.emplace_back(SearchPathSource::kUnset, 
"ADBC_DRIVER_PATH");
       }
       for (const auto& path : additional_search_paths) {
@@ -736,10 +740,14 @@ struct ManagedLibrary {
                                       venv_path / "etc" / "adbc" / "drivers");
           }
         }
+      } else {
+        search_paths.emplace_back(SearchPathSource::kDisabledAtRunTime,
+                                  "Conda prefix (enable 
ADBC_LOAD_FLAG_SEARCH_ENV)");
       }
 #else
       if (load_options & ADBC_LOAD_FLAG_SEARCH_ENV) {
-        search_paths.emplace_back(SearchPathSource::kDisabled, "Conda prefix");
+        search_paths.emplace_back(SearchPathSource::kDisabledAtCompileTime,
+                                  "Conda prefix");
       }
 #endif  // ADBC_CONDA_BUILD
 
@@ -776,6 +784,9 @@ struct ManagedLibrary {
         return status;
       }
       search_paths.insert(search_paths.end(), user_paths.begin(), 
user_paths.end());
+    } else {
+      search_paths.emplace_back(SearchPathSource::kDisabledAtRunTime,
+                                "HKEY_CURRENT_USER (enable 
ADBC_LOAD_FLAG_SEARCH_USER)");
     }
 
     if (load_options & ADBC_LOAD_FLAG_SEARCH_SYSTEM) {
@@ -800,6 +811,10 @@ struct ManagedLibrary {
         return status;
       }
       search_paths.insert(search_paths.end(), system_paths.begin(), 
system_paths.end());
+    } else {
+      search_paths.emplace_back(
+          SearchPathSource::kDisabledAtRunTime,
+          "HKEY_LOCAL_MACHINE (enable ADBC_LOAD_FLAG_SEARCH_SYSTEM)");
     }
 
     info.lib_path = driver_path;
@@ -810,6 +825,26 @@ struct ManagedLibrary {
         GetSearchPaths(load_options & ~ADBC_LOAD_FLAG_SEARCH_ENV);
     auto status = SearchPathsForDriver(driver_path, more_search_paths, info, 
error);
     if (status == ADBC_STATUS_NOT_FOUND) {
+      if (!(load_options & ADBC_LOAD_FLAG_SEARCH_USER)) {
+        std::filesystem::path user_config_dir = InternalAdbcUserConfigDir();
+        std::string message = "user config dir ";
+        message += user_config_dir.string();
+        message += " (enable ADBC_LOAD_FLAG_SEARCH_USER)";
+        more_search_paths.emplace_back(SearchPathSource::kDisabledAtRunTime,
+                                       std::move(message));
+      }
+      // Windows searches registry keys, so this only applies to other OSes
+#if !defined(_WIN32)
+      if (!(load_options & ADBC_LOAD_FLAG_SEARCH_SYSTEM)) {
+        std::filesystem::path system_config_dir = 
InternalAdbcSystemConfigDir();
+        std::string message = "system config dir ";
+        message += system_config_dir.string();
+        message += " (enable ADBC_LOAD_FLAG_SEARCH_SYSTEM)";
+        more_search_paths.emplace_back(SearchPathSource::kDisabledAtRunTime,
+                                       std::move(message));
+      }
+#endif  // !defined(_WIN32)
+
       // 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.
       search_paths.insert(search_paths.end(), more_search_paths.begin(),
@@ -1364,6 +1399,16 @@ std::filesystem::path InternalAdbcUserConfigDir() {
   return config_dir;
 }
 
+#if !defined(_WIN32)
+std::filesystem::path InternalAdbcSystemConfigDir() {
+#if defined(__APPLE__)
+  return std::filesystem::path("/Library/Application Support/ADBC/Drivers");
+#else
+  return std::filesystem::path("/etc/adbc/drivers");
+#endif  // defined(__APPLE__)
+}
+#endif  // !defined(_WIN32)
+
 std::vector<std::filesystem::path> InternalAdbcParsePath(const 
std::string_view path) {
   std::vector<std::filesystem::path> result;
   if (path.empty()) {

Reply via email to