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 93baecb70 fix(c/driver/postgresql): handle connection options before 
Init (#2701)
93baecb70 is described below

commit 93baecb70ad819a627955479b1d1dc3be8e30fe2
Author: David Li <[email protected]>
AuthorDate: Tue Apr 15 11:48:12 2025 +0900

    fix(c/driver/postgresql): handle connection options before Init (#2701)
---
 c/driver/postgresql/connection.cc      | 22 +++++++++++++++++++-
 c/driver/postgresql/connection.h       |  4 ++++
 c/driver/postgresql/postgresql_test.cc | 38 ++++++++++++++++++++++++++++++++++
 3 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/c/driver/postgresql/connection.cc 
b/c/driver/postgresql/connection.cc
index 9e6c41c6f..d3b691138 100644
--- a/c/driver/postgresql/connection.cc
+++ b/c/driver/postgresql/connection.cc
@@ -32,6 +32,7 @@
 #include <vector>
 
 #include <arrow-adbc/adbc.h>
+#include <fmt/format.h>
 #include <libpq-fe.h>
 
 #include "database.h"
@@ -1108,6 +1109,11 @@ AdbcStatusCode PostgresConnection::Init(struct 
AdbcDatabase* database,
 
   std::ignore = PQsetNoticeProcessor(conn_, SilentNoticeProcessor, nullptr);
 
+  for (const auto& [key, value] : post_init_options_) {
+    RAISE_ADBC(SetOption(key.data(), value.data(), error));
+  }
+  post_init_options_.clear();
+
   return ADBC_STATUS_OK;
 }
 
@@ -1159,6 +1165,11 @@ AdbcStatusCode PostgresConnection::SetOption(const char* 
key, const char* value,
       return ADBC_STATUS_INVALID_ARGUMENT;
     }
 
+    if (!conn_) {
+      post_init_options_.emplace_back(key, value);
+      return ADBC_STATUS_OK;
+    }
+
     if (autocommit != autocommit_) {
       const char* query = autocommit ? "COMMIT" : "BEGIN TRANSACTION";
 
@@ -1174,9 +1185,18 @@ AdbcStatusCode PostgresConnection::SetOption(const char* 
key, const char* value,
     }
     return ADBC_STATUS_OK;
   } else if (std::strcmp(key, ADBC_CONNECTION_OPTION_CURRENT_DB_SCHEMA) == 0) {
+    if (!conn_) {
+      post_init_options_.emplace_back(key, value);
+      return ADBC_STATUS_OK;
+    }
+
     // PostgreSQL doesn't accept a parameter here
     char* value_esc = PQescapeIdentifier(conn_, value, strlen(value));
-    std::string query = std::string("SET search_path TO ") + value_esc;
+    if (!value_esc) {
+      SetError(error, "[libpq] Could not escape identifier: %s", 
PQerrorMessage(conn_));
+      return ADBC_STATUS_INTERNAL;
+    }
+    std::string query = fmt::format("SET search_path TO {}", value_esc);
     PQfreemem(value_esc);
 
     PqResultHelper result_helper{conn_, query};
diff --git a/c/driver/postgresql/connection.h b/c/driver/postgresql/connection.h
index 7683875b5..02e0c4f1b 100644
--- a/c/driver/postgresql/connection.h
+++ b/c/driver/postgresql/connection.h
@@ -20,6 +20,9 @@
 #include <array>
 #include <cstdint>
 #include <memory>
+#include <string>
+#include <utility>
+#include <vector>
 
 #include <arrow-adbc/adbc.h>
 #include <libpq-fe.h>
@@ -83,5 +86,6 @@ class PostgresConnection {
   PGconn* conn_;
   PGcancel* cancel_;
   bool autocommit_;
+  std::vector<std::pair<std::string, std::string>> post_init_options_;
 };
 }  // namespace adbcpq
diff --git a/c/driver/postgresql/postgresql_test.cc 
b/c/driver/postgresql/postgresql_test.cc
index b45fc5183..5167dbef7 100644
--- a/c/driver/postgresql/postgresql_test.cc
+++ b/c/driver/postgresql/postgresql_test.cc
@@ -691,6 +691,44 @@ TEST_F(PostgresConnectionTest, MetadataSetCurrentDbSchema) 
{
   ASSERT_THAT(AdbcStatementRelease(&statement.value, &error), 
IsOkStatus(&error));
 }
 
+TEST_F(PostgresConnectionTest, MetadataSetCurrentDbSchemaInit) {
+  // Regression test: setting the schema before Init (which Python does)
+
+  // 1. Create the schema
+  {
+    ASSERT_THAT(AdbcConnectionNew(&connection, &error), IsOkStatus(&error));
+    ASSERT_THAT(AdbcConnectionInit(&connection, &database, &error), 
IsOkStatus(&error));
+
+    adbc_validation::Handle<struct AdbcStatement> statement;
+    ASSERT_THAT(AdbcStatementNew(&connection, &statement.value, &error),
+                IsOkStatus(&error));
+
+    ASSERT_THAT(
+        AdbcStatementSetSqlQuery(&statement.value,
+                                 "CREATE SCHEMA IF NOT EXISTS regtestschema", 
&error),
+        IsOkStatus(&error));
+    ASSERT_THAT(AdbcStatementExecuteQuery(&statement.value, nullptr, nullptr, 
&error),
+                IsOkStatus(&error));
+
+    ASSERT_THAT(AdbcStatementRelease(&statement.value, &error), 
IsOkStatus(&error));
+    ASSERT_THAT(AdbcConnectionRelease(&connection, &error), 
IsOkStatus(&error));
+  }
+
+  // 2. Initialize a connection with the schema
+  {
+    ASSERT_THAT(AdbcConnectionNew(&connection, &error), IsOkStatus(&error));
+    ASSERT_THAT(
+        AdbcConnectionSetOption(&connection, 
ADBC_CONNECTION_OPTION_CURRENT_DB_SCHEMA,
+                                "regtestschema", &error),
+        IsOkStatus(&error));
+    ASSERT_THAT(AdbcConnectionInit(&connection, &database, &error), 
IsOkStatus(&error));
+
+    ASSERT_THAT(adbc_validation::ConnectionGetOption(
+                    &connection, ADBC_CONNECTION_OPTION_CURRENT_DB_SCHEMA, 
&error),
+                ::testing::Optional("regtestschema"s));
+  }
+}
+
 TEST_F(PostgresConnectionTest, MetadataGetSchemaCaseSensitiveTable) {
   ASSERT_THAT(AdbcConnectionNew(&connection, &error), IsOkStatus(&error));
   ASSERT_THAT(AdbcConnectionInit(&connection, &database, &error), 
IsOkStatus(&error));

Reply via email to