Skip to content

Commit be2e2d0

Browse files
lidavidmzeroshadekou
committed
feat(format): introduce ADBC API revision 1.1.0 (#692)
Fixes #317. --------- Co-authored-by: Matt Topol <zotthewizard@gmail.com> Co-authored-by: Sutou Kouhei <kou@cozmixng.org>
1 parent da33e6c commit be2e2d0

19 files changed

Lines changed: 1050 additions & 37 deletions

File tree

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ repos:
4343
- id: cmake-format
4444
args: [--in-place]
4545
- repo: https://github.com/cpplint/cpplint
46-
rev: 1.6.0
46+
rev: 1.6.1
4747
hooks:
4848
- id: cpplint
4949
args:
5050
# From Arrow's config
51-
- "--filter=-whitespace/comments,-readability/casting,-readability/todo,-readability/alt_tokens,-build/header_guard,-build/c++11,-build/include_order,-build/include_subdir"
51+
- "--filter=-whitespace/comments,-whitespace/indent,-readability/braces,-readability/casting,-readability/todo,-readability/alt_tokens,-build/header_guard,-build/c++11,-build/include_order,-build/include_subdir"
5252
- "--linelength=90"
5353
- "--verbose=2"
5454
- repo: https://github.com/golangci/golangci-lint

adbc.h

Lines changed: 596 additions & 2 deletions
Large diffs are not rendered by default.

c/driver/postgresql/postgresql.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,9 +471,10 @@ extern "C" {
471471
ADBC_EXPORT
472472
AdbcStatusCode AdbcDriverInit(int version, void* raw_driver, struct AdbcError* error) {
473473
if (version != ADBC_VERSION_1_0_0) return ADBC_STATUS_NOT_IMPLEMENTED;
474+
if (!raw_driver) return ADBC_STATUS_INVALID_ARGUMENT;
474475

475476
auto* driver = reinterpret_cast<struct AdbcDriver*>(raw_driver);
476-
std::memset(driver, 0, sizeof(*driver));
477+
std::memset(driver, 0, ADBC_DRIVER_1_0_0_SIZE);
477478
driver->DatabaseInit = PostgresDatabaseInit;
478479
driver->DatabaseNew = PostgresDatabaseNew;
479480
driver->DatabaseRelease = PostgresDatabaseRelease;

c/driver/sqlite/sqlite.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1393,7 +1393,7 @@ AdbcStatusCode SqliteDriverInit(int version, void* raw_driver, struct AdbcError*
13931393
}
13941394

13951395
struct AdbcDriver* driver = (struct AdbcDriver*)raw_driver;
1396-
memset(driver, 0, sizeof(*driver));
1396+
memset(driver, 0, ADBC_DRIVER_1_0_0_SIZE);
13971397
driver->DatabaseInit = SqliteDatabaseInit;
13981398
driver->DatabaseNew = SqliteDatabaseNew;
13991399
driver->DatabaseRelease = SqliteDatabaseRelease;

c/driver_manager/adbc_driver_manager.cc

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <adbc.h>
2020

2121
#include <algorithm>
22+
#include <array>
2223
#include <cstring>
2324
#include <string>
2425
#include <unordered_map>
@@ -191,6 +192,12 @@ AdbcStatusCode StatementExecutePartitions(struct AdbcStatement* statement,
191192
return ADBC_STATUS_NOT_IMPLEMENTED;
192193
}
193194

195+
AdbcStatusCode StatementExecuteSchema(struct AdbcStatement* statement,
196+
struct ArrowSchema* schema,
197+
struct AdbcError* error) {
198+
return ADBC_STATUS_NOT_IMPLEMENTED;
199+
}
200+
194201
AdbcStatusCode StatementGetParameterSchema(struct AdbcStatement* statement,
195202
struct ArrowSchema* schema,
196203
struct AdbcError* error) {
@@ -540,6 +547,15 @@ AdbcStatusCode AdbcStatementExecuteQuery(struct AdbcStatement* statement,
540547
error);
541548
}
542549

550+
AdbcStatusCode AdbcStatementExecuteSchema(struct AdbcStatement* statement,
551+
struct ArrowSchema* schema,
552+
struct AdbcError* error) {
553+
if (!statement->private_driver) {
554+
return ADBC_STATUS_INVALID_STATE;
555+
}
556+
return statement->private_driver->StatementExecuteSchema(statement, schema, error);
557+
}
558+
543559
AdbcStatusCode AdbcStatementGetParameterSchema(struct AdbcStatement* statement,
544560
struct ArrowSchema* schema,
545561
struct AdbcError* error) {
@@ -636,11 +652,19 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name, const char* entrypoint,
636652
AdbcDriverInitFunc init_func;
637653
std::string error_message;
638654

639-
if (version != ADBC_VERSION_1_0_0) {
640-
SetError(error, "Only ADBC 1.0.0 is supported");
641-
return ADBC_STATUS_NOT_IMPLEMENTED;
655+
switch (version) {
656+
case ADBC_VERSION_1_0_0:
657+
case ADBC_VERSION_1_1_0:
658+
break;
659+
default:
660+
SetError(error, "Only ADBC 1.0.0 and 1.1.0 are supported");
661+
return ADBC_STATUS_NOT_IMPLEMENTED;
642662
}
643663

664+
if (!raw_driver) {
665+
SetError(error, "Must provide non-NULL raw_driver");
666+
return ADBC_STATUS_INVALID_ARGUMENT;
667+
}
644668
auto* driver = reinterpret_cast<struct AdbcDriver*>(raw_driver);
645669

646670
if (!entrypoint) {
@@ -767,6 +791,25 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name, const char* entrypoint,
767791

768792
AdbcStatusCode AdbcLoadDriverFromInitFunc(AdbcDriverInitFunc init_func, int version,
769793
void* raw_driver, struct AdbcError* error) {
794+
constexpr std::array<int, 2> kSupportedVersions = {
795+
ADBC_VERSION_1_1_0,
796+
ADBC_VERSION_1_0_0,
797+
};
798+
799+
if (!raw_driver) {
800+
SetError(error, "Must provide non-NULL raw_driver");
801+
return ADBC_STATUS_INVALID_ARGUMENT;
802+
}
803+
804+
switch (version) {
805+
case ADBC_VERSION_1_0_0:
806+
case ADBC_VERSION_1_1_0:
807+
break;
808+
default:
809+
SetError(error, "Only ADBC 1.0.0 and 1.1.0 are supported");
810+
return ADBC_STATUS_NOT_IMPLEMENTED;
811+
}
812+
770813
#define FILL_DEFAULT(DRIVER, STUB) \
771814
if (!DRIVER->STUB) { \
772815
DRIVER->STUB = &STUB; \
@@ -777,12 +820,20 @@ AdbcStatusCode AdbcLoadDriverFromInitFunc(AdbcDriverInitFunc init_func, int vers
777820
return ADBC_STATUS_INTERNAL; \
778821
}
779822

780-
auto result = init_func(version, raw_driver, error);
823+
// Starting from the passed version, try each (older) version in
824+
// succession with the underlying driver until we find one that's
825+
// accepted.
826+
AdbcStatusCode result = ADBC_STATUS_NOT_IMPLEMENTED;
827+
for (const int try_version : kSupportedVersions) {
828+
if (try_version > version) continue;
829+
result = init_func(try_version, raw_driver, error);
830+
if (result != ADBC_STATUS_NOT_IMPLEMENTED) break;
831+
}
781832
if (result != ADBC_STATUS_OK) {
782833
return result;
783834
}
784835

785-
if (version == ADBC_VERSION_1_0_0) {
836+
if (version >= ADBC_VERSION_1_0_0) {
786837
auto* driver = reinterpret_cast<struct AdbcDriver*>(raw_driver);
787838
CHECK_REQUIRED(driver, DatabaseNew);
788839
CHECK_REQUIRED(driver, DatabaseInit);
@@ -812,6 +863,13 @@ AdbcStatusCode AdbcLoadDriverFromInitFunc(AdbcDriverInitFunc init_func, int vers
812863
FILL_DEFAULT(driver, StatementSetSqlQuery);
813864
FILL_DEFAULT(driver, StatementSetSubstraitPlan);
814865
}
866+
if (version >= ADBC_VERSION_1_1_0) {
867+
auto* driver = reinterpret_cast<struct AdbcDriver*>(raw_driver);
868+
FILL_DEFAULT(driver, StatementExecuteSchema);
869+
870+
// Zero out the padding
871+
std::memset(driver->reserved, 0, sizeof(driver->reserved));
872+
}
815873

816874
return ADBC_STATUS_OK;
817875

c/driver_manager/adbc_driver_manager_test.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ namespace adbc {
3434
using adbc_validation::IsOkStatus;
3535
using adbc_validation::IsStatus;
3636

37+
TEST(Adbc, AdbcDriverSize) { ASSERT_EQ(sizeof(AdbcDriver), 96 * sizeof(void*)); }
38+
3739
class DriverManager : public ::testing::Test {
3840
public:
3941
void SetUp() override {
@@ -157,6 +159,38 @@ TEST_F(DriverManager, MultiDriverTest) {
157159
error->release(&error.value);
158160
}
159161

162+
class AdbcVersion : public ::testing::Test {
163+
public:
164+
void SetUp() override {
165+
std::memset(&driver, 0, sizeof(driver));
166+
std::memset(&error, 0, sizeof(error));
167+
}
168+
169+
void TearDown() override {
170+
if (error.release) {
171+
error.release(&error);
172+
}
173+
174+
if (driver.release) {
175+
ASSERT_THAT(driver.release(&driver, &error), IsOkStatus(&error));
176+
ASSERT_EQ(driver.private_data, nullptr);
177+
ASSERT_EQ(driver.private_manager, nullptr);
178+
}
179+
}
180+
181+
protected:
182+
struct AdbcDriver driver = {};
183+
struct AdbcError error = {};
184+
};
185+
186+
// TODO: set up a dummy driver to test behavior more deterministically
187+
188+
TEST_F(AdbcVersion, ForwardsCompatible) {
189+
ASSERT_THAT(
190+
AdbcLoadDriver("adbc_driver_sqlite", nullptr, ADBC_VERSION_1_1_0, &driver, &error),
191+
IsOkStatus(&error));
192+
}
193+
160194
class SqliteQuirks : public adbc_validation::DriverQuirks {
161195
public:
162196
AdbcStatusCode SetupDatabase(struct AdbcDatabase* database,

go/adbc/adbc.go

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -142,20 +142,35 @@ const (
142142
StatusUnauthorized // Unauthorized
143143
)
144144

145+
const (
146+
AdbcVersion1_0_0 int64 = 1_000_000
147+
AdbcVersion1_1_0 int64 = 1_001_000
148+
)
149+
145150
// Canonical option values
146151
const (
147-
OptionValueEnabled = "true"
148-
OptionValueDisabled = "false"
149-
OptionKeyAutoCommit = "adbc.connection.autocommit"
150-
OptionKeyIngestTargetTable = "adbc.ingest.target_table"
151-
OptionKeyIngestMode = "adbc.ingest.mode"
152-
OptionKeyIsolationLevel = "adbc.connection.transaction.isolation_level"
153-
OptionKeyReadOnly = "adbc.connection.readonly"
154-
OptionValueIngestModeCreate = "adbc.ingest.mode.create"
155-
OptionValueIngestModeAppend = "adbc.ingest.mode.append"
156-
OptionKeyURI = "uri"
157-
OptionKeyUsername = "username"
158-
OptionKeyPassword = "password"
152+
OptionValueEnabled = "true"
153+
OptionValueDisabled = "false"
154+
OptionKeyAutoCommit = "adbc.connection.autocommit"
155+
// The current catalog.
156+
OptionKeyCurrentCatalog = "adbc.connection.catalog"
157+
// The current schema.
158+
OptionKeyCurrentDbSchema = "adbc.connection.db_schema"
159+
// Make ExecutePartitions nonblocking.
160+
OptionKeyIncremental = "adbc.statement.exec.incremental"
161+
// Get the progress
162+
OptionKeyProgress = "adbc.statement.exec.progress"
163+
OptionKeyIngestTargetTable = "adbc.ingest.target_table"
164+
OptionKeyIngestMode = "adbc.ingest.mode"
165+
OptionKeyIsolationLevel = "adbc.connection.transaction.isolation_level"
166+
OptionKeyReadOnly = "adbc.connection.readonly"
167+
OptionValueIngestModeCreate = "adbc.ingest.mode.create"
168+
OptionValueIngestModeAppend = "adbc.ingest.mode.append"
169+
OptionValueIngestModeReplace = "adbc.ingest.mode.replace"
170+
OptionValueIngestModeCreateAppend = "adbc.ingest.mode.create_append"
171+
OptionKeyURI = "uri"
172+
OptionKeyUsername = "username"
173+
OptionKeyPassword = "password"
159174
)
160175

161176
type OptionIsolationLevel string
@@ -170,6 +185,11 @@ const (
170185
LevelLinearizable OptionIsolationLevel = "adbc.connection.transaction.isolation.linearizable"
171186
)
172187

188+
// Canonical property values
189+
const (
190+
PropertyProgress = "adbc.statement.exec.progress"
191+
)
192+
173193
// Driver is the entry point for the interface. It is similar to
174194
// database/sql.Driver taking a map of keys and values as options
175195
// to initialize a Connection to the database. Any common connection
@@ -212,6 +232,8 @@ const (
212232
InfoDriverVersion InfoCode = 101 // DriverVersion
213233
// The driver Arrow library version (type: utf8)
214234
InfoDriverArrowVersion InfoCode = 102 // DriverArrowVersion
235+
// The driver ADBC API version (type: int64)
236+
InfoDriverADBCVersion InfoCode = 103 // DriverADBCVersion
215237
)
216238

217239
type ObjectDepth int
@@ -275,6 +297,10 @@ type Connection interface {
275297
// codes are defined as constants. Codes [0, 10_000) are reserved
276298
// for ADBC usage. Drivers/vendors will ignore requests for unrecognized
277299
// codes (the row will be omitted from the result).
300+
//
301+
// Since ADBC 1.1.0: the range [500, 1_000) is reserved for "XDBC"
302+
// information, which is the same metadata provided by the same info
303+
// code range in the Arrow Flight SQL GetSqlInfo RPC.
278304
GetInfo(ctx context.Context, infoCodes []InfoCode) (array.RecordReader, error)
279305

280306
// GetObjects gets a hierarchical view of all catalogs, database schemas,
@@ -470,6 +496,9 @@ type Statement interface {
470496
// of rows affected if known, otherwise it will be -1.
471497
//
472498
// This invalidates any prior result sets on this statement.
499+
//
500+
// Since ADBC 1.1.0: releasing the returned RecordReader without
501+
// consuming it fully is equivalent to calling AdbcStatementCancel.
473502
ExecuteQuery(context.Context) (array.RecordReader, int64, error)
474503

475504
// ExecuteUpdate executes a statement that does not generate a result
@@ -534,5 +563,45 @@ type Statement interface {
534563
//
535564
// If the driver does not support partitioned results, this will return
536565
// an error with a StatusNotImplemented code.
566+
//
567+
// When OptionKeyIncremental is set, this should be called
568+
// repeatedly until receiving an empty Partitions.
537569
ExecutePartitions(context.Context) (*arrow.Schema, Partitions, int64, error)
538570
}
571+
572+
// StatementCancel is a Statement that also supports Cancel.
573+
//
574+
// Since ADBC API revision 1.1.0.
575+
type StatementCancel interface {
576+
// Cancel stops execution of an in-progress query.
577+
//
578+
// This can be called during ExecuteQuery (or similar), or while
579+
// consuming a RecordReader returned from such. Calling this
580+
// function should make the other functions return an error with a
581+
// StatusCancelled code.
582+
//
583+
// This must always be thread-safe (other operations are not
584+
// necessarily thread-safe).
585+
Cancel() error
586+
}
587+
588+
// StatementExecuteSchema is a Statement that also supports ExecuteSchema.
589+
//
590+
// Since ADBC API revision 1.1.0.
591+
type StatementExecuteSchema interface {
592+
// ExecuteSchema gets the schema of the result set of a query without executing it.
593+
ExecuteSchema(context.Context) (*arrow.Schema, error)
594+
}
595+
596+
// GetSetOptions is a PostInitOptions that also supports getting and setting property values of different types.
597+
//
598+
// Since ADBC API revision 1.1.0.
599+
type GetSetOptions interface {
600+
PostInitOptions
601+
602+
SetOption(key, value string) error
603+
SetOptionInt(key, value int64) error
604+
SetOptionDouble(key, value float64) error
605+
GetOptionInt(key string) (int64, error)
606+
GetOptionDouble(key string) (float64, error)
607+
}

go/adbc/infocode_string.go

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go/adbc/pkg/_tmpl/driver.go.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,7 @@ func {{.Prefix}}DriverInit(version C.int, rawDriver *C.void, err *C.struct_AdbcE
915915
}
916916

917917
driver := (*C.struct_AdbcDriver)(unsafe.Pointer(rawDriver))
918-
C.memset(unsafe.Pointer(driver), 0, C.sizeof_struct_AdbcDriver)
918+
C.memset(unsafe.Pointer(driver), 0, C.ADBC_DRIVER_1_0_0_SIZE)
919919
driver.DatabaseInit = (*[0]byte)(C.{{.Prefix}}DatabaseInit)
920920
driver.DatabaseNew = (*[0]byte)(C.{{.Prefix}}DatabaseNew)
921921
driver.DatabaseRelease = (*[0]byte)(C.{{.Prefix}}DatabaseRelease)

go/adbc/pkg/flightsql/driver.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)