Current section

Files

Jump to
adbc 3rd_party apache-arrow-adbc c driver common driver_base.h
Raw

3rd_party/apache-arrow-adbc/c/driver/common/driver_base.h

// 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.
#include <cstring>
#include <memory>
#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <adbc.h>
// This file defines a developer-friendly way to create an ADBC driver, currently intended
// for testing the R driver manager. It handles errors, option getting/setting, and
// managing the export of the many C callables that compose an AdbcDriver. In general,
// functions or methods intended to be called from C are prefixed with "C" and are private
// (i.e., the public and protected methods are the only ones that driver authors should
// ever interact with).
//
// Example:
// class MyDatabase: public DatabaseObjectBase {};
// class MyConnection: public ConnectionObjectBase {};
// class MyStatement: public StatementObjectbase {};
// AdbcStatusCode VoidDriverInitFunc(int version, void* raw_driver, AdbcError* error) {
// return Driver<MyDatabase, MyConnection, MyStatement>::Init(
// version, raw_driver, error);
// }
namespace adbc {
namespace common {
class Error {
public:
explicit Error(std::string message) : message_(std::move(message)) {
std::memset(sql_state_, 0, sizeof(sql_state_));
}
explicit Error(const char* message) : Error(std::string(message)) {}
Error(std::string message, std::vector<std::pair<std::string, std::string>> details)
: message_(std::move(message)), details_(std::move(details)) {
std::memset(sql_state_, 0, sizeof(sql_state_));
}
void AddDetail(std::string key, std::string value) {
details_.push_back({std::move(key), std::move(value)});
}
void ToAdbc(AdbcError* adbc_error, AdbcDriver* driver = nullptr) {
if (adbc_error == nullptr) {
return;
}
if (adbc_error->vendor_code == ADBC_ERROR_VENDOR_CODE_PRIVATE_DATA) {
auto error_owned_by_adbc_error =
new Error(std::move(message_), std::move(details_));
adbc_error->message =
const_cast<char*>(error_owned_by_adbc_error->message_.c_str());
adbc_error->private_data = error_owned_by_adbc_error;
adbc_error->private_driver = driver;
} else {
adbc_error->message = reinterpret_cast<char*>(std::malloc(message_.size() + 1));
if (adbc_error->message != nullptr) {
std::memcpy(adbc_error->message, message_.c_str(), message_.size() + 1);
}
}
std::memcpy(adbc_error->sqlstate, sql_state_, sizeof(sql_state_));
adbc_error->release = &CRelease;
}
private:
std::string message_;
std::vector<std::pair<std::string, std::string>> details_;
char sql_state_[5];
// Let the Driver use these to expose C callables wrapping option setters/getters
template <typename DatabaseT, typename ConnectionT, typename StatementT>
friend class Driver;
int CDetailCount() const { return details_.size(); }
AdbcErrorDetail CDetail(int index) const {
const auto& detail = details_[index];
return {detail.first.c_str(), reinterpret_cast<const uint8_t*>(detail.second.data()),
detail.second.size() + 1};
}
static void CRelease(AdbcError* error) {
if (error->vendor_code == ADBC_ERROR_VENDOR_CODE_PRIVATE_DATA) {
auto error_obj = reinterpret_cast<Error*>(error->private_data);
delete error_obj;
} else {
std::free(error->message);
}
std::memset(error, 0, sizeof(AdbcError));
}
};
// Variant that handles the option types that can be get/set by databases,
// connections, and statements. It currently does not attempt conversion
// (i.e., getting a double option as a string).
class Option {
public:
enum Type { TYPE_MISSING, TYPE_STRING, TYPE_BYTES, TYPE_INT, TYPE_DOUBLE };
Option() : type_(TYPE_MISSING) {}
explicit Option(const std::string& value) : type_(TYPE_STRING), value_string_(value) {}
explicit Option(const std::vector<uint8_t>& value)
: type_(TYPE_BYTES), value_bytes_(value) {}
explicit Option(double value) : type_(TYPE_DOUBLE), value_double_(value) {}
explicit Option(int64_t value) : type_(TYPE_INT), value_int_(value) {}
Type type() const { return type_; }
const std::string& GetStringUnsafe() const { return value_string_; }
const std::vector<uint8_t>& GetBytesUnsafe() const { return value_bytes_; }
int64_t GetIntUnsafe() const { return value_int_; }
double GetDoubleUnsafe() const { return value_double_; }
private:
Type type_;
std::string value_string_;
std::vector<uint8_t> value_bytes_;
double value_double_;
int64_t value_int_;
// Methods used by trampolines to export option values in C below
friend class ObjectBase;
AdbcStatusCode CGet(char* out, size_t* length) const {
switch (type_) {
case TYPE_STRING: {
const std::string& value = GetStringUnsafe();
size_t value_size_with_terminator = value.size() + 1;
if (*length < value_size_with_terminator) {
*length = value_size_with_terminator;
} else {
memcpy(out, value.data(), value_size_with_terminator);
}
return ADBC_STATUS_OK;
}
default:
return ADBC_STATUS_NOT_FOUND;
}
}
AdbcStatusCode CGet(uint8_t* out, size_t* length) const {
switch (type_) {
case TYPE_BYTES: {
const std::vector<uint8_t>& value = GetBytesUnsafe();
if (*length < value.size()) {
*length = value.size();
} else {
memcpy(out, value.data(), value.size());
}
return ADBC_STATUS_OK;
}
default:
return ADBC_STATUS_NOT_FOUND;
}
}
AdbcStatusCode CGet(int64_t* value) const {
switch (type_) {
case TYPE_INT:
*value = GetIntUnsafe();
return ADBC_STATUS_OK;
default:
return ADBC_STATUS_NOT_FOUND;
}
}
AdbcStatusCode CGet(double* value) const {
switch (type_) {
case TYPE_DOUBLE:
*value = GetDoubleUnsafe();
return ADBC_STATUS_OK;
default:
return ADBC_STATUS_NOT_FOUND;
}
}
};
// Base class for private_data of AdbcDatabase, AdbcConnection, and AdbcStatement
// This class handles option setting and getting.
class ObjectBase {
public:
ObjectBase() : driver_(nullptr) {}
virtual ~ObjectBase() {}
// Driver authors can override this method to reject options that are not supported or
// that are set at a time not supported by the driver (e.g., to reject options that are
// set after Init() is called if this is not supported).
virtual AdbcStatusCode SetOption(const std::string& key, const Option& value) {
options_[key] = value;
return ADBC_STATUS_OK;
}
// Called After zero or more SetOption() calls. The parent is the private_data of
// the AdbcDriver, AdbcDatabase, or AdbcConnection when initializing a subclass of
// DatabaseObjectBase, ConnectionObjectBase, and StatementObjectBase (respectively).
// For example, if you have defined Driver<MyDatabase, MyConnection, MyStatement>,
// you can reinterpret_cast<MyDatabase>(parent) in MyConnection::Init().
virtual AdbcStatusCode Init(void* parent, AdbcError* error) { return ADBC_STATUS_OK; }
// Called when the corresponding AdbcXXXRelease() function is invoked from C.
// Driver authors can override this method to return an error if the object is
// not in a valid state (e.g., if a connection has open statements) or to clean
// up resources when resource cleanup could fail. Resource cleanup that cannot fail
// (e.g., releasing memory) should generally be handled in the deleter.
virtual AdbcStatusCode Release(AdbcError* error) { return ADBC_STATUS_OK; }
// Get an option that was previously set, providing an optional default value.
virtual const Option& GetOption(const std::string& key,
const Option& default_value = Option()) const {
auto result = options_.find(key);
if (result == options_.end()) {
return default_value;
} else {
return result->second;
}
}
protected:
// Needed to export errors using Error::ToAdbc() that use 1.1.0 extensions
// (i.e., error details). This will be nullptr before Init() is called.
AdbcDriver* driver() const { return driver_; }
private:
AdbcDriver* driver_;
std::unordered_map<std::string, Option> options_;
// Let the Driver use these to expose C callables wrapping option setters/getters
template <typename DatabaseT, typename ConnectionT, typename StatementT>
friend class Driver;
// The AdbcDriver* struct is set right before Init() is called by the Driver
// trampoline.
void set_driver(AdbcDriver* driver) { driver_ = driver; }
template <typename T>
AdbcStatusCode CSetOption(const char* key, T value, AdbcError* error) {
Option option(value);
return SetOption(key, option);
}
AdbcStatusCode CSetOptionBytes(const char* key, const uint8_t* value, size_t length,
AdbcError* error) {
std::vector<uint8_t> cppvalue(value, value + length);
Option option(cppvalue);
return SetOption(key, option);
}
template <typename T>
AdbcStatusCode CGetOptionStringLike(const char* key, T* value, size_t* length,
AdbcError* error) const {
Option result = GetOption(key);
if (result.type() == Option::TYPE_MISSING) {
InitErrorNotFound(key, error);
return ADBC_STATUS_NOT_FOUND;
} else {
AdbcStatusCode status = result.CGet(value, length);
if (status != ADBC_STATUS_OK) {
InitErrorWrongType(key, error);
}
return status;
}
}
template <typename T>
AdbcStatusCode CGetOptionNumeric(const char* key, T* value, AdbcError* error) const {
Option result = GetOption(key);
if (result.type() == Option::TYPE_MISSING) {
InitErrorNotFound(key, error);
return ADBC_STATUS_NOT_FOUND;
} else {
AdbcStatusCode status = result.CGet(value);
if (status != ADBC_STATUS_OK) {
InitErrorWrongType(key, error);
}
return status;
}
}
void InitErrorNotFound(const char* key, AdbcError* error) const {
std::stringstream msg_builder;
msg_builder << "Option not found for key '" << key << "'";
Error cpperror(msg_builder.str());
cpperror.AddDetail("adbc.driver_base.option_key", key);
cpperror.ToAdbc(error, driver());
}
void InitErrorWrongType(const char* key, AdbcError* error) const {
std::stringstream msg_builder;
msg_builder << "Wrong type requested for option key '" << key << "'";
Error cpperror(msg_builder.str());
cpperror.AddDetail("adbc.driver_base.option_key", key);
cpperror.ToAdbc(error, driver());
}
};
// Driver authors can subclass DatabaseObjectBase to track driver-specific
// state pertaining to the AdbcDatbase. The private_data member of an
// AdbcDatabase initialized by the driver will be a pointer to the
// subclass of DatbaseObjectBase.
class DatabaseObjectBase : public ObjectBase {
public:
// (there are no database functions other than option getting/setting)
};
// Driver authors can subclass ConnectionObjectBase to track driver-specific
// state pertaining to the AdbcConnection. The private_data member of an
// AdbcConnection initialized by the driver will be a pointer to the
// subclass of ConnectionObjectBase. Driver authors can override methods to
// implement the corresponding ConnectionXXX driver methods.
class ConnectionObjectBase : public ObjectBase {
public:
virtual AdbcStatusCode Commit(AdbcError* error) { return ADBC_STATUS_NOT_IMPLEMENTED; }
virtual AdbcStatusCode GetInfo(const uint32_t* info_codes, size_t info_codes_length,
ArrowArrayStream* out, AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode GetObjects(int depth, const char* catalog, const char* db_schema,
const char* table_name, const char** table_type,
const char* column_name, ArrowArrayStream* out,
AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode GetTableSchema(const char* catalog, const char* db_schema,
const char* table_name, ArrowSchema* schema,
AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode GetTableTypes(ArrowArrayStream* out, AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode ReadPartition(const uint8_t* serialized_partition,
size_t serialized_length, ArrowArrayStream* out,
AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode Rollback(AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode Cancel(AdbcError* error) { return ADBC_STATUS_NOT_IMPLEMENTED; }
virtual AdbcStatusCode GetStatistics(const char* catalog, const char* db_schema,
const char* table_name, char approximate,
ArrowArrayStream* out, AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode GetStatisticNames(ArrowArrayStream* out, AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
};
// Driver authors can subclass StatementObjectBase to track driver-specific
// state pertaining to the AdbcStatement. The private_data member of an
// AdbcStatement initialized by the driver will be a pointer to the
// subclass of StatementObjectBase. Driver authors can override methods to
// implement the corresponding StatementXXX driver methods.
class StatementObjectBase : public ObjectBase {
public:
virtual AdbcStatusCode ExecuteQuery(ArrowArrayStream* stream, int64_t* rows_affected,
AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode ExecuteSchema(ArrowSchema* schema, AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode Prepare(AdbcError* error) { return ADBC_STATUS_NOT_IMPLEMENTED; }
virtual AdbcStatusCode SetSqlQuery(const char* query, AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode SetSubstraitPlan(const uint8_t* plan, size_t length,
AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode Bind(ArrowArray* values, ArrowSchema* schema, AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode BindStream(ArrowArrayStream* stream, AdbcError* error) {
return ADBC_STATUS_NOT_IMPLEMENTED;
}
virtual AdbcStatusCode Cancel(AdbcError* error) { return ADBC_STATUS_NOT_IMPLEMENTED; }
};
// Driver authors can declare a template specialization of the Driver class
// and use it to provide their driver init function. It is possible, but
// rarely useful, to subclass a driver.
template <typename DatabaseT, typename ConnectionT, typename StatementT>
class Driver {
public:
static AdbcStatusCode Init(int version, void* raw_driver, AdbcError* error) {
if (version != ADBC_VERSION_1_1_0) return ADBC_STATUS_NOT_IMPLEMENTED;
AdbcDriver* driver = (AdbcDriver*)raw_driver;
std::memset(driver, 0, sizeof(AdbcDriver));
// Driver lifecycle
driver->private_data = new Driver();
driver->release = &CDriverRelease;
// Driver functions
driver->ErrorGetDetailCount = &CErrorGetDetailCount;
driver->ErrorGetDetail = &CErrorGetDetail;
// Database lifecycle
driver->DatabaseNew = &CNew<AdbcDatabase, DatabaseT>;
driver->DatabaseInit = &CDatabaseInit;
driver->DatabaseRelease = &CRelease<AdbcDatabase, DatabaseT>;
// Database functions
driver->DatabaseSetOption = &CSetOption<AdbcDatabase, DatabaseT>;
driver->DatabaseSetOptionBytes = &CSetOptionBytes<AdbcDatabase, DatabaseT>;
driver->DatabaseSetOptionInt = &CSetOptionInt<AdbcDatabase, DatabaseT>;
driver->DatabaseSetOptionDouble = &CSetOptionDouble<AdbcDatabase, DatabaseT>;
driver->DatabaseGetOption = &CGetOption<AdbcDatabase, DatabaseT>;
driver->DatabaseGetOptionBytes = &CGetOptionBytes<AdbcDatabase, DatabaseT>;
driver->DatabaseGetOptionInt = &CGetOptionInt<AdbcDatabase, DatabaseT>;
driver->DatabaseGetOptionDouble = &CGetOptionDouble<AdbcDatabase, DatabaseT>;
// Connection lifecycle
driver->ConnectionNew = &CNew<AdbcConnection, ConnectionT>;
driver->ConnectionInit = &CConnectionInit;
driver->ConnectionRelease = &CRelease<AdbcConnection, ConnectionT>;
// Connection functions
driver->ConnectionSetOption = &CSetOption<AdbcConnection, ConnectionT>;
driver->ConnectionSetOptionBytes = &CSetOptionBytes<AdbcConnection, ConnectionT>;
driver->ConnectionSetOptionInt = &CSetOptionInt<AdbcConnection, ConnectionT>;
driver->ConnectionSetOptionDouble = &CSetOptionDouble<AdbcConnection, ConnectionT>;
driver->ConnectionGetOption = &CGetOption<AdbcConnection, ConnectionT>;
driver->ConnectionGetOptionBytes = &CGetOptionBytes<AdbcConnection, ConnectionT>;
driver->ConnectionGetOptionInt = &CGetOptionInt<AdbcConnection, ConnectionT>;
driver->ConnectionGetOptionDouble = &CGetOptionDouble<AdbcConnection, ConnectionT>;
driver->ConnectionCommit = &CConnectionCommit;
driver->ConnectionGetInfo = &CConnectionGetInfo;
driver->ConnectionGetObjects = &CConnectionGetObjects;
driver->ConnectionGetTableSchema = &CConnectionGetTableSchema;
driver->ConnectionGetTableTypes = &CConnectionGetTableTypes;
driver->ConnectionReadPartition = &CConnectionReadPartition;
driver->ConnectionRollback = &CConnectionRollback;
driver->ConnectionCancel = &CConnectionCancel;
driver->ConnectionGetStatistics = &CConnectionGetStatistics;
driver->ConnectionGetStatisticNames = &CConnectionGetStatisticNames;
// Statement lifecycle
driver->StatementNew = &CStatementNew;
driver->StatementRelease = &CRelease<AdbcStatement, StatementT>;
// Statement functions
driver->StatementSetOption = &CSetOption<AdbcStatement, StatementT>;
driver->StatementSetOptionBytes = &CSetOptionBytes<AdbcStatement, StatementT>;
driver->StatementSetOptionInt = &CSetOptionInt<AdbcStatement, StatementT>;
driver->StatementSetOptionDouble = &CSetOptionDouble<AdbcStatement, StatementT>;
driver->StatementGetOption = &CGetOption<AdbcStatement, StatementT>;
driver->StatementGetOptionBytes = &CGetOptionBytes<AdbcStatement, StatementT>;
driver->StatementGetOptionInt = &CGetOptionInt<AdbcStatement, StatementT>;
driver->StatementGetOptionDouble = &CGetOptionDouble<AdbcStatement, StatementT>;
driver->StatementExecuteQuery = &CStatementExecuteQuery;
driver->StatementExecuteSchema = &CStatementExecuteSchema;
driver->StatementPrepare = &CStatementPrepare;
driver->StatementSetSqlQuery = &CStatementSetSqlQuery;
driver->StatementSetSubstraitPlan = &CStatementSetSubstraitPlan;
driver->StatementBind = &CStatementBind;
driver->StatementBindStream = &CStatementBindStream;
driver->StatementCancel = &CStatementCancel;
return ADBC_STATUS_OK;
}
private:
// Driver trampolines
static AdbcStatusCode CDriverRelease(AdbcDriver* driver, AdbcError* error) {
auto driver_private = reinterpret_cast<Driver*>(driver->private_data);
delete driver_private;
driver->private_data = nullptr;
return ADBC_STATUS_OK;
}
static int CErrorGetDetailCount(const AdbcError* error) {
if (error->vendor_code != ADBC_ERROR_VENDOR_CODE_PRIVATE_DATA) {
return 0;
}
auto error_obj = reinterpret_cast<Error*>(error->private_data);
return error_obj->CDetailCount();
}
static AdbcErrorDetail CErrorGetDetail(const AdbcError* error, int index) {
auto error_obj = reinterpret_cast<Error*>(error->private_data);
return error_obj->CDetail(index);
}
// Templatable trampolines
template <typename T, typename ObjectT>
static AdbcStatusCode CNew(T* obj, AdbcError* error) {
auto private_data = new ObjectT();
obj->private_data = private_data;
return ADBC_STATUS_OK;
}
template <typename T, typename ObjectT>
static AdbcStatusCode CRelease(T* obj, AdbcError* error) {
auto private_data = reinterpret_cast<ObjectT*>(obj->private_data);
AdbcStatusCode result = private_data->Release(error);
if (result != ADBC_STATUS_OK) {
return result;
}
delete private_data;
obj->private_data = nullptr;
return ADBC_STATUS_OK;
}
template <typename T, typename ObjectT>
static AdbcStatusCode CSetOption(T* obj, const char* key, const char* value,
AdbcError* error) {
auto private_data = reinterpret_cast<ObjectT*>(obj->private_data);
return private_data->template CSetOption<>(key, value, error);
}
template <typename T, typename ObjectT>
static AdbcStatusCode CSetOptionBytes(T* obj, const char* key, const uint8_t* value,
size_t length, AdbcError* error) {
auto private_data = reinterpret_cast<ObjectT*>(obj->private_data);
return private_data->CSetOptionBytes(key, value, length, error);
}
template <typename T, typename ObjectT>
static AdbcStatusCode CSetOptionInt(T* obj, const char* key, int64_t value,
AdbcError* error) {
auto private_data = reinterpret_cast<ObjectT*>(obj->private_data);
return private_data->template CSetOption<>(key, value, error);
}
template <typename T, typename ObjectT>
static AdbcStatusCode CSetOptionDouble(T* obj, const char* key, double value,
AdbcError* error) {
auto private_data = reinterpret_cast<ObjectT*>(obj->private_data);
return private_data->template CSetOption<>(key, value, error);
}
template <typename T, typename ObjectT>
static AdbcStatusCode CGetOption(T* obj, const char* key, char* value, size_t* length,
AdbcError* error) {
auto private_data = reinterpret_cast<ObjectT*>(obj->private_data);
return private_data->template CGetOptionStringLike<>(key, value, length, error);
}
template <typename T, typename ObjectT>
static AdbcStatusCode CGetOptionBytes(T* obj, const char* key, uint8_t* value,
size_t* length, AdbcError* error) {
auto private_data = reinterpret_cast<ObjectT*>(obj->private_data);
return private_data->template CGetOptionStringLike<>(key, value, length, error);
}
template <typename T, typename ObjectT>
static AdbcStatusCode CGetOptionInt(T* obj, const char* key, int64_t* value,
AdbcError* error) {
auto private_data = reinterpret_cast<ObjectT*>(obj->private_data);
return private_data->template CGetOptionNumeric<>(key, value, error);
}
template <typename T, typename ObjectT>
static AdbcStatusCode CGetOptionDouble(T* obj, const char* key, double* value,
AdbcError* error) {
auto private_data = reinterpret_cast<ObjectT*>(obj->private_data);
return private_data->template CGetOptionNumeric<>(key, value, error);
}
// Database trampolines
static AdbcStatusCode CDatabaseInit(AdbcDatabase* database, AdbcError* error) {
auto private_data = reinterpret_cast<DatabaseT*>(database->private_data);
private_data->set_driver(database->private_driver);
return private_data->Init(database->private_driver->private_data, error);
}
// Connection trampolines
static AdbcStatusCode CConnectionInit(AdbcConnection* connection,
AdbcDatabase* database, AdbcError* error) {
auto private_data = reinterpret_cast<ConnectionT*>(connection->private_data);
private_data->set_driver(connection->private_driver);
return private_data->Init(database->private_data, error);
}
static AdbcStatusCode CConnectionCancel(AdbcConnection* connection, AdbcError* error) {
auto private_data = reinterpret_cast<ConnectionT*>(connection->private_data);
return private_data->Cancel(error);
}
static AdbcStatusCode CConnectionGetInfo(AdbcConnection* connection,
const uint32_t* info_codes,
size_t info_codes_length,
ArrowArrayStream* out, AdbcError* error) {
auto private_data = reinterpret_cast<ConnectionT*>(connection->private_data);
return private_data->GetInfo(info_codes, info_codes_length, out, error);
}
static AdbcStatusCode CConnectionGetObjects(AdbcConnection* connection, int depth,
const char* catalog, const char* db_schema,
const char* table_name,
const char** table_type,
const char* column_name,
ArrowArrayStream* out, AdbcError* error) {
auto private_data = reinterpret_cast<ConnectionT*>(connection->private_data);
return private_data->GetObjects(depth, catalog, db_schema, table_name, table_type,
column_name, out, error);
}
static AdbcStatusCode CConnectionGetStatistics(
AdbcConnection* connection, const char* catalog, const char* db_schema,
const char* table_name, char approximate, ArrowArrayStream* out, AdbcError* error) {
auto private_data = reinterpret_cast<ConnectionT*>(connection->private_data);
return private_data->GetStatistics(catalog, db_schema, table_name, approximate, out,
error);
}
static AdbcStatusCode CConnectionGetStatisticNames(AdbcConnection* connection,
ArrowArrayStream* out,
AdbcError* error) {
auto private_data = reinterpret_cast<ConnectionT*>(connection->private_data);
return private_data->GetStatisticNames(out, error);
}
static AdbcStatusCode CConnectionGetTableSchema(AdbcConnection* connection,
const char* catalog,
const char* db_schema,
const char* table_name,
ArrowSchema* schema, AdbcError* error) {
auto private_data = reinterpret_cast<ConnectionT*>(connection->private_data);
return private_data->GetTableSchema(catalog, db_schema, table_name, schema, error);
}
static AdbcStatusCode CConnectionGetTableTypes(AdbcConnection* connection,
ArrowArrayStream* out,
AdbcError* error) {
auto private_data = reinterpret_cast<ConnectionT*>(connection->private_data);
return private_data->GetTableTypes(out, error);
}
static AdbcStatusCode CConnectionReadPartition(AdbcConnection* connection,
const uint8_t* serialized_partition,
size_t serialized_length,
ArrowArrayStream* out,
AdbcError* error) {
auto private_data = reinterpret_cast<ConnectionT*>(connection->private_data);
return private_data->ReadPartition(serialized_partition, serialized_length, out,
error);
}
static AdbcStatusCode CConnectionCommit(AdbcConnection* connection, AdbcError* error) {
auto private_data = reinterpret_cast<ConnectionT*>(connection->private_data);
return private_data->Commit(error);
}
static AdbcStatusCode CConnectionRollback(AdbcConnection* connection,
AdbcError* error) {
auto private_data = reinterpret_cast<ConnectionT*>(connection->private_data);
return private_data->Rollback(error);
}
// Statement trampolines
static AdbcStatusCode CStatementNew(AdbcConnection* connection,
AdbcStatement* statement, AdbcError* error) {
auto private_data = new StatementT();
private_data->set_driver(connection->private_driver);
AdbcStatusCode status = private_data->Init(connection->private_data, error);
if (status != ADBC_STATUS_OK) {
delete private_data;
}
statement->private_data = private_data;
return ADBC_STATUS_OK;
}
static AdbcStatusCode CStatementExecuteQuery(AdbcStatement* statement,
ArrowArrayStream* stream,
int64_t* rows_affected, AdbcError* error) {
auto private_data = reinterpret_cast<StatementT*>(statement->private_data);
return private_data->ExecuteQuery(stream, rows_affected, error);
}
static AdbcStatusCode CStatementExecuteSchema(AdbcStatement* statement,
ArrowSchema* schema, AdbcError* error) {
auto private_data = reinterpret_cast<StatementT*>(statement->private_data);
return private_data->ExecuteSchema(schema, error);
}
static AdbcStatusCode CStatementPrepare(AdbcStatement* statement, AdbcError* error) {
auto private_data = reinterpret_cast<StatementT*>(statement->private_data);
return private_data->Prepare(error);
}
static AdbcStatusCode CStatementSetSqlQuery(AdbcStatement* statement, const char* query,
AdbcError* error) {
auto private_data = reinterpret_cast<StatementT*>(statement->private_data);
return private_data->SetSqlQuery(query, error);
}
static AdbcStatusCode CStatementSetSubstraitPlan(AdbcStatement* statement,
const uint8_t* plan, size_t length,
AdbcError* error) {
auto private_data = reinterpret_cast<StatementT*>(statement->private_data);
return private_data->SetSubstraitPlan(plan, length, error);
}
static AdbcStatusCode CStatementBind(AdbcStatement* statement, ArrowArray* values,
ArrowSchema* schema, AdbcError* error) {
auto private_data = reinterpret_cast<StatementT*>(statement->private_data);
return private_data->Bind(values, schema, error);
}
static AdbcStatusCode CStatementBindStream(AdbcStatement* statement,
ArrowArrayStream* stream, AdbcError* error) {
auto private_data = reinterpret_cast<StatementT*>(statement->private_data);
return private_data->BindStream(stream, error);
}
static AdbcStatusCode CStatementCancel(AdbcStatement* statement, AdbcError* error) {
auto private_data = reinterpret_cast<StatementT*>(statement->private_data);
return private_data->Cancel(error);
}
};
} // namespace common
} // namespace adbc