Skip to content

Commit c09a698

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

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
@@ -1340,7 +1340,7 @@ AdbcStatusCode SqliteDriverInit(int version, void* raw_driver, struct AdbcError*
13401340
}
13411341

13421342
struct AdbcDriver* driver = (struct AdbcDriver*)raw_driver;
1343-
memset(driver, 0, sizeof(*driver));
1343+
memset(driver, 0, ADBC_DRIVER_1_0_0_SIZE);
13441344
driver->DatabaseInit = SqliteDatabaseInit;
13451345
driver->DatabaseNew = SqliteDatabaseNew;
13461346
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) {
@@ -640,11 +656,19 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name, const char* entrypoint,
640656
AdbcDriverInitFunc init_func;
641657
std::string error_message;
642658

643-
if (version != ADBC_VERSION_1_0_0) {
644-
SetError(error, "Only ADBC 1.0.0 is supported");
645-
return ADBC_STATUS_NOT_IMPLEMENTED;
659+
switch (version) {
660+
case ADBC_VERSION_1_0_0:
661+
case ADBC_VERSION_1_1_0:
662+
break;
663+
default:
664+
SetError(error, "Only ADBC 1.0.0 and 1.1.0 are supported");
665+
return ADBC_STATUS_NOT_IMPLEMENTED;
646666
}
647667

668+
if (!raw_driver) {
669+
SetError(error, "Must provide non-NULL raw_driver");
670+
return ADBC_STATUS_INVALID_ARGUMENT;
671+
}
648672
auto* driver = reinterpret_cast<struct AdbcDriver*>(raw_driver);
649673

650674
if (!entrypoint) {
@@ -771,6 +795,25 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name, const char* entrypoint,
771795

772796
AdbcStatusCode AdbcLoadDriverFromInitFunc(AdbcDriverInitFunc init_func, int version,
773797
void* raw_driver, struct AdbcError* error) {
798+
constexpr std::array<int, 2> kSupportedVersions = {
799+
ADBC_VERSION_1_1_0,
800+
ADBC_VERSION_1_0_0,
801+
};
802+
803+
if (!raw_driver) {
804+
SetError(error, "Must provide non-NULL raw_driver");
805+
return ADBC_STATUS_INVALID_ARGUMENT;
806+
}
807+
808+
switch (version) {
809+
case ADBC_VERSION_1_0_0:
810+
case ADBC_VERSION_1_1_0:
811+
break;
812+
default:
813+
SetError(error, "Only ADBC 1.0.0 and 1.1.0 are supported");
814+
return ADBC_STATUS_NOT_IMPLEMENTED;
815+
}
816+
774817
#define FILL_DEFAULT(DRIVER, STUB) \
775818
if (!DRIVER->STUB) { \
776819
DRIVER->STUB = &STUB; \
@@ -781,12 +824,20 @@ AdbcStatusCode AdbcLoadDriverFromInitFunc(AdbcDriverInitFunc init_func, int vers
781824
return ADBC_STATUS_INTERNAL; \
782825
}
783826

784-
auto result = init_func(version, raw_driver, error);
827+
// Starting from the passed version, try each (older) version in
828+
// succession with the underlying driver until we find one that's
829+
// accepted.
830+
AdbcStatusCode result = ADBC_STATUS_NOT_IMPLEMENTED;
831+
for (const int try_version : kSupportedVersions) {
832+
if (try_version > version) continue;
833+
result = init_func(try_version, raw_driver, error);
834+
if (result != ADBC_STATUS_NOT_IMPLEMENTED) break;
835+
}
785836
if (result != ADBC_STATUS_OK) {
786837
return result;
787838
}
788839

789-
if (version == ADBC_VERSION_1_0_0) {
840+
if (version >= ADBC_VERSION_1_0_0) {
790841
auto* driver = reinterpret_cast<struct AdbcDriver*>(raw_driver);
791842
CHECK_REQUIRED(driver, DatabaseNew);
792843
CHECK_REQUIRED(driver, DatabaseInit);
@@ -816,6 +867,13 @@ AdbcStatusCode AdbcLoadDriverFromInitFunc(AdbcDriverInitFunc init_func, int vers
816867
FILL_DEFAULT(driver, StatementSetSqlQuery);
817868
FILL_DEFAULT(driver, StatementSetSubstraitPlan);
818869
}
870+
if (version >= ADBC_VERSION_1_1_0) {
871+
auto* driver = reinterpret_cast<struct AdbcDriver*>(raw_driver);
872+
FILL_DEFAULT(driver, StatementExecuteSchema);
873+
874+
// Zero out the padding
875+
std::memset(driver->reserved, 0, sizeof(driver->reserved));
876+
}
819877

820878
return ADBC_STATUS_OK;
821879

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
@@ -901,7 +901,7 @@ func {{.Prefix}}DriverInit(version C.int, rawDriver *C.void, err *C.struct_AdbcE
901901
}
902902

903903
driver := (*C.struct_AdbcDriver)(unsafe.Pointer(rawDriver))
904-
C.memset(unsafe.Pointer(driver), 0, C.sizeof_struct_AdbcDriver)
904+
C.memset(unsafe.Pointer(driver), 0, C.ADBC_DRIVER_1_0_0_SIZE)
905905
driver.DatabaseInit = (*[0]byte)(C.{{.Prefix}}DatabaseInit)
906906
driver.DatabaseNew = (*[0]byte)(C.{{.Prefix}}DatabaseNew)
907907
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)