Skip to content

Commit 97c032d

Browse files
authored
[C][Java][Python] Add GetInfo (#45)
1 parent cfe1752 commit 97c032d

File tree

18 files changed

+632
-26
lines changed

18 files changed

+632
-26
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ docker_cache
7070

7171
site/
7272

73+
# Python
74+
dist/
75+
7376
# R files
7477
**/.Rproj.user
7578
**/*.Rcheck/

adbc.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,61 @@ AdbcStatusCode AdbcConnectionRelease(struct AdbcConnection* connection,
358358
///
359359
/// @{
360360

361+
/// \brief Get metadata about the database/driver.
362+
///
363+
/// The result is an Arrow dataset with the following schema:
364+
///
365+
/// Field Name | Field Type
366+
/// ----------------------------|------------------------
367+
/// info_name | uint32 not null
368+
/// info_value | INFO_SCHEMA
369+
///
370+
/// INFO_SCHEMA is a dense union with members:
371+
///
372+
/// Field Name (Type Code) | Field Type
373+
/// ----------------------------|------------------------
374+
/// string_value (0) | utf8
375+
/// bool_value (1) | bool
376+
/// int64_value (2) | int64
377+
/// int32_bitmask (3) | int32
378+
/// string_list (4) | list<utf8>
379+
/// int32_to_int32_list_map (5) | map<int32, list<int32>>
380+
///
381+
/// Each metadatum is identified by an integer code. The recognized
382+
/// codes are defined as constants. Codes [0, 10_000) are reserved
383+
/// for ADBC usage. Drivers/vendors will ignore requests for
384+
/// unrecognized codes (the row will be omitted from the result).
385+
///
386+
/// \param[in] connection The connection to query.
387+
/// \param[in] info_codes A list of metadata codes to fetch, or NULL
388+
/// to fetch all.
389+
/// \param[in] info_codes_length The length of the info_codes
390+
/// parameter. Ignored if info_codes is NULL.
391+
/// \param[out] statement The result set. AdbcStatementGetStream can
392+
/// be called immediately; do not call Execute or Prepare.
393+
/// \param[out] error Error details, if an error occurs.
394+
ADBC_EXPORT
395+
AdbcStatusCode AdbcConnectionGetInfo(struct AdbcConnection* connection,
396+
uint32_t* info_codes, size_t info_codes_length,
397+
struct AdbcStatement* statement,
398+
struct AdbcError* error);
399+
400+
/// \brief The database vendor/product name (e.g. the server name).
401+
/// (type: utf8).
402+
#define ADBC_INFO_VENDOR_NAME 0
403+
/// \brief The database vendor/product version (type: utf8).
404+
#define ADBC_INFO_VENDOR_VERSION 1
405+
/// \brief The database vendor/product Arrow library version (type:
406+
/// utf8).
407+
#define ADBC_INFO_VENDOR_ARROW_VERSION 2
408+
409+
/// \brief The driver name (type: utf8).
410+
#define ADBC_INFO_DRIVER_NAME 100
411+
/// \brief The driver version (type: utf8).
412+
#define ADBC_INFO_DRIVER_VERSION 101
413+
/// \brief The driver Arrow library version (type: utf8).
414+
#define ADBC_INFO_DRIVER_ARROW_VERSION 102
415+
361416
/// \brief Get a hierarchical view of all catalogs, database schemas,
362417
/// tables, and columns.
363418
///
@@ -819,6 +874,8 @@ struct ADBC_EXPORT AdbcDriver {
819874
AdbcStatusCode (*DatabaseInit)(struct AdbcDatabase*, struct AdbcError*);
820875
AdbcStatusCode (*DatabaseRelease)(struct AdbcDatabase*, struct AdbcError*);
821876

877+
AdbcStatusCode (*ConnectionGetInfo)(struct AdbcConnection*, uint32_t*, size_t,
878+
struct AdbcStatement*, struct AdbcError*);
822879
AdbcStatusCode (*ConnectionNew)(struct AdbcConnection*, struct AdbcError*);
823880
AdbcStatusCode (*ConnectionSetOption)(struct AdbcConnection*, const char*, const char*,
824881
struct AdbcError*);

c/driver_manager/adbc_driver_manager.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,17 @@ AdbcStatusCode AdbcConnectionCommit(struct AdbcConnection* connection,
320320
return connection->private_driver->ConnectionCommit(connection, error);
321321
}
322322

323+
AdbcStatusCode AdbcConnectionGetInfo(struct AdbcConnection* connection,
324+
uint32_t* info_codes, size_t info_codes_length,
325+
struct AdbcStatement* statement,
326+
struct AdbcError* error) {
327+
if (!connection->private_driver) {
328+
return ADBC_STATUS_INVALID_STATE;
329+
}
330+
return connection->private_driver->ConnectionGetInfo(
331+
connection, info_codes, info_codes_length, statement, error);
332+
}
333+
323334
AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int depth,
324335
const char* catalog, const char* db_schema,
325336
const char* table_name, const char** table_types,
@@ -681,6 +692,7 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name, const char* entrypoint,
681692
CHECK_REQUIRED(driver, DatabaseInit);
682693
CHECK_REQUIRED(driver, DatabaseRelease);
683694

695+
CHECK_REQUIRED(driver, ConnectionGetInfo);
684696
CHECK_REQUIRED(driver, ConnectionNew);
685697
CHECK_REQUIRED(driver, ConnectionInit);
686698
CHECK_REQUIRED(driver, ConnectionRelease);

c/driver_manager/adbc_driver_manager_test.cc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,51 @@ TEST_F(DriverManager, ConnectionInitRelease) {
107107
ADBC_ASSERT_OK_WITH_ERROR(error, AdbcConnectionRelease(&connection, &error));
108108
}
109109

110+
TEST_F(DriverManager, MetadataGetInfo) {
111+
static std::shared_ptr<arrow::Schema> kInfoSchema = arrow::schema({
112+
arrow::field("info_name", arrow::uint32(), /*nullable=*/false),
113+
arrow::field(
114+
"info_value",
115+
arrow::dense_union({
116+
arrow::field("string_value", arrow::utf8()),
117+
arrow::field("bool_value", arrow::boolean()),
118+
arrow::field("int64_value", arrow::int64()),
119+
arrow::field("int32_bitmask", arrow::int32()),
120+
arrow::field("string_list", arrow::list(arrow::utf8())),
121+
arrow::field("int32_to_int32_list_map",
122+
arrow::map(arrow::int32(), arrow::list(arrow::int32()))),
123+
})),
124+
});
125+
126+
AdbcStatement statement;
127+
std::memset(&statement, 0, sizeof(statement));
128+
ADBC_ASSERT_OK_WITH_ERROR(error, AdbcStatementNew(&connection, &statement, &error));
129+
ADBC_ASSERT_OK_WITH_ERROR(
130+
error, AdbcConnectionGetInfo(&connection, nullptr, 0, &statement, &error));
131+
132+
std::shared_ptr<arrow::Schema> schema;
133+
arrow::RecordBatchVector batches;
134+
ReadStatement(&statement, &schema, &batches);
135+
ASSERT_SCHEMA_EQ(*schema, *kInfoSchema);
136+
ASSERT_EQ(1, batches.size());
137+
138+
std::vector<uint32_t> info = {
139+
ADBC_INFO_DRIVER_NAME,
140+
ADBC_INFO_DRIVER_VERSION,
141+
ADBC_INFO_VENDOR_NAME,
142+
ADBC_INFO_VENDOR_VERSION,
143+
};
144+
ADBC_ASSERT_OK_WITH_ERROR(error, AdbcStatementNew(&connection, &statement, &error));
145+
ADBC_ASSERT_OK_WITH_ERROR(
146+
error,
147+
AdbcConnectionGetInfo(&connection, info.data(), info.size(), &statement, &error));
148+
batches.clear();
149+
ReadStatement(&statement, &schema, &batches);
150+
ASSERT_SCHEMA_EQ(*schema, *kInfoSchema);
151+
ASSERT_EQ(1, batches.size());
152+
ASSERT_EQ(4, batches[0]->num_rows());
153+
}
154+
110155
TEST_F(DriverManager, SqlExecute) {
111156
std::string query = "SELECT 1";
112157
AdbcStatement statement;

c/drivers/sqlite/sqlite.cc

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <arrow/record_batch.h>
3030
#include <arrow/status.h>
3131
#include <arrow/table.h>
32+
#include <arrow/util/config.h>
3233
#include <arrow/util/logging.h>
3334
#include <arrow/util/string_builder.h>
3435

@@ -621,6 +622,102 @@ class SqliteStatementImpl {
621622
return ADBC_STATUS_INVALID_STATE;
622623
}
623624

625+
AdbcStatusCode GetInfo(const std::shared_ptr<SqliteStatementImpl>& self,
626+
uint32_t* info_codes, size_t info_codes_length,
627+
struct AdbcError* error) {
628+
static std::shared_ptr<arrow::Schema> kInfoSchema = arrow::schema({
629+
arrow::field("info_name", arrow::uint32(), /*nullable=*/false),
630+
arrow::field(
631+
"info_value",
632+
arrow::dense_union({
633+
arrow::field("string_value", arrow::utf8()),
634+
arrow::field("bool_value", arrow::boolean()),
635+
arrow::field("int64_value", arrow::int64()),
636+
arrow::field("int32_bitmask", arrow::int32()),
637+
arrow::field("string_list", arrow::list(arrow::utf8())),
638+
arrow::field("int32_to_int32_list_map",
639+
arrow::map(arrow::int32(), arrow::list(arrow::int32()))),
640+
})),
641+
});
642+
static int kStringValueCode = 0;
643+
644+
static std::vector<uint32_t> kSupported = {
645+
ADBC_INFO_VENDOR_NAME, ADBC_INFO_VENDOR_VERSION, ADBC_INFO_DRIVER_NAME,
646+
ADBC_INFO_DRIVER_VERSION, ADBC_INFO_DRIVER_ARROW_VERSION,
647+
};
648+
649+
if (!info_codes) {
650+
info_codes = kSupported.data();
651+
info_codes_length = kSupported.size();
652+
}
653+
654+
arrow::UInt32Builder info_name;
655+
std::unique_ptr<arrow::ArrayBuilder> info_value_builder;
656+
ADBC_RETURN_NOT_OK(
657+
FromArrowStatus(MakeBuilder(arrow::default_memory_pool(),
658+
kInfoSchema->field(1)->type(), &info_value_builder),
659+
error));
660+
arrow::DenseUnionBuilder* info_value =
661+
static_cast<arrow::DenseUnionBuilder*>(info_value_builder.get());
662+
arrow::StringBuilder* info_string =
663+
static_cast<arrow::StringBuilder*>(info_value->child_builder(0).get());
664+
665+
for (size_t i = 0; i < info_codes_length; i++) {
666+
switch (info_codes[i]) {
667+
case ADBC_INFO_VENDOR_NAME:
668+
ADBC_RETURN_NOT_OK(FromArrowStatus(info_name.Append(info_codes[i]), error));
669+
ADBC_RETURN_NOT_OK(
670+
FromArrowStatus(info_value->Append(kStringValueCode), error));
671+
ADBC_RETURN_NOT_OK(FromArrowStatus(info_string->Append("SQLite3"), error));
672+
break;
673+
case ADBC_INFO_VENDOR_VERSION:
674+
ADBC_RETURN_NOT_OK(FromArrowStatus(info_name.Append(info_codes[i]), error));
675+
ADBC_RETURN_NOT_OK(
676+
FromArrowStatus(info_value->Append(kStringValueCode), error));
677+
ADBC_RETURN_NOT_OK(
678+
FromArrowStatus(info_string->Append(sqlite3_libversion()), error));
679+
break;
680+
case ADBC_INFO_DRIVER_NAME:
681+
ADBC_RETURN_NOT_OK(FromArrowStatus(info_name.Append(info_codes[i]), error));
682+
ADBC_RETURN_NOT_OK(
683+
FromArrowStatus(info_value->Append(kStringValueCode), error));
684+
ADBC_RETURN_NOT_OK(
685+
FromArrowStatus(info_string->Append("ADBC C SQLite3"), error));
686+
break;
687+
case ADBC_INFO_DRIVER_VERSION:
688+
// TODO: set up CMake to embed version info
689+
ADBC_RETURN_NOT_OK(FromArrowStatus(info_name.Append(info_codes[i]), error));
690+
ADBC_RETURN_NOT_OK(
691+
FromArrowStatus(info_value->Append(kStringValueCode), error));
692+
ADBC_RETURN_NOT_OK(FromArrowStatus(info_string->Append("0.0.1"), error));
693+
break;
694+
case ADBC_INFO_DRIVER_ARROW_VERSION:
695+
ADBC_RETURN_NOT_OK(FromArrowStatus(info_name.Append(info_codes[i]), error));
696+
ADBC_RETURN_NOT_OK(
697+
FromArrowStatus(info_value->Append(kStringValueCode), error));
698+
ADBC_RETURN_NOT_OK(FromArrowStatus(
699+
info_string->Append("Arrow/C++ " ARROW_VERSION_STRING), error));
700+
break;
701+
default:
702+
// Unrecognized
703+
break;
704+
}
705+
}
706+
707+
arrow::ArrayVector arrays(2);
708+
ADBC_RETURN_NOT_OK(FromArrowStatus(info_name.Finish(&arrays[0]), error));
709+
ADBC_RETURN_NOT_OK(FromArrowStatus(info_value->Finish(&arrays[1]), error));
710+
const int64_t rows = arrays[0]->length();
711+
auto status = arrow::RecordBatchReader::Make(
712+
{
713+
arrow::RecordBatch::Make(kInfoSchema, rows, std::move(arrays)),
714+
},
715+
kInfoSchema)
716+
.Value(&result_reader_);
717+
ADBC_RETURN_NOT_OK(FromArrowStatus(status, error));
718+
return ADBC_STATUS_OK;
719+
}
720+
624721
AdbcStatusCode GetObjects(const std::shared_ptr<SqliteStatementImpl>& self, int depth,
625722
const char* catalog, const char* db_schema,
626723
const char* table_name, const char** table_type,
@@ -1234,6 +1331,16 @@ AdbcStatusCode SqliteConnectionCommit(struct AdbcConnection* connection,
12341331
return (*ptr)->Commit(error);
12351332
}
12361333

1334+
AdbcStatusCode SqliteConnectionGetInfo(struct AdbcConnection* connection,
1335+
uint32_t* info_codes, size_t info_codes_length,
1336+
struct AdbcStatement* statement,
1337+
struct AdbcError* error) {
1338+
if (!statement->private_data) return ADBC_STATUS_INVALID_STATE;
1339+
auto ptr =
1340+
reinterpret_cast<std::shared_ptr<SqliteStatementImpl>*>(statement->private_data);
1341+
return (*ptr)->GetInfo(*ptr, info_codes, info_codes_length, error);
1342+
}
1343+
12371344
AdbcStatusCode SqliteConnectionGetObjects(
12381345
struct AdbcConnection* connection, int depth, const char* catalog,
12391346
const char* db_schema, const char* table_name, const char** table_types,
@@ -1441,6 +1548,14 @@ AdbcStatusCode AdbcConnectionCommit(struct AdbcConnection* connection,
14411548
return SqliteConnectionCommit(connection, error);
14421549
}
14431550

1551+
AdbcStatusCode AdbcConnectionGetInfo(struct AdbcConnection* connection,
1552+
uint32_t* info_codes, size_t info_codes_length,
1553+
struct AdbcStatement* statement,
1554+
struct AdbcError* error) {
1555+
return SqliteConnectionGetInfo(connection, info_codes, info_codes_length, statement,
1556+
error);
1557+
}
1558+
14441559
AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int depth,
14451560
const char* catalog, const char* db_schema,
14461561
const char* table_name, const char** table_types,
@@ -1566,6 +1681,7 @@ AdbcStatusCode AdbcSqliteDriverInit(size_t count, struct AdbcDriver* driver,
15661681
driver->DatabaseSetOption = SqliteDatabaseSetOption;
15671682

15681683
driver->ConnectionCommit = SqliteConnectionCommit;
1684+
driver->ConnectionGetInfo = SqliteConnectionGetInfo;
15691685
driver->ConnectionGetObjects = SqliteConnectionGetObjects;
15701686
driver->ConnectionGetTableSchema = SqliteConnectionGetTableSchema;
15711687
driver->ConnectionGetTableTypes = SqliteConnectionGetTableTypes;

c/drivers/sqlite/sqlite_test.cc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,51 @@ TEST_F(Sqlite, MultipleConnections) {
421421
ADBC_ASSERT_OK_WITH_ERROR(error, AdbcConnectionRelease(&connection2, &error));
422422
}
423423

424+
TEST_F(Sqlite, MetadataGetInfo) {
425+
static std::shared_ptr<arrow::Schema> kInfoSchema = arrow::schema({
426+
arrow::field("info_name", arrow::uint32(), /*nullable=*/false),
427+
arrow::field(
428+
"info_value",
429+
arrow::dense_union({
430+
arrow::field("string_value", arrow::utf8()),
431+
arrow::field("bool_value", arrow::boolean()),
432+
arrow::field("int64_value", arrow::int64()),
433+
arrow::field("int32_bitmask", arrow::int32()),
434+
arrow::field("string_list", arrow::list(arrow::utf8())),
435+
arrow::field("int32_to_int32_list_map",
436+
arrow::map(arrow::int32(), arrow::list(arrow::int32()))),
437+
})),
438+
});
439+
440+
AdbcStatement statement;
441+
std::memset(&statement, 0, sizeof(statement));
442+
ADBC_ASSERT_OK_WITH_ERROR(error, AdbcStatementNew(&connection, &statement, &error));
443+
ADBC_ASSERT_OK_WITH_ERROR(
444+
error, AdbcConnectionGetInfo(&connection, nullptr, 0, &statement, &error));
445+
446+
std::shared_ptr<arrow::Schema> schema;
447+
arrow::RecordBatchVector batches;
448+
ReadStatement(&statement, &schema, &batches);
449+
ASSERT_SCHEMA_EQ(*schema, *kInfoSchema);
450+
ASSERT_EQ(1, batches.size());
451+
452+
std::vector<uint32_t> info = {
453+
ADBC_INFO_DRIVER_NAME,
454+
ADBC_INFO_DRIVER_VERSION,
455+
ADBC_INFO_VENDOR_NAME,
456+
ADBC_INFO_VENDOR_VERSION,
457+
};
458+
ADBC_ASSERT_OK_WITH_ERROR(error, AdbcStatementNew(&connection, &statement, &error));
459+
ADBC_ASSERT_OK_WITH_ERROR(
460+
error,
461+
AdbcConnectionGetInfo(&connection, info.data(), info.size(), &statement, &error));
462+
batches.clear();
463+
ReadStatement(&statement, &schema, &batches);
464+
ASSERT_SCHEMA_EQ(*schema, *kInfoSchema);
465+
ASSERT_EQ(1, batches.size());
466+
ASSERT_EQ(4, batches[0]->num_rows());
467+
}
468+
424469
TEST_F(Sqlite, MetadataGetTableTypes) {
425470
AdbcStatement statement;
426471
std::memset(&statement, 0, sizeof(statement));

java/core/src/main/java/org/apache/arrow/adbc/core/AdbcConnection.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,20 @@ default AdbcStatement deserializePartitionDescriptor(ByteBuffer descriptor) thro
5454
"Connection does not support deserializePartitionDescriptor(ByteBuffer)");
5555
}
5656

57+
AdbcStatement getInfo(int[] infoCodes) throws AdbcException;
58+
59+
default AdbcStatement getInfo(AdbcInfoCode[] infoCodes) throws AdbcException {
60+
int[] codes = new int[infoCodes.length];
61+
for (int i = 0; i < infoCodes.length; i++) {
62+
codes[i] = infoCodes[i].getValue();
63+
}
64+
return getInfo(codes);
65+
}
66+
67+
default AdbcStatement getInfo() throws AdbcException {
68+
return getInfo((int[]) null);
69+
}
70+
5771
/**
5872
* Get a hierarchical view of all catalogs, database schemas, tables, and columns.
5973
*

0 commit comments

Comments
 (0)