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 9b68784f refactor(c/driver/postgresql): Remove utils duplication (#628)
9b68784f is described below

commit 9b68784f3e0da710118074e1b5dcb28d1f47c2e7
Author: William Ayd <[email protected]>
AuthorDate: Mon May 1 21:33:14 2023 -0700

    refactor(c/driver/postgresql): Remove utils duplication (#628)
    
    - Use the new SetError with variadic arguments
    - Replaced StringBuilder with some std::string concatenation where
    applicable
    - Replaced any CHECK_ macro with the variant from either nanoarrow or
    existing util
    - Renamed util.h -> postgres_util.h to disambiguate; right now this
    seems just scoped to utils for network byte swapping
---
 c/driver/common/utils.c                         |   6 +-
 c/driver/postgresql/CMakeLists.txt              |   4 +
 c/driver/postgresql/connection.cc               |  19 +--
 c/driver/postgresql/database.cc                 |  23 +--
 c/driver/postgresql/{util.h => postgres_util.h} |  80 -----------
 c/driver/postgresql/postgresql.cc               |   7 +-
 c/driver/postgresql/statement.cc                | 177 +++++++++++++-----------
 c/driver/sqlite/sqlite.c                        | 147 +++++++++++---------
 r/adbcpostgresql/bootstrap.R                    |   4 +-
 r/adbcpostgresql/src/Makevars.in                |   1 +
 r/adbcpostgresql/src/Makevars.ucrt              |   1 +
 r/adbcpostgresql/src/Makevars.win               |   1 +
 12 files changed, 216 insertions(+), 254 deletions(-)

diff --git a/c/driver/common/utils.c b/c/driver/common/utils.c
index 8ea35c54..f21ce5b8 100644
--- a/c/driver/common/utils.c
+++ b/c/driver/common/utils.c
@@ -27,7 +27,6 @@
 #include <nanoarrow/nanoarrow.h>
 
 static size_t kErrorBufferSize = 256;
-static char kErrorPrefix[] = "[SQLite] ";
 
 static void ReleaseError(struct AdbcError* error) {
   free(error->message);
@@ -46,12 +45,9 @@ void SetError(struct AdbcError* error, const char* format, 
...) {
 
   error->release = &ReleaseError;
 
-  memcpy(error->message, kErrorPrefix, sizeof(kErrorPrefix));
-
   va_list args;
   va_start(args, format);
-  vsnprintf(error->message + sizeof(kErrorPrefix) - 1,
-            kErrorBufferSize - sizeof(kErrorPrefix) + 1, format, args);
+  vsnprintf(error->message, kErrorBufferSize, format, args);
   va_end(args);
 }
 
diff --git a/c/driver/postgresql/CMakeLists.txt 
b/c/driver/postgresql/CMakeLists.txt
index 23d5cf9f..8cf6f283 100644
--- a/c/driver/postgresql/CMakeLists.txt
+++ b/c/driver/postgresql/CMakeLists.txt
@@ -41,16 +41,19 @@ add_arrow_lib(adbc_driver_postgresql
               SHARED_LINK_FLAGS
               ${ADBC_LINK_FLAGS}
               SHARED_LINK_LIBS
+              adbc_driver_common
               nanoarrow
               ${LIBPQ_LINK_LIBRARIES}
               STATIC_LINK_LIBS
               ${LIBPQ_LINK_LIBRARIES}
+              adbc_driver_common
               nanoarrow
               ${LIBPQ_STATIC_LIBRARIES})
 include_directories(SYSTEM ${REPOSITORY_ROOT})
 include_directories(SYSTEM ${REPOSITORY_ROOT}/c/)
 include_directories(SYSTEM ${LIBPQ_INCLUDE_DIRS})
 include_directories(SYSTEM ${REPOSITORY_ROOT}/c/vendor)
+include_directories(SYSTEM ${REPOSITORY_ROOT}/c/driver/common)
 
 foreach(LIB_TARGET ${ADBC_LIBRARIES})
   target_compile_definitions(${LIB_TARGET} PRIVATE ADBC_EXPORTING)
@@ -74,6 +77,7 @@ if(ADBC_BUILD_TESTS)
                 ../../validation/adbc_validation.cc
                 ../../validation/adbc_validation_util.cc
                 EXTRA_LINK_LIBS
+                adbc_driver_common
                 nanoarrow
                 ${TEST_LINK_LIBS})
   target_compile_features(adbc-driver-postgresql-test PRIVATE cxx_std_17)
diff --git a/c/driver/postgresql/connection.cc 
b/c/driver/postgresql/connection.cc
index b61ebbef..e079b397 100644
--- a/c/driver/postgresql/connection.cc
+++ b/c/driver/postgresql/connection.cc
@@ -23,18 +23,18 @@
 #include <adbc.h>
 
 #include "database.h"
-#include "util.h"
+#include "utils.h"
 
 namespace adbcpq {
 AdbcStatusCode PostgresConnection::Commit(struct AdbcError* error) {
   if (autocommit_) {
-    SetError(error, "Cannot commit when autocommit is enabled");
+    SetError(error, "%s", "[libpq] Cannot commit when autocommit is enabled");
     return ADBC_STATUS_INVALID_STATE;
   }
 
   PGresult* result = PQexec(conn_, "COMMIT");
   if (PQresultStatus(result) != PGRES_COMMAND_OK) {
-    SetError(error, "Failed to commit: ", PQerrorMessage(conn_));
+    SetError(error, "%s%s", "[libpq] Failed to commit: ", 
PQerrorMessage(conn_));
     PQclear(result);
     return ADBC_STATUS_IO;
   }
@@ -53,7 +53,7 @@ AdbcStatusCode PostgresConnection::GetTableSchema(const char* 
catalog,
 AdbcStatusCode PostgresConnection::Init(struct AdbcDatabase* database,
                                         struct AdbcError* error) {
   if (!database || !database->private_data) {
-    SetError(error, "Must provide an initialized AdbcDatabase");
+    SetError(error, "%s", "[libpq] Must provide an initialized AdbcDatabase");
     return ADBC_STATUS_INVALID_ARGUMENT;
   }
   database_ =
@@ -71,13 +71,13 @@ AdbcStatusCode PostgresConnection::Release(struct 
AdbcError* error) {
 
 AdbcStatusCode PostgresConnection::Rollback(struct AdbcError* error) {
   if (autocommit_) {
-    SetError(error, "Cannot rollback when autocommit is enabled");
+    SetError(error, "%s", "[libpq] Cannot rollback when autocommit is 
enabled");
     return ADBC_STATUS_INVALID_STATE;
   }
 
   PGresult* result = PQexec(conn_, "ROLLBACK");
   if (PQresultStatus(result) != PGRES_COMMAND_OK) {
-    SetError(error, "Failed to rollback: ", PQerrorMessage(conn_));
+    SetError(error, "%s%s", "[libpq] Failed to rollback: ", 
PQerrorMessage(conn_));
     PQclear(result);
     return ADBC_STATUS_IO;
   }
@@ -94,7 +94,7 @@ AdbcStatusCode PostgresConnection::SetOption(const char* key, 
const char* value,
     } else if (std::strcmp(value, ADBC_OPTION_VALUE_DISABLED) == 0) {
       autocommit = false;
     } else {
-      SetError(error, "Invalid value for option ", key, ": ", value);
+      SetError(error, "%s%s%s%s", "[libpq] Invalid value for option ", key, ": 
", value);
       return ADBC_STATUS_INVALID_ARGUMENT;
     }
 
@@ -103,7 +103,8 @@ AdbcStatusCode PostgresConnection::SetOption(const char* 
key, const char* value,
 
       PGresult* result = PQexec(conn_, query);
       if (PQresultStatus(result) != PGRES_COMMAND_OK) {
-        SetError(error, "Failed to update autocommit: ", 
PQerrorMessage(conn_));
+        SetError(error, "%s%s",
+                 "[libpq] Failed to update autocommit: ", 
PQerrorMessage(conn_));
         PQclear(result);
         return ADBC_STATUS_IO;
       }
@@ -112,7 +113,7 @@ AdbcStatusCode PostgresConnection::SetOption(const char* 
key, const char* value,
     }
     return ADBC_STATUS_OK;
   }
-  SetError(error, "Unknown option ", key);
+  SetError(error, "%s%s", "[libpq] Unknown option ", key);
   return ADBC_STATUS_NOT_IMPLEMENTED;
 }
 }  // namespace adbcpq
diff --git a/c/driver/postgresql/database.cc b/c/driver/postgresql/database.cc
index 08ff0fc2..92accae9 100644
--- a/c/driver/postgresql/database.cc
+++ b/c/driver/postgresql/database.cc
@@ -17,6 +17,7 @@
 
 #include "database.h"
 
+#include <cinttypes>
 #include <cstring>
 #include <memory>
 #include <utility>
@@ -26,7 +27,7 @@
 #include <libpq-fe.h>
 #include <nanoarrow/nanoarrow.h>
 
-#include "util.h"
+#include "utils.h"
 
 namespace adbcpq {
 
@@ -42,7 +43,8 @@ AdbcStatusCode PostgresDatabase::Init(struct AdbcError* 
error) {
 
 AdbcStatusCode PostgresDatabase::Release(struct AdbcError* error) {
   if (open_connections_ != 0) {
-    SetError(error, "Database released with ", open_connections_, " open 
connections");
+    SetError(error, "%s%" PRId32 "%s", "[libpq] Database released with ",
+             open_connections_, " open connections");
     return ADBC_STATUS_INVALID_STATE;
   }
   return ADBC_STATUS_OK;
@@ -53,7 +55,7 @@ AdbcStatusCode PostgresDatabase::SetOption(const char* key, 
const char* value,
   if (strcmp(key, "uri") == 0) {
     uri_ = value;
   } else {
-    SetError(error, "Unknown database option ", key);
+    SetError(error, "%s%s", "[libpq] Unknown database option ", key);
     return ADBC_STATUS_NOT_IMPLEMENTED;
   }
   return ADBC_STATUS_OK;
@@ -61,12 +63,13 @@ AdbcStatusCode PostgresDatabase::SetOption(const char* key, 
const char* value,
 
 AdbcStatusCode PostgresDatabase::Connect(PGconn** conn, struct AdbcError* 
error) {
   if (uri_.empty()) {
-    SetError(error, "Must set database option 'uri' before creating a 
connection");
+    SetError(error, "%s",
+             "[libpq] Must set database option 'uri' before creating a 
connection");
     return ADBC_STATUS_INVALID_STATE;
   }
   *conn = PQconnectdb(uri_.c_str());
   if (PQstatus(*conn) != CONNECTION_OK) {
-    SetError(error, "Failed to connect: ", PQerrorMessage(*conn));
+    SetError(error, "%s%s", "[libpq] Failed to connect: ", 
PQerrorMessage(*conn));
     PQfinish(*conn);
     *conn = nullptr;
     return ADBC_STATUS_IO;
@@ -79,7 +82,7 @@ AdbcStatusCode PostgresDatabase::Disconnect(PGconn** conn, 
struct AdbcError* err
   PQfinish(*conn);
   *conn = nullptr;
   if (--open_connections_ < 0) {
-    SetError(error, "Open connection count underflowed");
+    SetError(error, "%s", "[libpq] Open connection count underflowed");
     return ADBC_STATUS_INTERNAL;
   }
   return ADBC_STATUS_OK;
@@ -144,7 +147,8 @@ ORDER BY
   if (pq_status == PGRES_TUPLES_OK) {
     InsertPgAttributeResult(result, resolver);
   } else {
-    SetError(error, "Failed to build type mapping table: ", 
PQerrorMessage(conn));
+    SetError(error, "%s%s",
+             "[libpq] Failed to build type mapping table: ", 
PQerrorMessage(conn));
     final_status = ADBC_STATUS_IO;
   }
 
@@ -158,7 +162,8 @@ ORDER BY
     if (pq_status == PGRES_TUPLES_OK) {
       InsertPgTypeResult(result, resolver);
     } else {
-      SetError(error, "Failed to build type mapping table: ", 
PQerrorMessage(conn));
+      SetError(error, "%s%s",
+               "[libpq] Failed to build type mapping table: ", 
PQerrorMessage(conn));
       final_status = ADBC_STATUS_IO;
     }
 
@@ -246,7 +251,7 @@ static inline int32_t InsertPgTypeResult(
 
     // If there's an array type and the insert succeeded, add that now too
     if (result == NANOARROW_OK && typarray != 0) {
-      std::string array_typname = StringBuilder("_", typname);
+      std::string array_typname = "_" + *typname;
       item.oid = typarray;
       item.typname = array_typname.c_str();
       item.typreceive = "array_recv";
diff --git a/c/driver/postgresql/util.h b/c/driver/postgresql/postgres_util.h
similarity index 62%
rename from c/driver/postgresql/util.h
rename to c/driver/postgresql/postgres_util.h
index c5982f0a..d03660b3 100644
--- a/c/driver/postgresql/util.h
+++ b/c/driver/postgresql/postgres_util.h
@@ -22,10 +22,6 @@
 #else
 #include <netinet/in.h>
 #endif
-#include <cstring>
-#include <sstream>
-#include <string>
-#include <utility>
 
 #if defined(__linux__)
 #include <endian.h>
@@ -37,9 +33,6 @@
 
 namespace adbcpq {
 
-#define CONCAT(x, y) x##y
-#define MAKE_NAME(x, y) CONCAT(x, y)
-
 #if defined(_WIN32) && defined(_MSC_VER)
 static inline uint32_t SwapNetworkToHost(uint16_t x) { return ntohs(x); }
 static inline uint32_t SwapHostToNetwork(uint16_t x) { return htons(x); }
@@ -76,79 +69,6 @@ static inline uint64_t SwapNetworkToHost(uint64_t x) { 
return be64toh(x); }
 static inline uint64_t SwapHostToNetwork(uint64_t x) { return htobe64(x); }
 #endif
 
-// see arrow/util/string_builder.h
-
-template <typename Head>
-static inline void StringBuilderRecursive(std::stringstream& stream, Head&& 
head) {
-  stream << head;
-}
-
-template <typename Head, typename... Tail>
-static inline void StringBuilderRecursive(std::stringstream& stream, Head&& 
head,
-                                          Tail&&... tail) {
-  StringBuilderRecursive(stream, std::forward<Head>(head));
-  StringBuilderRecursive(stream, std::forward<Tail>(tail)...);
-}
-
-template <typename... Args>
-static inline std::string StringBuilder(Args&&... args) {
-  std::stringstream ss;
-  StringBuilderRecursive(ss, std::forward<Args>(args)...);
-  return ss.str();
-}
-
-static inline void ReleaseError(struct AdbcError* error) {
-  delete[] error->message;
-  error->message = nullptr;
-  error->release = nullptr;
-}
-
-template <typename... Args>
-static inline void SetError(struct AdbcError* error, Args&&... args) {
-  if (!error) return;
-  std::string message = StringBuilder("[libpq] ", std::forward<Args>(args)...);
-  if (error->message) {
-    message.reserve(message.size() + 1 + std::strlen(error->message));
-    message.append(1, '\n');
-    message.append(error->message);
-    delete[] error->message;
-  }
-  error->message = new char[message.size() + 1];
-  message.copy(error->message, message.size());
-  error->message[message.size()] = '\0';
-  error->release = ReleaseError;
-}
-
-#define CHECK_IMPL(NAME, EXPR)          \
-  do {                                  \
-    const AdbcStatusCode NAME = (EXPR); \
-    if (NAME != ADBC_STATUS_OK) {       \
-      return NAME;                      \
-    }                                   \
-  } while (false)
-#define CHECK(EXPR) CHECK_IMPL(MAKE_NAME(adbc_status_, __COUNTER__), EXPR)
-
-#define CHECK_NA_ADBC_IMPL(NAME, EXPR, ERROR)                    \
-  do {                                                           \
-    const int NAME = (EXPR);                                     \
-    if (NAME) {                                                  \
-      SetError((ERROR), #EXPR " failed: ", std::strerror(NAME)); \
-      return ADBC_STATUS_INTERNAL;                               \
-    }                                                            \
-  } while (false)
-/// Check an errno-style code and return an ADBC code if necessary.
-#define CHECK_NA_ADBC(EXPR, ERROR) \
-  CHECK_NA_ADBC_IMPL(MAKE_NAME(errno_status_, __COUNTER__), EXPR, ERROR)
-
-#define CHECK_NA_IMPL(NAME, EXPR) \
-  do {                            \
-    const int NAME = (EXPR);      \
-    if (NAME) return NAME;        \
-  } while (false)
-
-/// Check an errno-style code and return it if necessary.
-#define CHECK_NA(EXPR) CHECK_NA_IMPL(MAKE_NAME(errno_status_, __COUNTER__), 
EXPR)
-
 /// Endianness helpers
 
 static inline uint16_t LoadNetworkUInt16(const char* buf) {
diff --git a/c/driver/postgresql/postgresql.cc 
b/c/driver/postgresql/postgresql.cc
index 8cb998d1..1305f197 100644
--- a/c/driver/postgresql/postgresql.cc
+++ b/c/driver/postgresql/postgresql.cc
@@ -25,7 +25,7 @@
 #include "connection.h"
 #include "database.h"
 #include "statement.h"
-#include "util.h"
+#include "utils.h"
 
 using adbcpq::PostgresConnection;
 using adbcpq::PostgresDatabase;
@@ -51,7 +51,6 @@ using adbcpq::PostgresStatement;
 // AdbcDatabase
 
 namespace {
-using adbcpq::SetError;
 AdbcStatusCode PostgresDatabaseInit(struct AdbcDatabase* database,
                                     struct AdbcError* error) {
   if (!database || !database->private_data) return ADBC_STATUS_INVALID_STATE;
@@ -62,11 +61,11 @@ AdbcStatusCode PostgresDatabaseInit(struct AdbcDatabase* 
database,
 AdbcStatusCode PostgresDatabaseNew(struct AdbcDatabase* database,
                                    struct AdbcError* error) {
   if (!database) {
-    SetError(error, "database must not be null");
+    SetError(error, "%s", "[libpq] database must not be null");
     return ADBC_STATUS_INVALID_STATE;
   }
   if (database->private_data) {
-    SetError(error, "database is already initialized");
+    SetError(error, "%s", "[libpq] database is already initialized");
     return ADBC_STATUS_INVALID_STATE;
   }
   auto impl = std::make_shared<PostgresDatabase>();
diff --git a/c/driver/postgresql/statement.cc b/c/driver/postgresql/statement.cc
index c0d3de3d..01d30d69 100644
--- a/c/driver/postgresql/statement.cc
+++ b/c/driver/postgresql/statement.cc
@@ -19,6 +19,7 @@
 
 #include <array>
 #include <cerrno>
+#include <cinttypes>
 #include <cstring>
 #include <iostream>
 #include <memory>
@@ -31,7 +32,8 @@
 
 #include "connection.h"
 #include "postgres_type.h"
-#include "util.h"
+#include "postgres_util.h"
+#include "utils.h"
 
 namespace adbcpq {
 
@@ -112,18 +114,19 @@ AdbcStatusCode InferSchema(const PostgresTypeResolver& 
type_resolver, PGresult*
   ArrowError na_error;
   const int num_fields = PQnfields(result);
   ArrowSchemaInit(out);
-  CHECK_NA_ADBC(ArrowSchemaSetTypeStruct(out, num_fields), error);
+  CHECK_NA(INTERNAL, ArrowSchemaSetTypeStruct(out, num_fields), error);
   for (int i = 0; i < num_fields; i++) {
     const Oid pg_oid = PQftype(result, i);
     PostgresType pg_type;
     if (type_resolver.Find(pg_oid, &pg_type, &na_error) != NANOARROW_OK) {
-      SetError(error, "Column #", i + 1, " (\"", PQfname(result, i),
-               "\") has unknown type code ", pg_oid);
+      SetError(error, "%s%d%s%s%s%d", "[libpq] Column #", i + 1, " (\"",
+               PQfname(result, i), "\") has unknown type code ", pg_oid);
       return ADBC_STATUS_NOT_IMPLEMENTED;
     }
 
-    CHECK_NA_ADBC(pg_type.WithFieldName(PQfname(result, 
i)).SetSchema(out->children[i]),
-                  error);
+    CHECK_NA(INTERNAL,
+             pg_type.WithFieldName(PQfname(result, 
i)).SetSchema(out->children[i]),
+             error);
   }
   return ADBC_STATUS_OK;
 }
@@ -154,21 +157,23 @@ struct BindStream {
 
   template <typename Callback>
   AdbcStatusCode Begin(Callback&& callback, struct AdbcError* error) {
-    CHECK_NA_ADBC(bind->get_schema(&bind.value, &bind_schema.value), error);
-    CHECK_NA_ADBC(
+    CHECK_NA(INTERNAL, bind->get_schema(&bind.value, &bind_schema.value), 
error);
+    CHECK_NA(
+        INTERNAL,
         ArrowSchemaViewInit(&bind_schema_view, &bind_schema.value, /*error*/ 
nullptr),
         error);
 
     if (bind_schema_view.type != ArrowType::NANOARROW_TYPE_STRUCT) {
-      SetError(error, "Bind parameters must have type STRUCT");
+      SetError(error, "%s", "[libpq] Bind parameters must have type STRUCT");
       return ADBC_STATUS_INVALID_STATE;
     }
 
     bind_schema_fields.resize(bind_schema->n_children);
     for (size_t i = 0; i < bind_schema_fields.size(); i++) {
-      CHECK_NA_ADBC(ArrowSchemaViewInit(&bind_schema_fields[i], 
bind_schema->children[i],
-                                        /*error*/ nullptr),
-                    error);
+      CHECK_NA(INTERNAL,
+               ArrowSchemaViewInit(&bind_schema_fields[i], 
bind_schema->children[i],
+                                   /*error*/ nullptr),
+               error);
     }
 
     return std::move(callback)();
@@ -206,7 +211,8 @@ struct BindStream {
           param_lengths[i] = 0;
           break;
         default:
-          SetError(error, "Field #", i + 1, " ('", 
bind_schema->children[i]->name,
+          SetError(error, "%s%" PRIu64 "%s%s%s%s", "[libpq] Field #",
+                   static_cast<uint64_t>(i + 1), " ('", 
bind_schema->children[i]->name,
                    "') has unsupported parameter type ",
                    ArrowTypeString(bind_schema_fields[i].type));
           return ADBC_STATUS_NOT_IMPLEMENTED;
@@ -214,7 +220,8 @@ struct BindStream {
 
       param_types[i] = type_resolver.GetOID(type_id);
       if (param_types[i] == 0) {
-        SetError(error, "Field #", i + 1, " ('", 
bind_schema->children[i]->name,
+        SetError(error, "%s%" PRIu64 "%s%s%s%s", "[libpq] Field #",
+                 static_cast<uint64_t>(i + 1), " ('", 
bind_schema->children[i]->name,
                  "') has type with no corresponding PostgreSQL type ",
                  ArrowTypeString(bind_schema_fields[i].type));
         return ADBC_STATUS_NOT_IMPLEMENTED;
@@ -235,8 +242,8 @@ struct BindStream {
     PGresult* result = PQprepare(conn, /*stmtName=*/"", query.c_str(),
                                  /*nParams=*/bind_schema->n_children, 
param_types.data());
     if (PQresultStatus(result) != PGRES_COMMAND_OK) {
-      SetError(error, "Failed to prepare query: ", PQerrorMessage(conn));
-      SetError(error, "Query: ", query);
+      SetError(error, "%s%s", "[libpq] Failed to prepare query: ", 
PQerrorMessage(conn));
+      SetError(error, "%s%s", "[libpq] Query: ", query.c_str());
       PQclear(result);
       return ADBC_STATUS_IO;
     }
@@ -253,7 +260,8 @@ struct BindStream {
       int res = bind->get_next(&bind.value, &array.value);
       if (res != 0) {
         // TODO: include errno
-        SetError(error, "Failed to read next batch from stream of bind 
parameters: ",
+        SetError(error, "%s%s",
+                 "[libpq] Failed to read next batch from stream of bind 
parameters: ",
                  bind->get_last_error(&bind.value));
         return ADBC_STATUS_IO;
       }
@@ -261,11 +269,12 @@ struct BindStream {
 
       Handle<struct ArrowArrayView> array_view;
       // TODO: include error messages
-      CHECK_NA_ADBC(
+      CHECK_NA(
+          INTERNAL,
           ArrowArrayViewInitFromSchema(&array_view.value, &bind_schema.value, 
nullptr),
           error);
-      CHECK_NA_ADBC(ArrowArrayViewSetArray(&array_view.value, &array.value, 
nullptr),
-                    error);
+      CHECK_NA(INTERNAL, ArrowArrayViewSetArray(&array_view.value, 
&array.value, nullptr),
+               error);
 
       for (int64_t row = 0; row < array->length; row++) {
         for (int64_t col = 0; col < array_view->n_children; col++) {
@@ -304,7 +313,8 @@ struct BindStream {
             }
             default:
               // TODO: data type to string
-              SetError(error, "Field #", col + 1, " ('", 
bind_schema->children[col]->name,
+              SetError(error, "%s%" PRId64 "%s%s%s%ud", "[libpq] Field #", col 
+ 1, " ('",
+                       bind_schema->children[col]->name,
                        "') has unsupported type for ingestion ",
                        bind_schema_fields[col].type);
               return ADBC_STATUS_NOT_IMPLEMENTED;
@@ -317,7 +327,8 @@ struct BindStream {
                                 /*resultFormat=*/0 /*text*/);
 
         if (PQresultStatus(result) != PGRES_COMMAND_OK) {
-          SetError(error, "Failed to execute prepared statement: ", 
PQerrorMessage(conn));
+          SetError(error, "%s%s", "[libpq] Failed to execute prepared 
statement: ",
+                   PQerrorMessage(conn));
           PQclear(result);
           return ADBC_STATUS_IO;
         }
@@ -338,7 +349,7 @@ int TupleReader::GetSchema(struct ArrowSchema* out) {
   }
 
   std::memset(out, 0, sizeof(*out));
-  CHECK_NA(ArrowSchemaDeepCopy(&schema_, out));
+  NANOARROW_RETURN_NOT_OK(ArrowSchemaDeepCopy(&schema_, out));
   return 0;
 }
 
@@ -356,19 +367,19 @@ int TupleReader::GetNext(struct ArrowArray* out) {
   // TODO: consistently release out on error (use another trampoline?)
   int na_res = ArrowArrayInitFromSchema(out, &schema_, &error);
   if (na_res != 0) {
-    last_error_ = StringBuilder("[libpq] Failed to init output array: ", 
na_res,
-                                std::strerror(na_res), ": ", error.message);
+    last_error_ = "[libpq] Failed to init output array: " + 
std::to_string(na_res) +
+                  std::strerror(na_res) + ": " + error.message;
     if (out->release) out->release(out);
     return na_res;
   }
 
   std::vector<ArrowSchemaView> fields(schema_.n_children);
-  CHECK_NA(ArrowArrayStartAppending(out));
+  NANOARROW_RETURN_NOT_OK(ArrowArrayStartAppending(out));
   for (int col = 0; col < schema_.n_children; col++) {
     na_res = ArrowSchemaViewInit(&fields[col], schema_.children[col], &error);
     if (na_res != 0) {
-      last_error_ = StringBuilder("[libpq] Failed to init schema view: ", 
na_res,
-                                  std::strerror(na_res), ": ", error.message);
+      last_error_ = "[libpq] Failed to init schema view: " + 
std::to_string(na_res) +
+                    std::strerror(na_res) + ": " + error.message;
       if (out->release) out->release(out);
       return na_res;
     }
@@ -432,7 +443,7 @@ int TupleReader::GetNext(struct ArrowArray* out) {
   if (na_res != 0) {
     result_code = na_res;
     if (!last_error_.empty()) last_error_ += '\n';
-    last_error_ += StringBuilder("[libpq] Failed to build result array: ", 
error.message);
+    last_error_ += "[libpq] Failed to build result array" + 
std::string(error.message);
   }
 
   // Check the server-side response
@@ -440,8 +451,8 @@ int TupleReader::GetNext(struct ArrowArray* out) {
   const int pq_status = PQresultStatus(result_);
   if (pq_status != PGRES_COMMAND_OK) {
     if (!last_error_.empty()) last_error_ += '\n';
-    last_error_ += StringBuilder("[libpq] Query failed: (", pq_status, ") ",
-                                 PQresultErrorMessage(result_));
+    last_error_ += "[libpq] Query failed: (" + std::to_string(pq_status) + ") 
" +
+                   PQresultErrorMessage(result_);
     result_code = EIO;
   }
   PQclear(result_);
@@ -485,8 +496,8 @@ int TupleReader::AppendNext(struct ArrowSchemaView* fields, 
const char* buf, int
     // end-of-stream
     return 0;
   } else if (field_count != schema_.n_children) {
-    last_error_ = StringBuilder("[libpq] Expected ", schema_.n_children,
-                                " fields but found ", field_count);
+    last_error_ = "[libpq] Expected " + std::to_string(schema_.n_children) +
+                  " fields but found " + std::to_string(field_count);
     return EIO;
   }
 
@@ -496,10 +507,11 @@ int TupleReader::AppendNext(struct ArrowSchemaView* 
fields, const char* buf, int
 
     // TODO: set error message here
     if (field_length != kNullFieldLength) {
-      CHECK_NA(AppendValue(fields, buf, col, *row_count, field_length, out));
+      NANOARROW_RETURN_NOT_OK(
+          AppendValue(fields, buf, col, *row_count, field_length, out));
       buf += field_length;
     } else {
-      CHECK_NA(ArrowArrayAppendNull(out->children[col], 1));
+      NANOARROW_RETURN_NOT_OK(ArrowArrayAppendNull(out->children[col], 1));
     }
   }
   (*row_count)++;
@@ -515,12 +527,12 @@ int TupleReader::AppendValue(struct ArrowSchemaView* 
fields, const char* buf, in
       buf += 1;
 
       if (raw_value != 0 && raw_value != 1) {
-        last_error_ = StringBuilder("[libpq] Column #", col + 1, " (\"",
-                                    schema_.children[col]->name,
-                                    "\"): invalid BOOL value ", raw_value);
+        last_error_ = "[libpq] Column #" + std::to_string(col + 1) + " (\"" +
+                      schema_.children[col]->name + "\"): invalid BOOL value " 
+
+                      std::to_string(raw_value);
         return EINVAL;
       }
-      CHECK_NA(ArrowArrayAppendInt(out->children[col], raw_value));
+      NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(out->children[col], 
raw_value));
       break;
     }
     case NANOARROW_TYPE_DOUBLE: {
@@ -530,7 +542,7 @@ int TupleReader::AppendValue(struct ArrowSchemaView* 
fields, const char* buf, in
       buf += sizeof(uint64_t);
       double value = 0.0;
       std::memcpy(&value, &raw_value, sizeof(double));
-      CHECK_NA(ArrowArrayAppendDouble(out->children[col], value));
+      NANOARROW_RETURN_NOT_OK(ArrowArrayAppendDouble(out->children[col], 
value));
       break;
     }
     case NANOARROW_TYPE_FLOAT: {
@@ -540,40 +552,42 @@ int TupleReader::AppendValue(struct ArrowSchemaView* 
fields, const char* buf, in
       buf += sizeof(uint32_t);
       float value = 0.0;
       std::memcpy(&value, &raw_value, sizeof(float));
-      CHECK_NA(ArrowArrayAppendDouble(out->children[col], value));
+      NANOARROW_RETURN_NOT_OK(ArrowArrayAppendDouble(out->children[col], 
value));
       break;
     }
     case NANOARROW_TYPE_INT16: {
       int32_t value = LoadNetworkInt16(buf);
       buf += sizeof(int32_t);
-      CHECK_NA(ArrowArrayAppendInt(out->children[col], value));
+      NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(out->children[col], value));
       break;
     }
     case NANOARROW_TYPE_INT32: {
       int32_t value = LoadNetworkInt32(buf);
       buf += sizeof(int32_t);
-      CHECK_NA(ArrowArrayAppendInt(out->children[col], value));
+      NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(out->children[col], value));
       break;
     }
     case NANOARROW_TYPE_INT64: {
       int64_t value = LoadNetworkInt64(buf);
       buf += sizeof(int64_t);
-      CHECK_NA(ArrowArrayAppendInt(out->children[col], value));
+      NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(out->children[col], value));
       break;
     }
     case NANOARROW_TYPE_BINARY: {
-      CHECK_NA(ArrowArrayAppendBytes(out->children[col], {buf, field_length}));
+      NANOARROW_RETURN_NOT_OK(
+          ArrowArrayAppendBytes(out->children[col], {buf, field_length}));
       break;
     }
     case NANOARROW_TYPE_STRING: {
       // textsend() in varlena.c
-      CHECK_NA(ArrowArrayAppendString(out->children[col], {buf, 
field_length}));
+      NANOARROW_RETURN_NOT_OK(
+          ArrowArrayAppendString(out->children[col], {buf, field_length}));
       break;
     }
     default:
-      last_error_ =
-          StringBuilder("[libpq] Column #", col + 1, " (\"", 
schema_.children[col]->name,
-                        "\") has unsupported type ", fields[col].type);
+      last_error_ = "[libpq] Column #" + std::to_string(col + 1) + " (\"" +
+                    schema_.children[col]->name + "\") has unsupported type " +
+                    std::to_string(fields[col].type);
       return ENOTSUP;
   }
   return 0;
@@ -614,7 +628,7 @@ void TupleReader::ReleaseTrampoline(struct 
ArrowArrayStream* self) {
 AdbcStatusCode PostgresStatement::New(struct AdbcConnection* connection,
                                       struct AdbcError* error) {
   if (!connection || !connection->private_data) {
-    SetError(error, "Must provide an initialized AdbcConnection");
+    SetError(error, "%s", "[libpq] Must provide an initialized 
AdbcConnection");
     return ADBC_STATUS_INVALID_ARGUMENT;
   }
   connection_ =
@@ -628,10 +642,10 @@ AdbcStatusCode PostgresStatement::Bind(struct ArrowArray* 
values,
                                        struct ArrowSchema* schema,
                                        struct AdbcError* error) {
   if (!values || !values->release) {
-    SetError(error, "Must provide non-NULL array");
+    SetError(error, "%s", "[libpq] Must provide non-NULL array");
     return ADBC_STATUS_INVALID_ARGUMENT;
   } else if (!schema || !schema->release) {
-    SetError(error, "Must provide non-NULL schema");
+    SetError(error, "%s", "[libpq] Must provide non-NULL schema");
     return ADBC_STATUS_INVALID_ARGUMENT;
   }
 
@@ -650,7 +664,7 @@ AdbcStatusCode PostgresStatement::Bind(struct ArrowArray* 
values,
 AdbcStatusCode PostgresStatement::Bind(struct ArrowArrayStream* stream,
                                        struct AdbcError* error) {
   if (!stream || !stream->release) {
-    SetError(error, "Must provide non-NULL stream");
+    SetError(error, "%s", "[libpq] Must provide non-NULL stream");
     return ADBC_STATUS_INVALID_ARGUMENT;
   }
   // Move stream
@@ -689,21 +703,23 @@ AdbcStatusCode PostgresStatement::CreateBulkTable(
         break;
       default:
         // TODO: data type to string
-        SetError(error, "Field #", i + 1, " ('", 
source_schema.children[i]->name,
+        SetError(error, "%s%" PRIu64 "%s%s%s%ud", "[libpq] Field #",
+                 static_cast<uint64_t>(i + 1), " ('", 
source_schema.children[i]->name,
                  "') has unsupported type for ingestion ", 
source_schema_fields[i].type);
         return ADBC_STATUS_NOT_IMPLEMENTED;
     }
   }
 
   create += ")";
-  SetError(error, create);
+  SetError(error, "%s%s", "[libpq] ", create.c_str());
   PGresult* result = PQexecParams(connection_->conn(), create.c_str(), 
/*nParams=*/0,
                                   /*paramTypes=*/nullptr, 
/*paramValues=*/nullptr,
                                   /*paramLengths=*/nullptr, 
/*paramFormats=*/nullptr,
                                   /*resultFormat=*/1 /*(binary)*/);
   if (PQresultStatus(result) != PGRES_COMMAND_OK) {
-    SetError(error, "Failed to create table: ", 
PQerrorMessage(connection_->conn()));
-    SetError(error, "Query: ", create);
+    SetError(error, "%s%s",
+             "[libpq] Failed to create table: ", 
PQerrorMessage(connection_->conn()));
+    SetError(error, "%s%s", "[libpq] Query: ", create.c_str());
     PQclear(result);
     return ADBC_STATUS_IO;
   }
@@ -715,22 +731,24 @@ AdbcStatusCode 
PostgresStatement::ExecutePreparedStatement(
     struct ArrowArrayStream* stream, int64_t* rows_affected, struct AdbcError* 
error) {
   if (!bind_.release) {
     // TODO: set an empty stream just to unify the code paths
-    SetError(error, "Prepared statements without parameters are not 
implemented");
+    SetError(error, "%s",
+             "[libpq] Prepared statements without parameters are not 
implemented");
     return ADBC_STATUS_NOT_IMPLEMENTED;
   }
   if (stream) {
     // TODO:
-    SetError(error, "Prepared statements returning result sets are not 
implemented");
+    SetError(error, "%s",
+             "[libpq] Prepared statements returning result sets are not 
implemented");
     return ADBC_STATUS_NOT_IMPLEMENTED;
   }
 
   BindStream bind_stream(std::move(bind_));
   std::memset(&bind_, 0, sizeof(bind_));
 
-  CHECK(bind_stream.Begin([&]() { return ADBC_STATUS_OK; }, error));
-  CHECK(bind_stream.SetParamTypes(*type_resolver_, error));
-  CHECK(bind_stream.Prepare(connection_->conn(), query_, error));
-  CHECK(bind_stream.Execute(connection_->conn(), rows_affected, error));
+  RAISE_ADBC(bind_stream.Begin([&]() { return ADBC_STATUS_OK; }, error));
+  RAISE_ADBC(bind_stream.SetParamTypes(*type_resolver_, error));
+  RAISE_ADBC(bind_stream.Prepare(connection_->conn(), query_, error));
+  RAISE_ADBC(bind_stream.Execute(connection_->conn(), rows_affected, error));
   return ADBC_STATUS_OK;
 }
 
@@ -760,7 +778,7 @@ AdbcStatusCode PostgresStatement::ExecuteQuery(struct 
ArrowArrayStream* stream,
   }
 
   if (query_.empty()) {
-    SetError(error, "Must SetSqlQuery before ExecuteQuery");
+    SetError(error, "%s", "[libpq] Must SetSqlQuery before ExecuteQuery");
     return ADBC_STATUS_INVALID_STATE;
   }
 
@@ -773,8 +791,8 @@ AdbcStatusCode PostgresStatement::ExecuteQuery(struct 
ArrowArrayStream* stream,
                      /*paramTypes=*/nullptr, /*paramValues=*/nullptr,
                      /*paramLengths=*/nullptr, /*paramFormats=*/nullptr, 
kPgBinaryFormat);
     if (PQresultStatus(result) != PGRES_TUPLES_OK) {
-      SetError(error, "Query was: ", schema_query);
-      SetError(error, "Failed to execute query: could not infer schema: ",
+      SetError(error, "%s%s", "[libpq] Query was: ", schema_query.c_str());
+      SetError(error, "%s%s", "[libpq] Failed to execute query: could not 
infer schema: ",
                PQerrorMessage(connection_->conn()));
       PQclear(result);
       return ADBC_STATUS_IO;
@@ -792,8 +810,8 @@ AdbcStatusCode PostgresStatement::ExecuteQuery(struct 
ArrowArrayStream* stream,
                      /*paramTypes=*/nullptr, /*paramValues=*/nullptr,
                      /*paramLengths=*/nullptr, /*paramFormats=*/nullptr, 
kPgBinaryFormat);
     if (PQresultStatus(reader_.result_) != PGRES_COPY_OUT) {
-      SetError(error, "Query was: ", copy_query);
-      SetError(error, "Failed to execute query: could not begin COPY: ",
+      SetError(error, "%s%s", "[libpq] Query was: ", copy_query.c_str());
+      SetError(error, "%s%s", "[libpq] Failed to execute query: could not 
begin COPY: ",
                PQerrorMessage(connection_->conn()));
       ClearResult();
       return ADBC_STATUS_IO;
@@ -809,13 +827,13 @@ AdbcStatusCode PostgresStatement::ExecuteQuery(struct 
ArrowArrayStream* stream,
 AdbcStatusCode PostgresStatement::ExecuteUpdateBulk(int64_t* rows_affected,
                                                     struct AdbcError* error) {
   if (!bind_.release) {
-    SetError(error, "Must Bind() before Execute() for bulk ingestion");
+    SetError(error, "%s", "[libpq] Must Bind() before Execute() for bulk 
ingestion");
     return ADBC_STATUS_INVALID_STATE;
   }
 
   BindStream bind_stream(std::move(bind_));
   std::memset(&bind_, 0, sizeof(bind_));
-  CHECK(bind_stream.Begin(
+  RAISE_ADBC(bind_stream.Begin(
       [&]() -> AdbcStatusCode {
         if (!ingest_.append) {
           // CREATE TABLE
@@ -825,7 +843,7 @@ AdbcStatusCode 
PostgresStatement::ExecuteUpdateBulk(int64_t* rows_affected,
         return ADBC_STATUS_OK;
       },
       error));
-  CHECK(bind_stream.SetParamTypes(*type_resolver_, error));
+  RAISE_ADBC(bind_stream.SetParamTypes(*type_resolver_, error));
 
   std::string insert = "INSERT INTO ";
   insert += ingest_.target;
@@ -837,15 +855,15 @@ AdbcStatusCode 
PostgresStatement::ExecuteUpdateBulk(int64_t* rows_affected,
   }
   insert += ")";
 
-  CHECK(bind_stream.Prepare(connection_->conn(), insert, error));
-  CHECK(bind_stream.Execute(connection_->conn(), rows_affected, error));
+  RAISE_ADBC(bind_stream.Prepare(connection_->conn(), insert, error));
+  RAISE_ADBC(bind_stream.Execute(connection_->conn(), rows_affected, error));
   return ADBC_STATUS_OK;
 }
 
 AdbcStatusCode PostgresStatement::ExecuteUpdateQuery(int64_t* rows_affected,
                                                      struct AdbcError* error) {
   if (query_.empty()) {
-    SetError(error, "Must SetSqlQuery before ExecuteQuery");
+    SetError(error, "%s", "[libpq] Must SetSqlQuery before ExecuteQuery");
     return ADBC_STATUS_INVALID_STATE;
   }
 
@@ -862,8 +880,9 @@ AdbcStatusCode 
PostgresStatement::ExecuteUpdateQuery(int64_t* rows_affected,
                           /*resultFormat=*/kPgBinaryFormat);
   }
   if (PQresultStatus(result) != PGRES_COMMAND_OK) {
-    SetError(error, "Query was: ", query_);
-    SetError(error, "Failed to execute query: ", 
PQerrorMessage(connection_->conn()));
+    SetError(error, "%s%s", "[libpq] Query was: ", query_.c_str());
+    SetError(error, "%s%s",
+             "[libpq] Failed to execute query: ", 
PQerrorMessage(connection_->conn()));
     PQclear(result);
     return ADBC_STATUS_IO;
   }
@@ -879,7 +898,7 @@ AdbcStatusCode PostgresStatement::GetParameterSchema(struct 
ArrowSchema* schema,
 
 AdbcStatusCode PostgresStatement::Prepare(struct AdbcError* error) {
   if (query_.empty()) {
-    SetError(error, "Must SetSqlQuery() before Prepare()");
+    SetError(error, "%s", "[libpq] Must SetSqlQuery() before Prepare()");
     return ADBC_STATUS_INVALID_STATE;
   }
 
@@ -916,11 +935,11 @@ AdbcStatusCode PostgresStatement::SetOption(const char* 
key, const char* value,
     } else if (std::strcmp(value, ADBC_INGEST_OPTION_MODE_APPEND) == 0) {
       ingest_.append = true;
     } else {
-      SetError(error, "Invalid value ", value, " for option ", key);
+      SetError(error, "%s%s%s%s", "[libpq] Invalid value ", value, " for 
option ", key);
       return ADBC_STATUS_INVALID_ARGUMENT;
     }
   } else {
-    SetError(error, "Unknown statement option ", key);
+    SetError(error, "%s%s", "[libq] Unknown statement option ", key);
     return ADBC_STATUS_NOT_IMPLEMENTED;
   }
   return ADBC_STATUS_OK;
diff --git a/c/driver/sqlite/sqlite.c b/c/driver/sqlite/sqlite.c
index 2cc3276c..43f9d980 100644
--- a/c/driver/sqlite/sqlite.c
+++ b/c/driver/sqlite/sqlite.c
@@ -42,25 +42,25 @@ static const uint32_t kSupportedInfoCodes[] = {
 
 // Private names (to avoid conflicts when using the driver manager)
 
-#define CHECK_DB_INIT(NAME, ERROR)                             \
-  if (!NAME->private_data) {                                   \
-    SetError(ERROR, "%s: database not initialized", __func__); \
-    return ADBC_STATUS_INVALID_STATE;                          \
+#define CHECK_DB_INIT(NAME, ERROR)                                      \
+  if (!NAME->private_data) {                                            \
+    SetError(ERROR, "[SQLite] %s: database not initialized", __func__); \
+    return ADBC_STATUS_INVALID_STATE;                                   \
   }
-#define CHECK_CONN_INIT(NAME, ERROR)                             \
-  if (!NAME->private_data) {                                     \
-    SetError(ERROR, "%s: connection not initialized", __func__); \
-    return ADBC_STATUS_INVALID_STATE;                            \
+#define CHECK_CONN_INIT(NAME, ERROR)                                      \
+  if (!NAME->private_data) {                                              \
+    SetError(ERROR, "[SQLite] %s: connection not initialized", __func__); \
+    return ADBC_STATUS_INVALID_STATE;                                     \
   }
-#define CHECK_STMT_INIT(NAME, ERROR)                            \
-  if (!NAME->private_data) {                                    \
-    SetError(ERROR, "%s: statement not initialized", __func__); \
-    return ADBC_STATUS_INVALID_STATE;                           \
+#define CHECK_STMT_INIT(NAME, ERROR)                                     \
+  if (!NAME->private_data) {                                             \
+    SetError(ERROR, "[SQLite] %s: statement not initialized", __func__); \
+    return ADBC_STATUS_INVALID_STATE;                                    \
   }
 
 AdbcStatusCode SqliteDatabaseNew(struct AdbcDatabase* database, struct 
AdbcError* error) {
   if (database->private_data) {
-    SetError(error, "AdbcDatabaseNew: database already allocated");
+    SetError(error, "[SQLite] AdbcDatabaseNew: database already allocated");
     return ADBC_STATUS_INVALID_STATE;
   }
 
@@ -81,7 +81,8 @@ AdbcStatusCode SqliteDatabaseSetOption(struct AdbcDatabase* 
database, const char
     strncpy(db->uri, value, len);
     return ADBC_STATUS_OK;
   }
-  SetError(error, "Unknown database option %s=%s", key, value ? value : 
"(NULL)");
+  SetError(error, "[SQLite] Unknown database option %s=%s", key,
+           value ? value : "(NULL)");
   return ADBC_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -92,9 +93,9 @@ int OpenDatabase(const char* maybe_uri, sqlite3** db, struct 
AdbcError* error) {
                            /*zVfs=*/NULL);
   if (rc != SQLITE_OK) {
     if (*db) {
-      SetError(error, "Failed to open %s: %s", uri, sqlite3_errmsg(*db));
+      SetError(error, "[SQLite] Failed to open %s: %s", uri, 
sqlite3_errmsg(*db));
     } else {
-      SetError(error, "Failed to open %s: failed to allocate memory", uri);
+      SetError(error, "[SQLite] Failed to open %s: failed to allocate memory", 
uri);
     }
     (void)sqlite3_close(*db);
     *db = NULL;
@@ -112,7 +113,7 @@ AdbcStatusCode ExecuteQuery(struct SqliteConnection* conn, 
const char* query,
   }
   rc = sqlite3_finalize(stmt);
   if (rc != SQLITE_OK && rc != SQLITE_DONE) {
-    SetError(error, "Failed to execute query \"%s\": %s", query,
+    SetError(error, "[SQLite] Failed to execute query \"%s\": %s", query,
              sqlite3_errmsg(conn->conn));
     return ADBC_STATUS_INTERNAL;
   }
@@ -125,7 +126,7 @@ AdbcStatusCode SqliteDatabaseInit(struct AdbcDatabase* 
database,
   struct SqliteDatabase* db = (struct SqliteDatabase*)database->private_data;
 
   if (db->db) {
-    SetError(error, "AdbcDatabaseInit: database already initialized");
+    SetError(error, "[SQLite] AdbcDatabaseInit: database already initialized");
     return ADBC_STATUS_INVALID_STATE;
   }
 
@@ -141,7 +142,7 @@ AdbcStatusCode SqliteDatabaseRelease(struct AdbcDatabase* 
database,
   if (db->uri) free(db->uri);
   if (db->db) {
     if (sqlite3_close(db->db) == SQLITE_BUSY) {
-      SetError(error, "AdbcDatabaseRelease: connection is busy");
+      SetError(error, "[SQLite] AdbcDatabaseRelease: connection is busy");
       return ADBC_STATUS_IO;
     }
   }
@@ -150,7 +151,7 @@ AdbcStatusCode SqliteDatabaseRelease(struct AdbcDatabase* 
database,
 
   if (connection_count > 0) {
     // -Wpedantic gives a warning if we use size_t in a printf() context
-    SetError(error, "AdbcDatabaseRelease: %ld open connections when released",
+    SetError(error, "[SQLite] AdbcDatabaseRelease: %ld open connections when 
released",
              (long)connection_count);  // NOLINT(runtime/int)
     return ADBC_STATUS_INVALID_STATE;
   }
@@ -160,7 +161,7 @@ AdbcStatusCode SqliteDatabaseRelease(struct AdbcDatabase* 
database,
 AdbcStatusCode SqliteConnectionNew(struct AdbcConnection* connection,
                                    struct AdbcError* error) {
   if (connection->private_data) {
-    SetError(error, "AdbcConnectionNew: connection already allocated");
+    SetError(error, "[SQLite] AdbcConnectionNew: connection already 
allocated");
     return ADBC_STATUS_INVALID_STATE;
   }
 
@@ -193,12 +194,13 @@ AdbcStatusCode SqliteConnectionSetOption(struct 
AdbcConnection* connection,
         conn->active_transaction = 1;
       }
     } else {
-      SetError(error, "Invalid connection option value %s=%s", key, value);
+      SetError(error, "[SQLite] Invalid connection option value %s=%s", key, 
value);
       return ADBC_STATUS_INVALID_ARGUMENT;
     }
     return ADBC_STATUS_OK;
   }
-  SetError(error, "Unknown connection option %s=%s", key, value ? value : 
"(NULL)");
+  SetError(error, "[SQLite] Unknown connection option %s=%s", key,
+           value ? value : "(NULL)");
   return ADBC_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -211,7 +213,7 @@ AdbcStatusCode SqliteConnectionInit(struct AdbcConnection* 
connection,
   struct SqliteDatabase* db = (struct SqliteDatabase*)database->private_data;
 
   if (conn->conn) {
-    SetError(error, "AdbcConnectionInit: connection already initialized");
+    SetError(error, "[SQLite] AdbcConnectionInit: connection already 
initialized");
     return ADBC_STATUS_INVALID_STATE;
   }
   return OpenDatabase(db->uri, &conn->conn, error);
@@ -225,7 +227,7 @@ AdbcStatusCode SqliteConnectionRelease(struct 
AdbcConnection* connection,
   if (conn->conn) {
     int rc = sqlite3_close(conn->conn);
     if (rc == SQLITE_BUSY) {
-      SetError(error, "AdbcConnectionRelease: connection is busy");
+      SetError(error, "[SQLite] AdbcConnectionRelease: connection is busy");
       return ADBC_STATUS_IO;
     }
   }
@@ -859,7 +861,8 @@ AdbcStatusCode SqliteConnectionGetTablesInner(
   }
 
   if (rc != SQLITE_DONE) {
-    SetError(error, "Failed to query for tables: %s", 
sqlite3_errmsg(conn->conn));
+    SetError(error, "[SQLite] Failed to query for tables: %s",
+             sqlite3_errmsg(conn->conn));
     return ADBC_STATUS_INTERNAL;
   }
   CHECK_NA(INTERNAL, ArrowArrayFinishElement(db_schema_tables_col), error);
@@ -909,7 +912,8 @@ AdbcStatusCode SqliteConnectionGetTablesImpl(struct 
SqliteConnection* conn, int
                                             fk_stmt, table_type, column_name,
                                             db_schema_tables_col, error);
   } else {
-    SetError(error, "Failed to query for tables: %s", 
sqlite3_errmsg(conn->conn));
+    SetError(error, "[SQLite] Failed to query for tables: %s",
+             sqlite3_errmsg(conn->conn));
     status = ADBC_STATUS_INTERNAL;
   }
 
@@ -1017,19 +1021,19 @@ AdbcStatusCode SqliteConnectionGetTableSchema(struct 
AdbcConnection* connection,
     memset(schema, 0, sizeof(*schema));
     return ADBC_STATUS_OK;
   } else if (table_name == NULL) {
-    SetError(error, "AdbcConnectionGetTableSchema: must provide table_name");
+    SetError(error, "[SQLite] AdbcConnectionGetTableSchema: must provide 
table_name");
     return ADBC_STATUS_INVALID_ARGUMENT;
   }
 
   struct StringBuilder query = {0};
   if (StringBuilderInit(&query, /*initial_size=*/64) != 0) {
-    SetError(error, "Could not initiate StringBuilder");
+    SetError(error, "[SQLite] Could not initiate StringBuilder");
     return ADBC_STATUS_INTERNAL;
   }
 
   if (StringBuilderAppend(&query, "%s%s", "SELECT * FROM ", table_name) != 0) {
     StringBuilderReset(&query);
-    SetError(error, "Call to StringBuilderAppend failed");
+    SetError(error, "[SQLite] Call to StringBuilderAppend failed");
     return ADBC_STATUS_INTERNAL;
   }
 
@@ -1038,7 +1042,7 @@ AdbcStatusCode SqliteConnectionGetTableSchema(struct 
AdbcConnection* connection,
       sqlite3_prepare_v2(conn->conn, query.buffer, query.size, &stmt, 
/*pzTail=*/NULL);
   StringBuilderReset(&query);
   if (rc != SQLITE_OK) {
-    SetError(error, "Failed to prepare query: %s", sqlite3_errmsg(conn->conn));
+    SetError(error, "[SQLite] Failed to prepare query: %s", 
sqlite3_errmsg(conn->conn));
     return ADBC_STATUS_INTERNAL;
   }
 
@@ -1048,7 +1052,7 @@ AdbcStatusCode SqliteConnectionGetTableSchema(struct 
AdbcConnection* connection,
   if (status == ADBC_STATUS_OK) {
     int code = stream.get_schema(&stream, schema);
     if (code != 0) {
-      SetError(error, "Failed to get schema: (%d) %s", code, strerror(code));
+      SetError(error, "[SQLite] Failed to get schema: (%d) %s", code, 
strerror(code));
       status = ADBC_STATUS_IO;
     }
   }
@@ -1116,7 +1120,7 @@ AdbcStatusCode SqliteConnectionCommit(struct 
AdbcConnection* connection,
   CHECK_CONN_INIT(connection, error);
   struct SqliteConnection* conn = (struct 
SqliteConnection*)connection->private_data;
   if (!conn->active_transaction) {
-    SetError(error, "No active transaction, cannot commit");
+    SetError(error, "[SQLite] No active transaction, cannot commit");
     return ADBC_STATUS_INVALID_STATE;
   }
 
@@ -1130,7 +1134,7 @@ AdbcStatusCode SqliteConnectionRollback(struct 
AdbcConnection* connection,
   CHECK_CONN_INIT(connection, error);
   struct SqliteConnection* conn = (struct 
SqliteConnection*)connection->private_data;
   if (!conn->active_transaction) {
-    SetError(error, "No active transaction, cannot rollback");
+    SetError(error, "[SQLite] No active transaction, cannot rollback");
     return ADBC_STATUS_INVALID_STATE;
   }
 
@@ -1145,10 +1149,10 @@ AdbcStatusCode SqliteStatementNew(struct 
AdbcConnection* connection,
   CHECK_CONN_INIT(connection, error);
   struct SqliteConnection* conn = (struct 
SqliteConnection*)connection->private_data;
   if (statement->private_data) {
-    SetError(error, "AdbcStatementNew: statement already allocated");
+    SetError(error, "[SQLite] AdbcStatementNew: statement already allocated");
     return ADBC_STATUS_INVALID_STATE;
   } else if (!conn->conn) {
-    SetError(error, "AdbcStatementNew: connection is not initialized");
+    SetError(error, "[SQLite] AdbcStatementNew: connection is not 
initialized");
     return ADBC_STATUS_INVALID_STATE;
   }
 
@@ -1176,7 +1180,8 @@ AdbcStatusCode SqliteStatementRelease(struct 
AdbcStatement* statement,
   AdbcSqliteBinderRelease(&stmt->binder);
   if (stmt->target_table) free(stmt->target_table);
   if (rc != SQLITE_OK) {
-    SetError(error, "AdbcStatementRelease: statement failed to finalize: (%d) 
%s", rc,
+    SetError(error,
+             "[SQLite] AdbcStatementRelease: statement failed to finalize: 
(%d) %s", rc,
              sqlite3_errmsg(stmt->conn));
   }
   free(statement->private_data);
@@ -1191,7 +1196,7 @@ AdbcStatusCode SqliteStatementPrepare(struct 
AdbcStatement* statement,
   struct SqliteStatement* stmt = (struct 
SqliteStatement*)statement->private_data;
 
   if (!stmt->query) {
-    SetError(error, "Must SetSqlQuery before ExecuteQuery or Prepare");
+    SetError(error, "[SQLite] Must SetSqlQuery before ExecuteQuery or 
Prepare");
     return ADBC_STATUS_INVALID_STATE;
   }
   if (stmt->prepared == 0) {
@@ -1199,7 +1204,7 @@ AdbcStatusCode SqliteStatementPrepare(struct 
AdbcStatement* statement,
       int rc = sqlite3_finalize(stmt->stmt);
       stmt->stmt = NULL;
       if (rc != SQLITE_OK) {
-        SetError(error, "Failed to finalize previous statement: (%d) %s", rc,
+        SetError(error, "[SQLite] Failed to finalize previous statement: (%d) 
%s", rc,
                  sqlite3_errmsg(stmt->conn));
         return ADBC_STATUS_IO;
       }
@@ -1209,8 +1214,8 @@ AdbcStatusCode SqliteStatementPrepare(struct 
AdbcStatement* statement,
         sqlite3_prepare_v2(stmt->conn, stmt->query, (int)stmt->query_len, 
&stmt->stmt,
                            /*pzTail=*/NULL);
     if (rc != SQLITE_OK) {
-      SetError(error, "Failed to prepare query: %s\nQuery:%s", 
sqlite3_errmsg(stmt->conn),
-               stmt->query);
+      SetError(error, "[SQLite] Failed to prepare query: %s\nQuery:%s",
+               sqlite3_errmsg(stmt->conn), stmt->query);
       (void)sqlite3_finalize(stmt->stmt);
       stmt->stmt = NULL;
       return ADBC_STATUS_INVALID_ARGUMENT;
@@ -1231,26 +1236,26 @@ AdbcStatusCode SqliteStatementInitIngest(struct 
SqliteStatement* stmt,
   struct StringBuilder insert_query = {0};
 
   if (StringBuilderInit(&create_query, /*initial_size=*/256) != 0) {
-    SetError(error, "Could not initiate StringBuilder");
+    SetError(error, "[SQLite] Could not initiate StringBuilder");
     return ADBC_STATUS_INTERNAL;
   }
 
   if (StringBuilderInit(&insert_query, /*initial_size=*/256) != 0) {
-    SetError(error, "Could not initiate StringBuilder");
+    SetError(error, "[SQLite] Could not initiate StringBuilder");
     StringBuilderReset(&create_query);
     return ADBC_STATUS_INTERNAL;
   }
 
   if (StringBuilderAppend(&create_query, "%s%s%s", "CREATE TABLE ", 
stmt->target_table,
                           " (") != 0) {
-    SetError(error, "Call to StringBuilderAppend failed");
+    SetError(error, "[SQLite] Call to StringBuilderAppend failed");
     code = ADBC_STATUS_INTERNAL;
     goto cleanup;
   }
 
   if (StringBuilderAppend(&insert_query, "%s%s%s", "INSERT INTO ", 
stmt->target_table,
                           " VALUES (") != 0) {
-    SetError(error, "Call to StringBuilderAppend failed");
+    SetError(error, "[SQLite] Call to StringBuilderAppend failed");
     code = ADBC_STATUS_INTERNAL;
     goto cleanup;
   }
@@ -1260,33 +1265,33 @@ AdbcStatusCode SqliteStatementInitIngest(struct 
SqliteStatement* stmt,
     // XXX: should escape the column name too
     if (StringBuilderAppend(&create_query, "%s", 
stmt->binder.schema.children[i]->name) !=
         0) {
-      SetError(error, "Call to StringBuilderAppend failed");
+      SetError(error, "[SQLite] Call to StringBuilderAppend failed");
       code = ADBC_STATUS_INTERNAL;
       goto cleanup;
     }
 
     if (i > 0) {
       if (StringBuilderAppend(&insert_query, "%s", ", ") != 0) {
-        SetError(error, "Call to StringBuilderAppend failed");
+        SetError(error, "[SQLite] Call to StringBuilderAppend failed");
         code = ADBC_STATUS_INTERNAL;
         goto cleanup;
       }
     }
 
     if (StringBuilderAppend(&insert_query, "%s", "?") != 0) {
-      SetError(error, "Call to StringBuilderAppend failed");
+      SetError(error, "[SQLite] Call to StringBuilderAppend failed");
       code = ADBC_STATUS_INTERNAL;
       goto cleanup;
     }
   }
   if (StringBuilderAppend(&create_query, "%s", ")") != 0) {
-    SetError(error, "Call to StringBuilderAppend failed");
+    SetError(error, "[SQLite] Call to StringBuilderAppend failed");
     code = ADBC_STATUS_INTERNAL;
     goto cleanup;
   }
 
   if (StringBuilderAppend(&insert_query, "%s", ")") != 0) {
-    SetError(error, "Call to StringBuilderAppend failed");
+    SetError(error, "[SQLite] Call to StringBuilderAppend failed");
     code = ADBC_STATUS_INTERNAL;
     goto cleanup;
   }
@@ -1301,7 +1306,7 @@ AdbcStatusCode SqliteStatementInitIngest(struct 
SqliteStatement* stmt,
     }
 
     if (rc != SQLITE_OK && rc != SQLITE_DONE) {
-      SetError(error, "Failed to create table: %s (executed '%s')",
+      SetError(error, "[SQLite] Failed to create table: %s (executed '%s')",
                sqlite3_errmsg(stmt->conn), create_query.buffer);
       code = ADBC_STATUS_INTERNAL;
     }
@@ -1311,7 +1316,7 @@ AdbcStatusCode SqliteStatementInitIngest(struct 
SqliteStatement* stmt,
     int rc = sqlite3_prepare_v2(stmt->conn, insert_query.buffer, 
(int)insert_query.size,
                                 insert_statement, /*pzTail=*/NULL);
     if (rc != SQLITE_OK) {
-      SetError(error, "Failed to prepare statement: %s (executed '%s')",
+      SetError(error, "[SQLite] Failed to prepare statement: %s (executed 
'%s')",
                sqlite3_errmsg(stmt->conn), insert_query.buffer);
       code = ADBC_STATUS_INTERNAL;
     }
@@ -1329,7 +1334,7 @@ AdbcStatusCode SqliteStatementExecuteIngest(struct 
SqliteStatement* stmt,
                                             int64_t* rows_affected,
                                             struct AdbcError* error) {
   if (!stmt->binder.schema.release) {
-    SetError(error, "Must Bind() before bulk ingestion");
+    SetError(error, "[SQLite] Must Bind() before bulk ingestion");
     return ADBC_STATUS_INVALID_STATE;
   }
 
@@ -1349,7 +1354,8 @@ AdbcStatusCode SqliteStatementExecuteIngest(struct 
SqliteStatement* stmt,
         rc = sqlite3_step(insert);
       } while (rc == SQLITE_ROW);
       if (rc != SQLITE_DONE) {
-        SetError(error, "Failed to execute statement: %s", 
sqlite3_errmsg(stmt->conn));
+        SetError(error, "[SQLite] Failed to execute statement: %s",
+                 sqlite3_errmsg(stmt->conn));
         status = ADBC_STATUS_INTERNAL;
         break;
       }
@@ -1381,7 +1387,9 @@ AdbcStatusCode SqliteStatementExecuteQuery(struct 
AdbcStatement* statement,
     int64_t expected = sqlite3_bind_parameter_count(stmt->stmt);
     int64_t actual = stmt->binder.schema.n_children;
     if (actual != expected) {
-      SetError(error, "Parameter count mismatch: expected %" PRId64 " but 
found %" PRId64,
+      SetError(error,
+               "[SQLite] Parameter count mismatch: expected %" PRId64
+               " but found %" PRId64,
                expected, actual);
       return ADBC_STATUS_INVALID_STATE;
     }
@@ -1413,7 +1421,7 @@ AdbcStatusCode SqliteStatementExecuteQuery(struct 
AdbcStatement* statement,
     if (sqlite3_reset(stmt->stmt) != SQLITE_OK) {
       status = ADBC_STATUS_IO;
       const char* msg = sqlite3_errmsg(stmt->conn);
-      SetError(error, "Failed to execute query: %s",
+      SetError(error, "[SQLite] Failed to execute query: %s",
                (msg == NULL) ? "(unknown error)" : msg);
     }
 
@@ -1456,7 +1464,7 @@ AdbcStatusCode SqliteStatementSetSubstraitPlan(struct 
AdbcStatement* statement,
                                                const uint8_t* plan, size_t 
length,
                                                struct AdbcError* error) {
   CHECK_STMT_INIT(statement, error);
-  SetError(error, "Substrait is not supported");
+  SetError(error, "[SQLite] Substrait is not supported");
   return ADBC_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -1486,7 +1494,7 @@ AdbcStatusCode SqliteStatementGetParameterSchema(struct 
AdbcStatement* statement
   int num_params = sqlite3_bind_parameter_count(stmt->stmt);
   if (num_params < 0) {
     // Should not happen
-    SetError(error, "SQLite returned negative parameter count");
+    SetError(error, "[SQLite] SQLite returned negative parameter count");
     return ADBC_STATUS_INTERNAL;
   }
 
@@ -1533,7 +1541,7 @@ AdbcStatusCode SqliteStatementSetOption(struct 
AdbcStatement* statement, const c
     } else if (strcmp(value, ADBC_INGEST_OPTION_MODE_CREATE) == 0) {
       stmt->append = 0;
     } else {
-      SetError(error, "Invalid statement option value %s=%s", key, value);
+      SetError(error, "[SQLite] Invalid statement option value %s=%s", key, 
value);
       return ADBC_STATUS_INVALID_ARGUMENT;
     }
     return ADBC_STATUS_OK;
@@ -1541,23 +1549,27 @@ AdbcStatusCode SqliteStatementSetOption(struct 
AdbcStatement* statement, const c
     char* end = NULL;
     long batch_size = strtol(value, &end, /*base=*/10);  // NOLINT(runtime/int)
     if (errno != 0) {
-      SetError(error, "Invalid statement option value %s=%s (out of range)", 
key, value);
+      SetError(error, "[SQLite] Invalid statement option value %s=%s (out of 
range)", key,
+               value);
       return ADBC_STATUS_INVALID_ARGUMENT;
     } else if (batch_size <= 0) {
       SetError(error,
-               "Invalid statement option value %s=%s (value is non-positive or 
invalid)",
+               "[SQLite] Invalid statement option value %s=%s (value is 
non-positive or "
+               "invalid)",
                key, value);
       return ADBC_STATUS_INVALID_ARGUMENT;
     } else if (batch_size > (long)INT_MAX) {  // NOLINT(runtime/int)
-      SetError(error,
-               "Invalid statement option value %s=%s (value is out of range of 
int)", key,
-               value);
+      SetError(
+          error,
+          "[SQLite] Invalid statement option value %s=%s (value is out of 
range of int)",
+          key, value);
       return ADBC_STATUS_INVALID_ARGUMENT;
     }
     stmt->batch_size = (int)batch_size;
     return ADBC_STATUS_OK;
   }
-  SetError(error, "Unknown statement option %s=%s", key, value ? value : 
"(NULL)");
+  SetError(error, "[SQLite] Unknown statement option %s=%s", key,
+           value ? value : "(NULL)");
   return ADBC_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -1567,13 +1579,14 @@ AdbcStatusCode SqliteStatementExecutePartitions(struct 
AdbcStatement* statement,
                                                 int64_t* rows_affected,
                                                 struct AdbcError* error) {
   CHECK_STMT_INIT(statement, error);
-  SetError(error, "Partitioned result sets are not supported");
+  SetError(error, "[SQLite] Partitioned result sets are not supported");
   return ADBC_STATUS_NOT_IMPLEMENTED;
 }  // NOLINT(whitespace/indent)
 
 AdbcStatusCode SqliteDriverInit(int version, void* raw_driver, struct 
AdbcError* error) {
   if (version != ADBC_VERSION_1_0_0) {
-    SetError(error, "Only version %d supported, got %d", ADBC_VERSION_1_0_0, 
version);
+    SetError(error, "[SQLite] Only version %d supported, got %d", 
ADBC_VERSION_1_0_0,
+             version);
     return ADBC_STATUS_NOT_IMPLEMENTED;
   }
 
diff --git a/r/adbcpostgresql/bootstrap.R b/r/adbcpostgresql/bootstrap.R
index b7c84fc5..fcfce076 100644
--- a/r/adbcpostgresql/bootstrap.R
+++ b/r/adbcpostgresql/bootstrap.R
@@ -19,7 +19,7 @@
 # into src/
 files_to_vendor <- c(
   "../../adbc.h",
-  "../../c/driver/postgresql/util.h",
+  "../../c/driver/postgresql/postgres_util.h",
   "../../c/driver/postgresql/postgres_type.h",
   "../../c/driver/postgresql/statement.h",
   "../../c/driver/postgresql/statement.cc",
@@ -28,6 +28,8 @@ files_to_vendor <- c(
   "../../c/driver/postgresql/database.h",
   "../../c/driver/postgresql/database.cc",
   "../../c/driver/postgresql/postgresql.cc",
+  "../../c/driver/common/utils.h",
+  "../../c/driver/common/utils.c",
   "../../c/vendor/nanoarrow/nanoarrow.h",
   "../../c/vendor/nanoarrow/nanoarrow.hpp",
   "../../c/vendor/nanoarrow/nanoarrow.c"
diff --git a/r/adbcpostgresql/src/Makevars.in b/r/adbcpostgresql/src/Makevars.in
index c062d117..cba36c46 100644
--- a/r/adbcpostgresql/src/Makevars.in
+++ b/r/adbcpostgresql/src/Makevars.in
@@ -22,5 +22,6 @@ OBJECTS = init.o \
     connection.o \
     database.o \
     statement.o \
+    utils.o \
     postgresql.o \
     nanoarrow/nanoarrow.o
diff --git a/r/adbcpostgresql/src/Makevars.ucrt 
b/r/adbcpostgresql/src/Makevars.ucrt
index 0fc2d0c0..5194f14a 100644
--- a/r/adbcpostgresql/src/Makevars.ucrt
+++ b/r/adbcpostgresql/src/Makevars.ucrt
@@ -22,5 +22,6 @@ OBJECTS = init.o \
     connection.o \
     database.o \
     statement.o \
+    utils.o \
     postgresql.o \
     nanoarrow/nanoarrow.o
diff --git a/r/adbcpostgresql/src/Makevars.win 
b/r/adbcpostgresql/src/Makevars.win
index a45dc513..59068c8f 100644
--- a/r/adbcpostgresql/src/Makevars.win
+++ b/r/adbcpostgresql/src/Makevars.win
@@ -25,6 +25,7 @@ OBJECTS = init.o \
     connection.o \
     database.o \
     statement.o \
+    utils.o \
     postgresql.o \
     nanoarrow/nanoarrow.o
 

Reply via email to