Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ docker_cache

site/

# Python
dist/

# R files
**/.Rproj.user
**/*.Rcheck/
Expand Down
57 changes: 57 additions & 0 deletions adbc.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,61 @@ AdbcStatusCode AdbcConnectionRelease(struct AdbcConnection* connection,
///
/// @{

/// \brief Get metadata about the database/driver.
///
/// The result is an Arrow dataset with the following schema:
///
/// Field Name | Field Type
/// ----------------------------|------------------------
/// info_name | uint32 not null
/// info_value | INFO_SCHEMA
///
/// INFO_SCHEMA is a dense union with members:
///
/// Field Name (Type Code) | Field Type
/// ----------------------------|------------------------
/// string_value (0) | utf8
/// bool_value (1) | bool
/// int64_value (2) | int64
/// int32_bitmask (3) | int32
/// string_list (4) | list<utf8>
/// int32_to_int32_list_map (5) | map<int32, list<int32>>
///
/// Each metadatum is identified by an integer code. The recognized
/// codes are defined as constants. Codes [0, 10_000) are reserved
/// for ADBC usage. Drivers/vendors will ignore requests for
/// unrecognized codes (the row will be omitted from the result).
///
/// \param[in] connection The connection to query.
/// \param[in] info_codes A list of metadata codes to fetch, or NULL
/// to fetch all.
/// \param[in] info_codes_length The length of the info_codes
/// parameter. Ignored if info_codes is NULL.
/// \param[out] statement The result set. AdbcStatementGetStream can
/// be called immediately; do not call Execute or Prepare.
/// \param[out] error Error details, if an error occurs.
ADBC_EXPORT
AdbcStatusCode AdbcConnectionGetInfo(struct AdbcConnection* connection,
uint32_t* info_codes, size_t info_codes_length,
struct AdbcStatement* statement,
struct AdbcError* error);

/// \brief The database vendor/product name (e.g. the server name).
/// (type: utf8).
#define ADBC_INFO_VENDOR_NAME 0
/// \brief The database vendor/product version (type: utf8).
#define ADBC_INFO_VENDOR_VERSION 1
/// \brief The database vendor/product Arrow library version (type:
/// utf8).
#define ADBC_INFO_VENDOR_ARROW_VERSION 2

/// \brief The driver name (type: utf8).
#define ADBC_INFO_DRIVER_NAME 100
/// \brief The driver version (type: utf8).
#define ADBC_INFO_DRIVER_VERSION 101
/// \brief The driver Arrow library version (type: utf8).
#define ADBC_INFO_DRIVER_ARROW_VERSION 102

/// \brief Get a hierarchical view of all catalogs, database schemas,
/// tables, and columns.
///
Expand Down Expand Up @@ -819,6 +874,8 @@ struct ADBC_EXPORT AdbcDriver {
AdbcStatusCode (*DatabaseInit)(struct AdbcDatabase*, struct AdbcError*);
AdbcStatusCode (*DatabaseRelease)(struct AdbcDatabase*, struct AdbcError*);

AdbcStatusCode (*ConnectionGetInfo)(struct AdbcConnection*, uint32_t*, size_t,
struct AdbcStatement*, struct AdbcError*);
AdbcStatusCode (*ConnectionNew)(struct AdbcConnection*, struct AdbcError*);
AdbcStatusCode (*ConnectionSetOption)(struct AdbcConnection*, const char*, const char*,
struct AdbcError*);
Expand Down
12 changes: 12 additions & 0 deletions c/driver_manager/adbc_driver_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,17 @@ AdbcStatusCode AdbcConnectionCommit(struct AdbcConnection* connection,
return connection->private_driver->ConnectionCommit(connection, error);
}

AdbcStatusCode AdbcConnectionGetInfo(struct AdbcConnection* connection,
uint32_t* info_codes, size_t info_codes_length,
struct AdbcStatement* statement,
struct AdbcError* error) {
if (!connection->private_driver) {
return ADBC_STATUS_INVALID_STATE;
}
return connection->private_driver->ConnectionGetInfo(
connection, info_codes, info_codes_length, statement, error);
}

AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int depth,
const char* catalog, const char* db_schema,
const char* table_name, const char** table_types,
Expand Down Expand Up @@ -681,6 +692,7 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name, const char* entrypoint,
CHECK_REQUIRED(driver, DatabaseInit);
CHECK_REQUIRED(driver, DatabaseRelease);

CHECK_REQUIRED(driver, ConnectionGetInfo);
CHECK_REQUIRED(driver, ConnectionNew);
CHECK_REQUIRED(driver, ConnectionInit);
CHECK_REQUIRED(driver, ConnectionRelease);
Expand Down
45 changes: 45 additions & 0 deletions c/driver_manager/adbc_driver_manager_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,51 @@ TEST_F(DriverManager, ConnectionInitRelease) {
ADBC_ASSERT_OK_WITH_ERROR(error, AdbcConnectionRelease(&connection, &error));
}

TEST_F(DriverManager, MetadataGetInfo) {
static std::shared_ptr<arrow::Schema> kInfoSchema = arrow::schema({
arrow::field("info_name", arrow::uint32(), /*nullable=*/false),
arrow::field(
"info_value",
arrow::dense_union({
arrow::field("string_value", arrow::utf8()),
arrow::field("bool_value", arrow::boolean()),
arrow::field("int64_value", arrow::int64()),
arrow::field("int32_bitmask", arrow::int32()),
arrow::field("string_list", arrow::list(arrow::utf8())),
arrow::field("int32_to_int32_list_map",
arrow::map(arrow::int32(), arrow::list(arrow::int32()))),
})),
});

AdbcStatement statement;
std::memset(&statement, 0, sizeof(statement));
ADBC_ASSERT_OK_WITH_ERROR(error, AdbcStatementNew(&connection, &statement, &error));
ADBC_ASSERT_OK_WITH_ERROR(
error, AdbcConnectionGetInfo(&connection, nullptr, 0, &statement, &error));

std::shared_ptr<arrow::Schema> schema;
arrow::RecordBatchVector batches;
ReadStatement(&statement, &schema, &batches);
ASSERT_SCHEMA_EQ(*schema, *kInfoSchema);
ASSERT_EQ(1, batches.size());

std::vector<uint32_t> info = {
ADBC_INFO_DRIVER_NAME,
ADBC_INFO_DRIVER_VERSION,
ADBC_INFO_VENDOR_NAME,
ADBC_INFO_VENDOR_VERSION,
};
ADBC_ASSERT_OK_WITH_ERROR(error, AdbcStatementNew(&connection, &statement, &error));
ADBC_ASSERT_OK_WITH_ERROR(
error,
AdbcConnectionGetInfo(&connection, info.data(), info.size(), &statement, &error));
batches.clear();
ReadStatement(&statement, &schema, &batches);
ASSERT_SCHEMA_EQ(*schema, *kInfoSchema);
ASSERT_EQ(1, batches.size());
ASSERT_EQ(4, batches[0]->num_rows());
}

TEST_F(DriverManager, SqlExecute) {
std::string query = "SELECT 1";
AdbcStatement statement;
Expand Down
116 changes: 116 additions & 0 deletions c/drivers/sqlite/sqlite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <arrow/record_batch.h>
#include <arrow/status.h>
#include <arrow/table.h>
#include <arrow/util/config.h>
#include <arrow/util/logging.h>
#include <arrow/util/string_builder.h>

Expand Down Expand Up @@ -621,6 +622,102 @@ class SqliteStatementImpl {
return ADBC_STATUS_INVALID_STATE;
}

AdbcStatusCode GetInfo(const std::shared_ptr<SqliteStatementImpl>& self,
uint32_t* info_codes, size_t info_codes_length,
struct AdbcError* error) {
static std::shared_ptr<arrow::Schema> kInfoSchema = arrow::schema({
arrow::field("info_name", arrow::uint32(), /*nullable=*/false),
arrow::field(
"info_value",
arrow::dense_union({
arrow::field("string_value", arrow::utf8()),
arrow::field("bool_value", arrow::boolean()),
arrow::field("int64_value", arrow::int64()),
arrow::field("int32_bitmask", arrow::int32()),
arrow::field("string_list", arrow::list(arrow::utf8())),
arrow::field("int32_to_int32_list_map",
arrow::map(arrow::int32(), arrow::list(arrow::int32()))),
})),
});
static int kStringValueCode = 0;

static std::vector<uint32_t> kSupported = {
ADBC_INFO_VENDOR_NAME, ADBC_INFO_VENDOR_VERSION, ADBC_INFO_DRIVER_NAME,
ADBC_INFO_DRIVER_VERSION, ADBC_INFO_DRIVER_ARROW_VERSION,
};

if (!info_codes) {
info_codes = kSupported.data();
info_codes_length = kSupported.size();
}

arrow::UInt32Builder info_name;
std::unique_ptr<arrow::ArrayBuilder> info_value_builder;
ADBC_RETURN_NOT_OK(
FromArrowStatus(MakeBuilder(arrow::default_memory_pool(),
kInfoSchema->field(1)->type(), &info_value_builder),
error));
arrow::DenseUnionBuilder* info_value =
static_cast<arrow::DenseUnionBuilder*>(info_value_builder.get());
arrow::StringBuilder* info_string =
static_cast<arrow::StringBuilder*>(info_value->child_builder(0).get());

for (size_t i = 0; i < info_codes_length; i++) {
switch (info_codes[i]) {
case ADBC_INFO_VENDOR_NAME:
ADBC_RETURN_NOT_OK(FromArrowStatus(info_name.Append(info_codes[i]), error));
ADBC_RETURN_NOT_OK(
FromArrowStatus(info_value->Append(kStringValueCode), error));
ADBC_RETURN_NOT_OK(FromArrowStatus(info_string->Append("SQLite3"), error));
break;
case ADBC_INFO_VENDOR_VERSION:
ADBC_RETURN_NOT_OK(FromArrowStatus(info_name.Append(info_codes[i]), error));
ADBC_RETURN_NOT_OK(
FromArrowStatus(info_value->Append(kStringValueCode), error));
ADBC_RETURN_NOT_OK(
FromArrowStatus(info_string->Append(sqlite3_libversion()), error));
break;
case ADBC_INFO_DRIVER_NAME:
ADBC_RETURN_NOT_OK(FromArrowStatus(info_name.Append(info_codes[i]), error));
ADBC_RETURN_NOT_OK(
FromArrowStatus(info_value->Append(kStringValueCode), error));
ADBC_RETURN_NOT_OK(
FromArrowStatus(info_string->Append("ADBC C SQLite3"), error));
break;
case ADBC_INFO_DRIVER_VERSION:
// TODO: set up CMake to embed version info
ADBC_RETURN_NOT_OK(FromArrowStatus(info_name.Append(info_codes[i]), error));
ADBC_RETURN_NOT_OK(
FromArrowStatus(info_value->Append(kStringValueCode), error));
ADBC_RETURN_NOT_OK(FromArrowStatus(info_string->Append("0.0.1"), error));
break;
case ADBC_INFO_DRIVER_ARROW_VERSION:
ADBC_RETURN_NOT_OK(FromArrowStatus(info_name.Append(info_codes[i]), error));
ADBC_RETURN_NOT_OK(
FromArrowStatus(info_value->Append(kStringValueCode), error));
ADBC_RETURN_NOT_OK(FromArrowStatus(
info_string->Append("Arrow/C++ " ARROW_VERSION_STRING), error));
break;
default:
// Unrecognized
break;
}
}

arrow::ArrayVector arrays(2);
ADBC_RETURN_NOT_OK(FromArrowStatus(info_name.Finish(&arrays[0]), error));
ADBC_RETURN_NOT_OK(FromArrowStatus(info_value->Finish(&arrays[1]), error));
const int64_t rows = arrays[0]->length();
auto status = arrow::RecordBatchReader::Make(
{
arrow::RecordBatch::Make(kInfoSchema, rows, std::move(arrays)),
},
kInfoSchema)
.Value(&result_reader_);
ADBC_RETURN_NOT_OK(FromArrowStatus(status, error));
return ADBC_STATUS_OK;
}

AdbcStatusCode GetObjects(const std::shared_ptr<SqliteStatementImpl>& self, int depth,
const char* catalog, const char* db_schema,
const char* table_name, const char** table_type,
Expand Down Expand Up @@ -1234,6 +1331,16 @@ AdbcStatusCode SqliteConnectionCommit(struct AdbcConnection* connection,
return (*ptr)->Commit(error);
}

AdbcStatusCode SqliteConnectionGetInfo(struct AdbcConnection* connection,
uint32_t* info_codes, size_t info_codes_length,
struct AdbcStatement* statement,
struct AdbcError* error) {
if (!statement->private_data) return ADBC_STATUS_INVALID_STATE;
auto ptr =
reinterpret_cast<std::shared_ptr<SqliteStatementImpl>*>(statement->private_data);
return (*ptr)->GetInfo(*ptr, info_codes, info_codes_length, error);
}

AdbcStatusCode SqliteConnectionGetObjects(
struct AdbcConnection* connection, int depth, const char* catalog,
const char* db_schema, const char* table_name, const char** table_types,
Expand Down Expand Up @@ -1441,6 +1548,14 @@ AdbcStatusCode AdbcConnectionCommit(struct AdbcConnection* connection,
return SqliteConnectionCommit(connection, error);
}

AdbcStatusCode AdbcConnectionGetInfo(struct AdbcConnection* connection,
uint32_t* info_codes, size_t info_codes_length,
struct AdbcStatement* statement,
struct AdbcError* error) {
return SqliteConnectionGetInfo(connection, info_codes, info_codes_length, statement,
error);
}

AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int depth,
const char* catalog, const char* db_schema,
const char* table_name, const char** table_types,
Expand Down Expand Up @@ -1566,6 +1681,7 @@ AdbcStatusCode AdbcSqliteDriverInit(size_t count, struct AdbcDriver* driver,
driver->DatabaseSetOption = SqliteDatabaseSetOption;

driver->ConnectionCommit = SqliteConnectionCommit;
driver->ConnectionGetInfo = SqliteConnectionGetInfo;
driver->ConnectionGetObjects = SqliteConnectionGetObjects;
driver->ConnectionGetTableSchema = SqliteConnectionGetTableSchema;
driver->ConnectionGetTableTypes = SqliteConnectionGetTableTypes;
Expand Down
45 changes: 45 additions & 0 deletions c/drivers/sqlite/sqlite_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,51 @@ TEST_F(Sqlite, MultipleConnections) {
ADBC_ASSERT_OK_WITH_ERROR(error, AdbcConnectionRelease(&connection2, &error));
}

TEST_F(Sqlite, MetadataGetInfo) {
static std::shared_ptr<arrow::Schema> kInfoSchema = arrow::schema({
arrow::field("info_name", arrow::uint32(), /*nullable=*/false),
arrow::field(
"info_value",
arrow::dense_union({
arrow::field("string_value", arrow::utf8()),
arrow::field("bool_value", arrow::boolean()),
arrow::field("int64_value", arrow::int64()),
arrow::field("int32_bitmask", arrow::int32()),
arrow::field("string_list", arrow::list(arrow::utf8())),
arrow::field("int32_to_int32_list_map",
arrow::map(arrow::int32(), arrow::list(arrow::int32()))),
})),
});

AdbcStatement statement;
std::memset(&statement, 0, sizeof(statement));
ADBC_ASSERT_OK_WITH_ERROR(error, AdbcStatementNew(&connection, &statement, &error));
ADBC_ASSERT_OK_WITH_ERROR(
error, AdbcConnectionGetInfo(&connection, nullptr, 0, &statement, &error));

std::shared_ptr<arrow::Schema> schema;
arrow::RecordBatchVector batches;
ReadStatement(&statement, &schema, &batches);
ASSERT_SCHEMA_EQ(*schema, *kInfoSchema);
ASSERT_EQ(1, batches.size());

std::vector<uint32_t> info = {
ADBC_INFO_DRIVER_NAME,
ADBC_INFO_DRIVER_VERSION,
ADBC_INFO_VENDOR_NAME,
ADBC_INFO_VENDOR_VERSION,
};
ADBC_ASSERT_OK_WITH_ERROR(error, AdbcStatementNew(&connection, &statement, &error));
ADBC_ASSERT_OK_WITH_ERROR(
error,
AdbcConnectionGetInfo(&connection, info.data(), info.size(), &statement, &error));
batches.clear();
ReadStatement(&statement, &schema, &batches);
ASSERT_SCHEMA_EQ(*schema, *kInfoSchema);
ASSERT_EQ(1, batches.size());
ASSERT_EQ(4, batches[0]->num_rows());
}

TEST_F(Sqlite, MetadataGetTableTypes) {
AdbcStatement statement;
std::memset(&statement, 0, sizeof(statement));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ default AdbcStatement deserializePartitionDescriptor(ByteBuffer descriptor) thro
"Connection does not support deserializePartitionDescriptor(ByteBuffer)");
}

AdbcStatement getInfo(int[] infoCodes) throws AdbcException;

default AdbcStatement getInfo(AdbcInfoCode[] infoCodes) throws AdbcException {
int[] codes = new int[infoCodes.length];
for (int i = 0; i < infoCodes.length; i++) {
codes[i] = infoCodes[i].getValue();
}
return getInfo(codes);
}

default AdbcStatement getInfo() throws AdbcException {
return getInfo((int[]) null);
}

/**
* Get a hierarchical view of all catalogs, database schemas, tables, and columns.
*
Expand Down
Loading