You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by li...@apache.org on 2023/06/27 17:30:30 UTC
[arrow-adbc] 01/04: feat(format): introduce ADBC API revision 1.1.0 (#692)
This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch spec-1.1.0
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git
commit 94b35a73473b2cab7896516ab55a0bb34cdb61f0
Author: David Li <li...@gmail.com>
AuthorDate: Tue Jun 6 10:11:27 2023 -0400
feat(format): introduce ADBC API revision 1.1.0 (#692)
Fixes #317.
---------
Co-authored-by: Matt Topol <zo...@gmail.com>
Co-authored-by: Sutou Kouhei <ko...@cozmixng.org>
---
.pre-commit-config.yaml | 4 +-
adbc.h | 598 ++++++++++++++++++++-
c/driver/postgresql/postgresql.cc | 3 +-
c/driver/sqlite/sqlite.c | 2 +-
c/driver_manager/adbc_driver_manager.cc | 68 ++-
c/driver_manager/adbc_driver_manager_test.cc | 34 ++
go/adbc/adbc.go | 93 +++-
go/adbc/infocode_string.go | 7 +-
go/adbc/pkg/_tmpl/driver.go.tmpl | 2 +-
go/adbc/pkg/flightsql/driver.go | 2 +-
go/adbc/pkg/snowflake/driver.go | 2 +-
.../org/apache/arrow/adbc/core/AdbcConnection.java | 38 +-
.../org/apache/arrow/adbc/core/AdbcDatabase.java | 2 +-
.../org/apache/arrow/adbc/core/AdbcDriver.java | 35 +-
.../org/apache/arrow/adbc/core/AdbcInfoCode.java | 17 +-
.../org/apache/arrow/adbc/core/AdbcOptionKey.java | 69 +++
.../core/{AdbcDriver.java => AdbcOptions.java} | 32 +-
.../org/apache/arrow/adbc/core/AdbcStatement.java | 51 +-
.../org/apache/arrow/adbc/core/BulkIngestMode.java | 15 +-
19 files changed, 1026 insertions(+), 48 deletions(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 82df862c..188b069b 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -43,12 +43,12 @@ repos:
- id: cmake-format
args: [--in-place]
- repo: https://github.com/cpplint/cpplint
- rev: 1.6.0
+ rev: 1.6.1
hooks:
- id: cpplint
args:
# From Arrow's config
- - "--filter=-whitespace/comments,-readability/casting,-readability/todo,-readability/alt_tokens,-build/header_guard,-build/c++11,-build/include_order,-build/include_subdir"
+ - "--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"
- "--linelength=90"
- "--verbose=2"
- repo: https://github.com/golangci/golangci-lint
diff --git a/adbc.h b/adbc.h
index 154e8812..756288da 100644
--- a/adbc.h
+++ b/adbc.h
@@ -279,6 +279,14 @@ struct ADBC_EXPORT AdbcError {
/// point to an AdbcDriver.
#define ADBC_VERSION_1_0_0 1000000
+/// \brief ADBC revision 1.1.0.
+///
+/// When passed to an AdbcDriverInitFunc(), the driver parameter must
+/// point to an AdbcDriver.
+///
+/// \addtogroup adbc-1.1.0
+#define ADBC_VERSION_1_1_0 1001000
+
/// \brief Canonical option value for enabling an option.
///
/// For use as the value in SetOption calls.
@@ -288,6 +296,37 @@ struct ADBC_EXPORT AdbcError {
/// For use as the value in SetOption calls.
#define ADBC_OPTION_VALUE_DISABLED "false"
+/// \brief Canonical option name for URIs.
+///
+/// Should be used as the expected option name to specify a URI for
+/// any ADBC driver.
+///
+/// The type is char*.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+#define ADBC_OPTION_URI "uri"
+/// \brief Canonical option name for usernames.
+///
+/// Should be used as the expected option name to specify a username
+/// to a driver for authentication.
+///
+/// The type is char*.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+#define ADBC_OPTION_USERNAME "username"
+/// \brief Canonical option name for passwords.
+///
+/// Should be used as the expected option name to specify a password
+/// for authentication to a driver.
+///
+/// The type is char*.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+#define ADBC_OPTION_PASSWORD "password"
+
/// \brief The database vendor/product name (e.g. the server name).
/// (type: utf8).
///
@@ -315,6 +354,16 @@ struct ADBC_EXPORT AdbcError {
///
/// \see AdbcConnectionGetInfo
#define ADBC_INFO_DRIVER_ARROW_VERSION 102
+/// \brief The driver ADBC API version (type: int64).
+///
+/// The value should be one of the ADBC_VERSION constants.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \see AdbcConnectionGetInfo
+/// \see ADBC_VERSION_1_0_0
+/// \see ADBC_VERSION_1_1_0
+#define ADBC_INFO_DRIVER_ADBC_VERSION 103
/// \brief Return metadata on catalogs, schemas, tables, and columns.
///
@@ -340,15 +389,68 @@ struct ADBC_EXPORT AdbcError {
/// \brief The name of the canonical option for whether autocommit is
/// enabled.
///
+/// The type is char*.
+///
/// \see AdbcConnectionSetOption
#define ADBC_CONNECTION_OPTION_AUTOCOMMIT "adbc.connection.autocommit"
/// \brief The name of the canonical option for whether the current
/// connection should be restricted to being read-only.
///
+/// The type is char*.
+///
/// \see AdbcConnectionSetOption
#define ADBC_CONNECTION_OPTION_READ_ONLY "adbc.connection.readonly"
+/// \brief The name of the canonical option for the current catalog.
+///
+/// The type is char*.
+///
+/// \see AdbcConnectionGetOption
+/// \see AdbcConnectionSetOption
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+#define ADBC_CONNECTION_OPTION_CURRENT_CATALOG "adbc.connection.catalog"
+
+/// \brief The name of the canonical option for the current schema.
+///
+/// The type is char*.
+///
+/// \see AdbcConnectionGetOption
+/// \see AdbcConnectionSetOption
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+#define ADBC_CONNECTION_OPTION_CURRENT_DB_SCHEMA "adbc.connection.db_schema"
+
+/// \brief The name of the canonical option for making query execution
+/// nonblocking.
+///
+/// When enabled, AdbcStatementExecutePartitions will return
+/// partitions as soon as they are available, instead of returning
+/// them all at the end. When there are no more to return, it will
+/// return an empty set of partitions. AdbcStatementExecuteQuery and
+/// AdbcStatementExecuteSchema are not affected.
+///
+/// The default is ADBC_OPTION_VALUE_DISABLED.
+///
+/// The type is char*.
+///
+/// \see AdbcStatementSetOption
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+#define ADBC_STATEMENT_OPTION_INCREMENTAL "adbc.statement.exec.incremental"
+
+/// \brief The name of the option for getting the progress of a query.
+///
+/// Progress is a value in [0.0, 1.0].
+///
+/// The type is double.
+///
+/// \see AdbcStatementGetOptionDouble
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+#define ADBC_STATEMENT_OPTION_PROGRESS "adbc.statement.exec.progress"
+
/// \brief The name of the canonical option for setting the isolation
/// level of a transaction.
///
@@ -357,6 +459,8 @@ struct ADBC_EXPORT AdbcError {
/// isolation level is not supported by a driver, it should return an
/// appropriate error.
///
+/// The type is char*.
+///
/// \see AdbcConnectionSetOption
#define ADBC_CONNECTION_OPTION_ISOLATION_LEVEL \
"adbc.connection.transaction.isolation_level"
@@ -449,8 +553,12 @@ struct ADBC_EXPORT AdbcError {
/// exist. If the table exists but has a different schema,
/// ADBC_STATUS_ALREADY_EXISTS should be raised. Else, data should be
/// appended to the target table.
+///
+/// The type is char*.
#define ADBC_INGEST_OPTION_TARGET_TABLE "adbc.ingest.target_table"
/// \brief Whether to create (the default) or append.
+///
+/// The type is char*.
#define ADBC_INGEST_OPTION_MODE "adbc.ingest.mode"
/// \brief Create the table and insert data; error if the table exists.
#define ADBC_INGEST_OPTION_MODE_CREATE "adbc.ingest.mode.create"
@@ -458,6 +566,17 @@ struct ADBC_EXPORT AdbcError {
/// table does not exist (ADBC_STATUS_NOT_FOUND) or does not match
/// the schema of the data to append (ADBC_STATUS_ALREADY_EXISTS).
#define ADBC_INGEST_OPTION_MODE_APPEND "adbc.ingest.mode.append"
+/// \brief Create the table and insert data; drop the original table
+/// if it already exists.
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+#define ADBC_INGEST_OPTION_MODE_REPLACE "adbc.ingest.mode.replace"
+/// \brief Insert data; create the table if it does not exist, or
+/// error if the table exists, but the schema does not match the
+/// schema of the data to append (ADBC_STATUS_ALREADY_EXISTS).
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+#define ADBC_INGEST_OPTION_MODE_CREATE_APPEND "adbc.ingest.mode.create_append"
/// @}
@@ -667,8 +786,89 @@ struct ADBC_EXPORT AdbcDriver {
struct AdbcError*);
AdbcStatusCode (*StatementSetSubstraitPlan)(struct AdbcStatement*, const uint8_t*,
size_t, struct AdbcError*);
+
+ /// \defgroup adbc-1.1.0 ADBC API Revision 1.1.0
+ ///
+ /// Functions added in ADBC 1.1.0. For backwards compatibility,
+ /// these members must not be accessed unless the version passed to
+ /// the AdbcDriverInitFunc is greater than or equal to
+ /// ADBC_VERSION_1_1_0.
+ ///
+ /// For a 1.0.0 driver being loaded by a 1.1.0 driver manager: the
+ /// 1.1.0 manager will allocate the new, expanded AdbcDriver struct
+ /// and attempt to have the driver initialize it with
+ /// ADBC_VERSION_1_1_0. This must return an error, after which the
+ /// driver will try again with ADBC_VERSION_1_0_0. The driver must
+ /// not access the new fields.
+ ///
+ /// For a 1.1.0 driver being loaded by a 1.0.0 driver manager: the
+ /// 1.0.0 manager will allocate the old AdbcDriver struct and
+ /// attempt to have the driver initialize it with
+ /// ADBC_VERSION_1_0_0. The driver must not access the new fields,
+ /// and should initialize the old fields.
+ ///
+ /// @{
+
+ AdbcStatusCode (*DatabaseGetOption)(struct AdbcDatabase*, const char*, const char**,
+ struct AdbcError*);
+ AdbcStatusCode (*DatabaseGetOptionInt)(struct AdbcDatabase*, const char*, int64_t*,
+ struct AdbcError*);
+ AdbcStatusCode (*DatabaseGetOptionDouble)(struct AdbcDatabase*, const char*, double*,
+ struct AdbcError*);
+ AdbcStatusCode (*DatabaseSetOptionInt)(struct AdbcDatabase*, const char*, int64_t,
+ struct AdbcError*);
+ AdbcStatusCode (*DatabaseSetOptionDouble)(struct AdbcDatabase*, const char*, double,
+ struct AdbcError*);
+
+ AdbcStatusCode (*ConnectionGetOption)(struct AdbcConnection*, const char*, const char**,
+ struct AdbcError*);
+ AdbcStatusCode (*ConnectionGetOptionInt)(struct AdbcConnection*, const char*, int64_t*,
+ struct AdbcError*);
+ AdbcStatusCode (*ConnectionGetOptionDouble)(struct AdbcConnection*, const char*,
+ double*, struct AdbcError*);
+ AdbcStatusCode (*ConnectionSetOptionInt)(struct AdbcConnection*, const char*, int64_t,
+ struct AdbcError*);
+ AdbcStatusCode (*ConnectionSetOptionDouble)(struct AdbcConnection*, const char*, double,
+ struct AdbcError*);
+
+ AdbcStatusCode (*StatementCancel)(struct AdbcStatement*, struct AdbcError*);
+ AdbcStatusCode (*StatementExecuteSchema)(struct AdbcStatement*, struct ArrowSchema*,
+ struct AdbcError*);
+ AdbcStatusCode (*StatementGetOption)(struct AdbcStatement*, const char*, const char**,
+ struct AdbcError*);
+ AdbcStatusCode (*StatementGetOptionInt)(struct AdbcStatement*, const char*, int64_t*,
+ struct AdbcError*);
+ AdbcStatusCode (*StatementGetOptionDouble)(struct AdbcStatement*, const char*, double*,
+ struct AdbcError*);
+ AdbcStatusCode (*StatementSetOptionInt)(struct AdbcStatement*, const char*, int64_t,
+ struct AdbcError*);
+ AdbcStatusCode (*StatementSetOptionDouble)(struct AdbcStatement*, const char*, double,
+ struct AdbcError*);
+
+ /// Pad the struct to have 96 pointers. Space reserved for future growth.
+ void* reserved[50];
+
+ /// @}
};
+/// \brief The size of the AdbcDriver structure in ADBC 1.0.0.
+/// Drivers written for ADBC 1.1.0 and later should never touch more
+/// than this portion of an AdbcDriver struct when given
+/// ADBC_VERSION_1_0_0.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+#define ADBC_DRIVER_1_0_0_SIZE (offsetof(struct AdbcDriver, DatabaseGetOption))
+
+/// \brief The size of the AdbcDriver structure in ADBC 1.1.0.
+/// Drivers written for ADBC 1.1.0 and later should never touch more
+/// than this portion of an AdbcDriver struct when given
+/// ADBC_VERSION_1_1_0.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+#define ADBC_DRIVER_1_1_0_SIZE (sizeof(struct AdbcDriver))
+
/// @}
/// \addtogroup adbc-database
@@ -684,16 +884,121 @@ struct ADBC_EXPORT AdbcDriver {
ADBC_EXPORT
AdbcStatusCode AdbcDatabaseNew(struct AdbcDatabase* database, struct AdbcError* error);
+/// \brief Get a string option of the database.
+///
+/// This must always be thread-safe (other operations are not).
+///
+/// The returned option value is only valid until the next call to
+/// GetOption or Release.
+///
+/// For standard options, drivers must always support getting the
+/// option value (if they support getting option values at all) via
+/// the type specified in the option. (For example, an option set via
+/// SetOptionDouble must be retrievable via GetOptionDouble.) Drivers
+/// may also support getting a converted option value via other
+/// getters if needed. (For example, getting the string
+/// representation of a double option.)
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] database The database.
+/// \param[in] key The option to get.
+/// \param[out] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_FOUND if the option is not recognized.
+AdbcStatusCode AdbcDatabaseGetOption(struct AdbcDatabase* database, const char* key,
+ const char** value, struct AdbcError* error);
+
+/// \brief Get an integer option of the database.
+///
+/// This must always be thread-safe (other operations are not).
+///
+/// For standard options, drivers must always support getting the
+/// option value (if they support getting option values at all) via
+/// the type specified in the option. (For example, an option set via
+/// SetOptionDouble must be retrievable via GetOptionDouble.) Drivers
+/// may also support getting a converted option value via other
+/// getters if needed. (For example, getting the integer
+/// representation of a double option.)
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] database The database.
+/// \param[in] key The option to get.
+/// \param[out] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_FOUND if the option is not recognized.
+AdbcStatusCode AdbcDatabaseGetOptionInt(struct AdbcDatabase* database, const char* key,
+ int64_t* value, struct AdbcError* error);
+
+/// \brief Get a double option of the database.
+///
+/// This must always be thread-safe (other operations are not).
+///
+/// For standard options, drivers must always support getting the
+/// option value (if they support getting option values at all) via
+/// the type specified in the option. (For example, an option set via
+/// SetOptionDouble must be retrievable via GetOptionDouble.) Drivers
+/// may also support getting a converted option value via other
+/// getters if needed. (For example, getting the double
+/// representation of an integer option.)
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] database The database.
+/// \param[in] key The option to get.
+/// \param[out] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_FOUND if the option is not recognized.
+AdbcStatusCode AdbcDatabaseGetOptionDouble(struct AdbcDatabase* database, const char* key,
+ double* value, struct AdbcError* error);
+
/// \brief Set a char* option.
///
/// Options may be set before AdbcDatabaseInit. Some drivers may
/// support setting options after initialization as well.
///
+/// \param[in] database The database.
+/// \param[in] key The option to set.
+/// \param[in] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
/// \return ADBC_STATUS_NOT_IMPLEMENTED if the option is not recognized
ADBC_EXPORT
AdbcStatusCode AdbcDatabaseSetOption(struct AdbcDatabase* database, const char* key,
const char* value, struct AdbcError* error);
+/// \brief Set an integer option on a database.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] database The database.
+/// \param[in] key The option to set.
+/// \param[in] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_IMPLEMENTED if the option is not recognized
+ADBC_EXPORT
+AdbcStatusCode AdbcDatabaseSetOptionInt(struct AdbcDatabase* database, const char* key,
+ int64_t value, struct AdbcError* error);
+
+/// \brief Set a double option on a database.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] database The database.
+/// \param[in] key The option to set.
+/// \param[in] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_IMPLEMENTED if the option is not recognized
+ADBC_EXPORT
+AdbcStatusCode AdbcDatabaseSetOptionDouble(struct AdbcDatabase* database, const char* key,
+ double value, struct AdbcError* error);
+
/// \brief Finish setting options and initialize the database.
///
/// Some drivers may support setting options after initialization
@@ -730,11 +1035,52 @@ AdbcStatusCode AdbcConnectionNew(struct AdbcConnection* connection,
/// Options may be set before AdbcConnectionInit. Some drivers may
/// support setting options after initialization as well.
///
+/// \param[in] connection The database connection.
+/// \param[in] key The option to set.
+/// \param[in] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
/// \return ADBC_STATUS_NOT_IMPLEMENTED if the option is not recognized
ADBC_EXPORT
AdbcStatusCode AdbcConnectionSetOption(struct AdbcConnection* connection, const char* key,
const char* value, struct AdbcError* error);
+/// \brief Set an integer option.
+///
+/// Options may be set before AdbcConnectionInit. Some drivers may
+/// support setting options after initialization as well.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] connection The database connection.
+/// \param[in] key The option to set.
+/// \param[in] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_IMPLEMENTED if the option is not recognized
+ADBC_EXPORT
+AdbcStatusCode AdbcConnectionSetOptionInt(struct AdbcConnection* connection,
+ const char* key, int64_t value,
+ struct AdbcError* error);
+
+/// \brief Set a double option.
+///
+/// Options may be set before AdbcConnectionInit. Some drivers may
+/// support setting options after initialization as well.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] connection The database connection.
+/// \param[in] key The option to set.
+/// \param[in] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_IMPLEMENTED if the option is not recognized
+ADBC_EXPORT
+AdbcStatusCode AdbcConnectionSetOptionDouble(struct AdbcConnection* connection,
+ const char* key, double value,
+ struct AdbcError* error);
+
/// \brief Finish setting options and initialize the connection.
///
/// Some drivers may support setting options after initialization
@@ -765,6 +1111,8 @@ AdbcStatusCode AdbcConnectionRelease(struct AdbcConnection* connection,
/// concurrent active statements and it must execute a SQL query
/// internally in order to implement the metadata function).
///
+/// This AdbcConnection must outlive the returned ArrowArrayStream.
+///
/// Some functions accept "search pattern" arguments, which are
/// strings that can contain the special character "%" to match zero
/// or more characters, or "_" to match exactly one character. (See
@@ -799,6 +1147,10 @@ AdbcStatusCode AdbcConnectionRelease(struct AdbcConnection* connection,
/// for ADBC usage. Drivers/vendors will ignore requests for
/// unrecognized codes (the row will be omitted from the result).
///
+/// Since ADBC 1.1.0: the range [500, 1_000) is reserved for "XDBC"
+/// information, which is the same metadata provided by the same info
+/// code range in the Arrow Flight SQL GetSqlInfo RPC.
+///
/// \param[in] connection The connection to query.
/// \param[in] info_codes A list of metadata codes to fetch, or NULL
/// to fetch all.
@@ -891,6 +1243,8 @@ AdbcStatusCode AdbcConnectionGetInfo(struct AdbcConnection* connection,
/// | fk_table | utf8 not null |
/// | fk_column_name | utf8 not null |
///
+/// This AdbcConnection must outlive the returned ArrowArrayStream.
+///
/// \param[in] connection The database connection.
/// \param[in] depth The level of nesting to display. If 0, display
/// all levels. If 1, display only catalogs (i.e. catalog_schemas
@@ -922,6 +1276,80 @@ AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int d
struct ArrowArrayStream* out,
struct AdbcError* error);
+/// \brief Get a string option of the connection.
+///
+/// This must always be thread-safe (other operations are not).
+///
+/// The returned option value is only valid until the next call to
+/// GetOption or Release.
+///
+/// For standard options, drivers must always support getting the
+/// option value (if they support getting option values at all) via
+/// the type specified in the option. (For example, an option set via
+/// SetOptionDouble must be retrievable via GetOptionDouble.) Drivers
+/// may also support getting a converted option value via other
+/// getters if needed. (For example, getting the string
+/// representation of a double option.)
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] connection The database connection.
+/// \param[in] key The option to get.
+/// \param[out] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_FOUND if the option is not recognized.
+AdbcStatusCode AdbcConnectionGetOption(struct AdbcConnection* connection, const char* key,
+ const char** value, struct AdbcError* error);
+
+/// \brief Get an integer option of the connection.
+///
+/// This must always be thread-safe (other operations are not).
+///
+/// For standard options, drivers must always support getting the
+/// option value (if they support getting option values at all) via
+/// the type specified in the option. (For example, an option set via
+/// SetOptionDouble must be retrievable via GetOptionDouble.) Drivers
+/// may also support getting a converted option value via other
+/// getters if needed. (For example, getting the string
+/// representation of a double option.)
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] connection The database connection.
+/// \param[in] key The option to get.
+/// \param[out] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_FOUND if the option is not recognized.
+AdbcStatusCode AdbcConnectionGetOptionInt(struct AdbcConnection* connection,
+ const char* key, int64_t* value,
+ struct AdbcError* error);
+
+/// \brief Get a double option of the connection.
+///
+/// This must always be thread-safe (other operations are not).
+///
+/// For standard options, drivers must always support getting the
+/// option value (if they support getting option values at all) via
+/// the type specified in the option. (For example, an option set via
+/// SetOptionDouble must be retrievable via GetOptionDouble.) Drivers
+/// may also support getting a converted option value via other
+/// getters if needed. (For example, getting the string
+/// representation of a double option.)
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] connection The database connection.
+/// \param[in] key The option to get.
+/// \param[out] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_FOUND if the option is not recognized.
+AdbcStatusCode AdbcConnectionGetOptionDouble(struct AdbcConnection* connection,
+ const char* key, double* value,
+ struct AdbcError* error);
+
/// \brief Get the Arrow schema of a table.
///
/// \param[in] connection The database connection.
@@ -945,6 +1373,8 @@ AdbcStatusCode AdbcConnectionGetTableSchema(struct AdbcConnection* connection,
/// ---------------|--------------
/// table_type | utf8 not null
///
+/// This AdbcConnection must outlive the returned ArrowArrayStream.
+///
/// \param[in] connection The database connection.
/// \param[out] out The result set.
/// \param[out] error Error details, if an error occurs.
@@ -973,6 +1403,8 @@ AdbcStatusCode AdbcConnectionGetTableTypes(struct AdbcConnection* connection,
///
/// A partition can be retrieved from AdbcPartitions.
///
+/// This AdbcConnection must outlive the returned ArrowArrayStream.
+///
/// \param[in] connection The connection to use. This does not have
/// to be the same connection that the partition was created on.
/// \param[in] serialized_partition The partition descriptor.
@@ -1042,7 +1474,11 @@ AdbcStatusCode AdbcStatementRelease(struct AdbcStatement* statement,
/// \brief Execute a statement and get the results.
///
-/// This invalidates any prior result sets.
+/// This invalidates any prior result sets. This AdbcStatement must
+/// outlive the returned ArrowArrayStream.
+///
+/// Since ADBC 1.1.0: releasing the returned ArrowArrayStream without
+/// consuming it fully is equivalent to calling AdbcStatementCancel.
///
/// \param[in] statement The statement to execute.
/// \param[out] out The results. Pass NULL if the client does not
@@ -1056,6 +1492,25 @@ AdbcStatusCode AdbcStatementExecuteQuery(struct AdbcStatement* statement,
struct ArrowArrayStream* out,
int64_t* rows_affected, struct AdbcError* error);
+/// \brief Get the schema of the result set of a query without
+/// executing it.
+///
+/// This invalidates any prior result sets.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+///
+/// \param[in] statement The statement to execute.
+/// \param[out] out The result schema.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+///
+/// \return ADBC_STATUS_NOT_IMPLEMENTED if the driver does not support this.
+ADBC_EXPORT
+AdbcStatusCode AdbcStatementExecuteSchema(struct AdbcStatement* statement,
+ struct ArrowSchema* schema,
+ struct AdbcError* error);
+
/// \brief Turn this statement into a prepared statement to be
/// executed multiple times.
///
@@ -1138,6 +1593,102 @@ AdbcStatusCode AdbcStatementBindStream(struct AdbcStatement* statement,
struct ArrowArrayStream* stream,
struct AdbcError* error);
+/// \brief Cancel execution of an in-progress query.
+///
+/// This can be called during AdbcStatementExecuteQuery (or similar),
+/// or while consuming an ArrowArrayStream returned from such.
+/// Calling this function should make the other functions return
+/// ADBC_STATUS_CANCELLED (from ADBC functions) or ECANCELED (from
+/// methods of ArrowArrayStream).
+///
+/// This must always be thread-safe (other operations are not).
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+///
+/// \param[in] statement The statement to cancel.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+///
+/// \return ADBC_STATUS_INVALID_STATE if there is no query to cancel.
+/// \return ADBC_STATUS_UNKNOWN if the query could not be cancelled.
+ADBC_EXPORT
+AdbcStatusCode AdbcStatementCancel(struct AdbcStatement* statement,
+ struct AdbcError* error);
+
+/// \brief Get a string option of the statement.
+///
+/// This must always be thread-safe (other operations are not).
+///
+/// The returned option value is only valid until the next call to
+/// GetOption or Release.
+///
+/// For standard options, drivers must always support getting the
+/// option value (if they support getting option values at all) via
+/// the type specified in the option. (For example, an option set via
+/// SetOptionDouble must be retrievable via GetOptionDouble.) Drivers
+/// may also support getting a converted option value via other
+/// getters if needed. (For example, getting the string
+/// representation of a double option.)
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] statement The statement.
+/// \param[in] key The option to get.
+/// \param[out] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_FOUND if the option is not recognized.
+AdbcStatusCode AdbcStatementGetOption(struct AdbcStatement* statement, const char* key,
+ const char** value, struct AdbcError* error);
+
+/// \brief Get an integer option of the statement.
+///
+/// This must always be thread-safe (other operations are not).
+///
+/// For standard options, drivers must always support getting the
+/// option value (if they support getting option values at all) via
+/// the type specified in the option. (For example, an option set via
+/// SetOptionDouble must be retrievable via GetOptionDouble.) Drivers
+/// may also support getting a converted option value via other
+/// getters if needed. (For example, getting the string
+/// representation of a double option.)
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] statement The statement.
+/// \param[in] key The option to get.
+/// \param[out] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_FOUND if the option is not recognized.
+AdbcStatusCode AdbcStatementGetOptionInt(struct AdbcStatement* statement, const char* key,
+ int64_t* value, struct AdbcError* error);
+
+/// \brief Get a double option of the statement.
+///
+/// This must always be thread-safe (other operations are not).
+///
+/// For standard options, drivers must always support getting the
+/// option value (if they support getting option values at all) via
+/// the type specified in the option. (For example, an option set via
+/// SetOptionDouble must be retrievable via GetOptionDouble.) Drivers
+/// may also support getting a converted option value via other
+/// getters if needed. (For example, getting the string
+/// representation of a double option.)
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] statement The statement.
+/// \param[in] key The option to get.
+/// \param[out] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_FOUND if the option is not recognized.
+AdbcStatusCode AdbcStatementGetOptionDouble(struct AdbcStatement* statement,
+ const char* key, double* value,
+ struct AdbcError* error);
+
/// \brief Get the schema for bound parameters.
///
/// This retrieves an Arrow schema describing the number, names, and
@@ -1159,10 +1710,45 @@ AdbcStatusCode AdbcStatementGetParameterSchema(struct AdbcStatement* statement,
struct AdbcError* error);
/// \brief Set a string option on a statement.
+/// \param[in] statement The statement.
+/// \param[in] key The option to set.
+/// \param[in] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_IMPLEMENTED if the option is not recognized.
ADBC_EXPORT
AdbcStatusCode AdbcStatementSetOption(struct AdbcStatement* statement, const char* key,
const char* value, struct AdbcError* error);
+/// \brief Set an integer option on a statement.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] statement The statement.
+/// \param[in] key The option to set.
+/// \param[in] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_IMPLEMENTED if the option is not recognized
+ADBC_EXPORT
+AdbcStatusCode AdbcStatementSetOptionInt(struct AdbcStatement* statement, const char* key,
+ int64_t value, struct AdbcError* error);
+
+/// \brief Set a double option on a statement.
+///
+/// \since ADBC API revision 1.1.0
+/// \addtogroup adbc-1.1.0
+/// \param[in] statement The statement.
+/// \param[in] key The option to set.
+/// \param[in] value The option value.
+/// \param[out] error An optional location to return an error
+/// message if necessary.
+/// \return ADBC_STATUS_NOT_IMPLEMENTED if the option is not recognized
+ADBC_EXPORT
+AdbcStatusCode AdbcStatementSetOptionDouble(struct AdbcStatement* statement,
+ const char* key, double value,
+ struct AdbcError* error);
+
/// \addtogroup adbc-statement-partition
/// @{
@@ -1198,7 +1784,15 @@ AdbcStatusCode AdbcStatementExecutePartitions(struct AdbcStatement* statement,
/// driver.
///
/// Although drivers may choose any name for this function, the
-/// recommended name is "AdbcDriverInit".
+/// recommended name is "AdbcDriverInit", or a name derived from the
+/// name of the driver's shared library as follows: remove the 'lib'
+/// prefix (on Unix systems) and all file extensions, then PascalCase
+/// the driver name, append Init, and prepend Adbc (if not already
+/// there). For example:
+///
+/// - libadbc_driver_sqlite.so.2.0.0 -> AdbcDriverSqliteInit
+/// - adbc_driver_sqlite.dll -> AdbcDriverSqliteInit
+/// - proprietary_driver.dll -> AdbcProprietaryDriverInit
///
/// \param[in] version The ADBC revision to attempt to initialize (see
/// ADBC_VERSION_1_0_0).
diff --git a/c/driver/postgresql/postgresql.cc b/c/driver/postgresql/postgresql.cc
index 29fd04cd..95e6c8b8 100644
--- a/c/driver/postgresql/postgresql.cc
+++ b/c/driver/postgresql/postgresql.cc
@@ -471,9 +471,10 @@ extern "C" {
ADBC_EXPORT
AdbcStatusCode AdbcDriverInit(int version, void* raw_driver, struct AdbcError* error) {
if (version != ADBC_VERSION_1_0_0) return ADBC_STATUS_NOT_IMPLEMENTED;
+ if (!raw_driver) return ADBC_STATUS_INVALID_ARGUMENT;
auto* driver = reinterpret_cast<struct AdbcDriver*>(raw_driver);
- std::memset(driver, 0, sizeof(*driver));
+ std::memset(driver, 0, ADBC_DRIVER_1_0_0_SIZE);
driver->DatabaseInit = PostgresDatabaseInit;
driver->DatabaseNew = PostgresDatabaseNew;
driver->DatabaseRelease = PostgresDatabaseRelease;
diff --git a/c/driver/sqlite/sqlite.c b/c/driver/sqlite/sqlite.c
index 4124098f..359c594d 100644
--- a/c/driver/sqlite/sqlite.c
+++ b/c/driver/sqlite/sqlite.c
@@ -1340,7 +1340,7 @@ AdbcStatusCode SqliteDriverInit(int version, void* raw_driver, struct AdbcError*
}
struct AdbcDriver* driver = (struct AdbcDriver*)raw_driver;
- memset(driver, 0, sizeof(*driver));
+ memset(driver, 0, ADBC_DRIVER_1_0_0_SIZE);
driver->DatabaseInit = SqliteDatabaseInit;
driver->DatabaseNew = SqliteDatabaseNew;
driver->DatabaseRelease = SqliteDatabaseRelease;
diff --git a/c/driver_manager/adbc_driver_manager.cc b/c/driver_manager/adbc_driver_manager.cc
index c63560a4..888c48a6 100644
--- a/c/driver_manager/adbc_driver_manager.cc
+++ b/c/driver_manager/adbc_driver_manager.cc
@@ -19,6 +19,7 @@
#include <adbc.h>
#include <algorithm>
+#include <array>
#include <cstring>
#include <string>
#include <unordered_map>
@@ -191,6 +192,12 @@ AdbcStatusCode StatementExecutePartitions(struct AdbcStatement* statement,
return ADBC_STATUS_NOT_IMPLEMENTED;
}
+AdbcStatusCode StatementExecuteSchema(struct AdbcStatement* statement,
+ struct ArrowSchema* schema,
+ struct AdbcError* error) {
+ return ADBC_STATUS_NOT_IMPLEMENTED;
+}
+
AdbcStatusCode StatementGetParameterSchema(struct AdbcStatement* statement,
struct ArrowSchema* schema,
struct AdbcError* error) {
@@ -540,6 +547,15 @@ AdbcStatusCode AdbcStatementExecuteQuery(struct AdbcStatement* statement,
error);
}
+AdbcStatusCode AdbcStatementExecuteSchema(struct AdbcStatement* statement,
+ struct ArrowSchema* schema,
+ struct AdbcError* error) {
+ if (!statement->private_driver) {
+ return ADBC_STATUS_INVALID_STATE;
+ }
+ return statement->private_driver->StatementExecuteSchema(statement, schema, error);
+}
+
AdbcStatusCode AdbcStatementGetParameterSchema(struct AdbcStatement* statement,
struct ArrowSchema* schema,
struct AdbcError* error) {
@@ -640,11 +656,19 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name, const char* entrypoint,
AdbcDriverInitFunc init_func;
std::string error_message;
- if (version != ADBC_VERSION_1_0_0) {
- SetError(error, "Only ADBC 1.0.0 is supported");
- return ADBC_STATUS_NOT_IMPLEMENTED;
+ switch (version) {
+ case ADBC_VERSION_1_0_0:
+ case ADBC_VERSION_1_1_0:
+ break;
+ default:
+ SetError(error, "Only ADBC 1.0.0 and 1.1.0 are supported");
+ return ADBC_STATUS_NOT_IMPLEMENTED;
}
+ if (!raw_driver) {
+ SetError(error, "Must provide non-NULL raw_driver");
+ return ADBC_STATUS_INVALID_ARGUMENT;
+ }
auto* driver = reinterpret_cast<struct AdbcDriver*>(raw_driver);
if (!entrypoint) {
@@ -771,6 +795,25 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name, const char* entrypoint,
AdbcStatusCode AdbcLoadDriverFromInitFunc(AdbcDriverInitFunc init_func, int version,
void* raw_driver, struct AdbcError* error) {
+ constexpr std::array<int, 2> kSupportedVersions = {
+ ADBC_VERSION_1_1_0,
+ ADBC_VERSION_1_0_0,
+ };
+
+ if (!raw_driver) {
+ SetError(error, "Must provide non-NULL raw_driver");
+ return ADBC_STATUS_INVALID_ARGUMENT;
+ }
+
+ switch (version) {
+ case ADBC_VERSION_1_0_0:
+ case ADBC_VERSION_1_1_0:
+ break;
+ default:
+ SetError(error, "Only ADBC 1.0.0 and 1.1.0 are supported");
+ return ADBC_STATUS_NOT_IMPLEMENTED;
+ }
+
#define FILL_DEFAULT(DRIVER, STUB) \
if (!DRIVER->STUB) { \
DRIVER->STUB = &STUB; \
@@ -781,12 +824,20 @@ AdbcStatusCode AdbcLoadDriverFromInitFunc(AdbcDriverInitFunc init_func, int vers
return ADBC_STATUS_INTERNAL; \
}
- auto result = init_func(version, raw_driver, error);
+ // Starting from the passed version, try each (older) version in
+ // succession with the underlying driver until we find one that's
+ // accepted.
+ AdbcStatusCode result = ADBC_STATUS_NOT_IMPLEMENTED;
+ for (const int try_version : kSupportedVersions) {
+ if (try_version > version) continue;
+ result = init_func(try_version, raw_driver, error);
+ if (result != ADBC_STATUS_NOT_IMPLEMENTED) break;
+ }
if (result != ADBC_STATUS_OK) {
return result;
}
- if (version == ADBC_VERSION_1_0_0) {
+ if (version >= ADBC_VERSION_1_0_0) {
auto* driver = reinterpret_cast<struct AdbcDriver*>(raw_driver);
CHECK_REQUIRED(driver, DatabaseNew);
CHECK_REQUIRED(driver, DatabaseInit);
@@ -816,6 +867,13 @@ AdbcStatusCode AdbcLoadDriverFromInitFunc(AdbcDriverInitFunc init_func, int vers
FILL_DEFAULT(driver, StatementSetSqlQuery);
FILL_DEFAULT(driver, StatementSetSubstraitPlan);
}
+ if (version >= ADBC_VERSION_1_1_0) {
+ auto* driver = reinterpret_cast<struct AdbcDriver*>(raw_driver);
+ FILL_DEFAULT(driver, StatementExecuteSchema);
+
+ // Zero out the padding
+ std::memset(driver->reserved, 0, sizeof(driver->reserved));
+ }
return ADBC_STATUS_OK;
diff --git a/c/driver_manager/adbc_driver_manager_test.cc b/c/driver_manager/adbc_driver_manager_test.cc
index 99fa477b..26c8dc61 100644
--- a/c/driver_manager/adbc_driver_manager_test.cc
+++ b/c/driver_manager/adbc_driver_manager_test.cc
@@ -34,6 +34,8 @@ namespace adbc {
using adbc_validation::IsOkStatus;
using adbc_validation::IsStatus;
+TEST(Adbc, AdbcDriverSize) { ASSERT_EQ(sizeof(AdbcDriver), 96 * sizeof(void*)); }
+
class DriverManager : public ::testing::Test {
public:
void SetUp() override {
@@ -157,6 +159,38 @@ TEST_F(DriverManager, MultiDriverTest) {
error->release(&error.value);
}
+class AdbcVersion : public ::testing::Test {
+ public:
+ void SetUp() override {
+ std::memset(&driver, 0, sizeof(driver));
+ std::memset(&error, 0, sizeof(error));
+ }
+
+ void TearDown() override {
+ if (error.release) {
+ error.release(&error);
+ }
+
+ if (driver.release) {
+ ASSERT_THAT(driver.release(&driver, &error), IsOkStatus(&error));
+ ASSERT_EQ(driver.private_data, nullptr);
+ ASSERT_EQ(driver.private_manager, nullptr);
+ }
+ }
+
+ protected:
+ struct AdbcDriver driver = {};
+ struct AdbcError error = {};
+};
+
+// TODO: set up a dummy driver to test behavior more deterministically
+
+TEST_F(AdbcVersion, ForwardsCompatible) {
+ ASSERT_THAT(
+ AdbcLoadDriver("adbc_driver_sqlite", nullptr, ADBC_VERSION_1_1_0, &driver, &error),
+ IsOkStatus(&error));
+}
+
class SqliteQuirks : public adbc_validation::DriverQuirks {
public:
AdbcStatusCode SetupDatabase(struct AdbcDatabase* database,
diff --git a/go/adbc/adbc.go b/go/adbc/adbc.go
index 92df909b..bc03d428 100644
--- a/go/adbc/adbc.go
+++ b/go/adbc/adbc.go
@@ -142,20 +142,35 @@ const (
StatusUnauthorized // Unauthorized
)
+const (
+ AdbcVersion1_0_0 int64 = 1_000_000
+ AdbcVersion1_1_0 int64 = 1_001_000
+)
+
// Canonical option values
const (
- OptionValueEnabled = "true"
- OptionValueDisabled = "false"
- OptionKeyAutoCommit = "adbc.connection.autocommit"
- OptionKeyIngestTargetTable = "adbc.ingest.target_table"
- OptionKeyIngestMode = "adbc.ingest.mode"
- OptionKeyIsolationLevel = "adbc.connection.transaction.isolation_level"
- OptionKeyReadOnly = "adbc.connection.readonly"
- OptionValueIngestModeCreate = "adbc.ingest.mode.create"
- OptionValueIngestModeAppend = "adbc.ingest.mode.append"
- OptionKeyURI = "uri"
- OptionKeyUsername = "username"
- OptionKeyPassword = "password"
+ OptionValueEnabled = "true"
+ OptionValueDisabled = "false"
+ OptionKeyAutoCommit = "adbc.connection.autocommit"
+ // The current catalog.
+ OptionKeyCurrentCatalog = "adbc.connection.catalog"
+ // The current schema.
+ OptionKeyCurrentDbSchema = "adbc.connection.db_schema"
+ // Make ExecutePartitions nonblocking.
+ OptionKeyIncremental = "adbc.statement.exec.incremental"
+ // Get the progress
+ OptionKeyProgress = "adbc.statement.exec.progress"
+ OptionKeyIngestTargetTable = "adbc.ingest.target_table"
+ OptionKeyIngestMode = "adbc.ingest.mode"
+ OptionKeyIsolationLevel = "adbc.connection.transaction.isolation_level"
+ OptionKeyReadOnly = "adbc.connection.readonly"
+ OptionValueIngestModeCreate = "adbc.ingest.mode.create"
+ OptionValueIngestModeAppend = "adbc.ingest.mode.append"
+ OptionValueIngestModeReplace = "adbc.ingest.mode.replace"
+ OptionValueIngestModeCreateAppend = "adbc.ingest.mode.create_append"
+ OptionKeyURI = "uri"
+ OptionKeyUsername = "username"
+ OptionKeyPassword = "password"
)
type OptionIsolationLevel string
@@ -170,6 +185,11 @@ const (
LevelLinearizable OptionIsolationLevel = "adbc.connection.transaction.isolation.linearizable"
)
+// Canonical property values
+const (
+ PropertyProgress = "adbc.statement.exec.progress"
+)
+
// Driver is the entry point for the interface. It is similar to
// database/sql.Driver taking a map of keys and values as options
// to initialize a Connection to the database. Any common connection
@@ -212,6 +232,8 @@ const (
InfoDriverVersion InfoCode = 101 // DriverVersion
// The driver Arrow library version (type: utf8)
InfoDriverArrowVersion InfoCode = 102 // DriverArrowVersion
+ // The driver ADBC API version (type: int64)
+ InfoDriverADBCVersion InfoCode = 103 // DriverADBCVersion
)
type ObjectDepth int
@@ -275,6 +297,10 @@ type Connection interface {
// 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).
+ //
+ // Since ADBC 1.1.0: the range [500, 1_000) is reserved for "XDBC"
+ // information, which is the same metadata provided by the same info
+ // code range in the Arrow Flight SQL GetSqlInfo RPC.
GetInfo(ctx context.Context, infoCodes []InfoCode) (array.RecordReader, error)
// GetObjects gets a hierarchical view of all catalogs, database schemas,
@@ -470,6 +496,9 @@ type Statement interface {
// of rows affected if known, otherwise it will be -1.
//
// This invalidates any prior result sets on this statement.
+ //
+ // Since ADBC 1.1.0: releasing the returned RecordReader without
+ // consuming it fully is equivalent to calling AdbcStatementCancel.
ExecuteQuery(context.Context) (array.RecordReader, int64, error)
// ExecuteUpdate executes a statement that does not generate a result
@@ -534,5 +563,45 @@ type Statement interface {
//
// If the driver does not support partitioned results, this will return
// an error with a StatusNotImplemented code.
+ //
+ // When OptionKeyIncremental is set, this should be called
+ // repeatedly until receiving an empty Partitions.
ExecutePartitions(context.Context) (*arrow.Schema, Partitions, int64, error)
}
+
+// StatementCancel is a Statement that also supports Cancel.
+//
+// Since ADBC API revision 1.1.0.
+type StatementCancel interface {
+ // Cancel stops execution of an in-progress query.
+ //
+ // This can be called during ExecuteQuery (or similar), or while
+ // consuming a RecordReader returned from such. Calling this
+ // function should make the other functions return an error with a
+ // StatusCancelled code.
+ //
+ // This must always be thread-safe (other operations are not
+ // necessarily thread-safe).
+ Cancel() error
+}
+
+// StatementExecuteSchema is a Statement that also supports ExecuteSchema.
+//
+// Since ADBC API revision 1.1.0.
+type StatementExecuteSchema interface {
+ // ExecuteSchema gets the schema of the result set of a query without executing it.
+ ExecuteSchema(context.Context) (*arrow.Schema, error)
+}
+
+// GetSetOptions is a PostInitOptions that also supports getting and setting property values of different types.
+//
+// Since ADBC API revision 1.1.0.
+type GetSetOptions interface {
+ PostInitOptions
+
+ SetOption(key, value string) error
+ SetOptionInt(key, value int64) error
+ SetOptionDouble(key, value float64) error
+ GetOptionInt(key string) (int64, error)
+ GetOptionDouble(key string) (float64, error)
+}
diff --git a/go/adbc/infocode_string.go b/go/adbc/infocode_string.go
index 73af20c1..df0fd74b 100644
--- a/go/adbc/infocode_string.go
+++ b/go/adbc/infocode_string.go
@@ -14,23 +14,24 @@ func _() {
_ = x[InfoDriverName-100]
_ = x[InfoDriverVersion-101]
_ = x[InfoDriverArrowVersion-102]
+ _ = x[InfoDriverADBCVersion-103]
}
const (
_InfoCode_name_0 = "VendorNameVendorVersionVendorArrowVersion"
- _InfoCode_name_1 = "DriverNameDriverVersionDriverArrowVersion"
+ _InfoCode_name_1 = "DriverNameDriverVersionDriverArrowVersionDriverADBCVersion"
)
var (
_InfoCode_index_0 = [...]uint8{0, 10, 23, 41}
- _InfoCode_index_1 = [...]uint8{0, 10, 23, 41}
+ _InfoCode_index_1 = [...]uint8{0, 10, 23, 41, 58}
)
func (i InfoCode) String() string {
switch {
case i <= 2:
return _InfoCode_name_0[_InfoCode_index_0[i]:_InfoCode_index_0[i+1]]
- case 100 <= i && i <= 102:
+ case 100 <= i && i <= 103:
i -= 100
return _InfoCode_name_1[_InfoCode_index_1[i]:_InfoCode_index_1[i+1]]
default:
diff --git a/go/adbc/pkg/_tmpl/driver.go.tmpl b/go/adbc/pkg/_tmpl/driver.go.tmpl
index 03a94c02..7ae325a1 100644
--- a/go/adbc/pkg/_tmpl/driver.go.tmpl
+++ b/go/adbc/pkg/_tmpl/driver.go.tmpl
@@ -901,7 +901,7 @@ func {{.Prefix}}DriverInit(version C.int, rawDriver *C.void, err *C.struct_AdbcE
}
driver := (*C.struct_AdbcDriver)(unsafe.Pointer(rawDriver))
- C.memset(unsafe.Pointer(driver), 0, C.sizeof_struct_AdbcDriver)
+ C.memset(unsafe.Pointer(driver), 0, C.ADBC_DRIVER_1_0_0_SIZE)
driver.DatabaseInit = (*[0]byte)(C.{{.Prefix}}DatabaseInit)
driver.DatabaseNew = (*[0]byte)(C.{{.Prefix}}DatabaseNew)
driver.DatabaseRelease = (*[0]byte)(C.{{.Prefix}}DatabaseRelease)
diff --git a/go/adbc/pkg/flightsql/driver.go b/go/adbc/pkg/flightsql/driver.go
index 6d5cf75b..7cbec398 100644
--- a/go/adbc/pkg/flightsql/driver.go
+++ b/go/adbc/pkg/flightsql/driver.go
@@ -905,7 +905,7 @@ func FlightSQLDriverInit(version C.int, rawDriver *C.void, err *C.struct_AdbcErr
}
driver := (*C.struct_AdbcDriver)(unsafe.Pointer(rawDriver))
- C.memset(unsafe.Pointer(driver), 0, C.sizeof_struct_AdbcDriver)
+ C.memset(unsafe.Pointer(driver), 0, C.ADBC_DRIVER_1_0_0_SIZE)
driver.DatabaseInit = (*[0]byte)(C.FlightSQLDatabaseInit)
driver.DatabaseNew = (*[0]byte)(C.FlightSQLDatabaseNew)
driver.DatabaseRelease = (*[0]byte)(C.FlightSQLDatabaseRelease)
diff --git a/go/adbc/pkg/snowflake/driver.go b/go/adbc/pkg/snowflake/driver.go
index 31e2f131..35dc0ce8 100644
--- a/go/adbc/pkg/snowflake/driver.go
+++ b/go/adbc/pkg/snowflake/driver.go
@@ -905,7 +905,7 @@ func SnowflakeDriverInit(version C.int, rawDriver *C.void, err *C.struct_AdbcErr
}
driver := (*C.struct_AdbcDriver)(unsafe.Pointer(rawDriver))
- C.memset(unsafe.Pointer(driver), 0, C.sizeof_struct_AdbcDriver)
+ C.memset(unsafe.Pointer(driver), 0, C.ADBC_DRIVER_1_0_0_SIZE)
driver.DatabaseInit = (*[0]byte)(C.SnowflakeDatabaseInit)
driver.DatabaseNew = (*[0]byte)(C.SnowflakeDatabaseNew)
driver.DatabaseRelease = (*[0]byte)(C.SnowflakeDatabaseRelease)
diff --git a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcConnection.java b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcConnection.java
index fea70548..d3c81191 100644
--- a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcConnection.java
+++ b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcConnection.java
@@ -27,7 +27,7 @@ import org.apache.arrow.vector.types.pojo.Schema;
* <p>Connections are not required to be thread-safe, but they can be used from multiple threads so
* long as clients take care to serialize accesses to a connection.
*/
-public interface AdbcConnection extends AutoCloseable {
+public interface AdbcConnection extends AutoCloseable, AdbcOptions {
/** Commit the pending transaction. */
default void commit() throws AdbcException {
throw AdbcException.notImplemented("Connection does not support transactions");
@@ -285,6 +285,42 @@ public interface AdbcConnection extends AutoCloseable {
throw AdbcException.notImplemented("Connection does not support transactions");
}
+ /**
+ * Get the current catalog.
+ *
+ * @since ADBC API revision 1.1.0
+ */
+ default String getCurrentCatalog() throws AdbcException {
+ throw AdbcException.notImplemented("Connection does not support current catalog");
+ }
+
+ /**
+ * Set the current catalog.
+ *
+ * @since ADBC API revision 1.1.0
+ */
+ default void setCurrentCatalog(String catalog) throws AdbcException {
+ throw AdbcException.notImplemented("Connection does not support current catalog");
+ }
+
+ /**
+ * Get the current schema.
+ *
+ * @since ADBC API revision 1.1.0
+ */
+ default String getCurrentDbSchema() throws AdbcException {
+ throw AdbcException.notImplemented("Connection does not support current catalog");
+ }
+
+ /**
+ * Set the current schema.
+ *
+ * @since ADBC API revision 1.1.0
+ */
+ default void setCurrentDbSchema(String catalog) throws AdbcException {
+ throw AdbcException.notImplemented("Connection does not support current catalog");
+ }
+
/**
* Get whether the connection is read-only.
*
diff --git a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcDatabase.java b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcDatabase.java
index e63c598b..723acfc0 100644
--- a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcDatabase.java
+++ b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcDatabase.java
@@ -24,7 +24,7 @@ package org.apache.arrow.adbc.core;
* remote/networked databases, for in-memory databases, this object provides an explicit point of
* ownership.
*/
-public interface AdbcDatabase extends AutoCloseable {
+public interface AdbcDatabase extends AutoCloseable, AdbcOptions {
/** Create a new connection to the database. */
AdbcConnection connect() throws AdbcException;
}
diff --git a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcDriver.java b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcDriver.java
index 80abd185..9386b880 100644
--- a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcDriver.java
+++ b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcDriver.java
@@ -21,11 +21,42 @@ import java.util.Map;
/** A handle to an ADBC database driver. */
public interface AdbcDriver {
- /** The standard parameter name for a connection URL (type String). */
- String PARAM_URL = "adbc.url";
+ /**
+ * The standard parameter name for a password (type String).
+ *
+ * @since ADBC API revision 1.1.0
+ */
+ AdbcOptionKey<String> PARAM_PASSWORD = new AdbcOptionKey<>("password", String.class);
+
+ /**
+ * The standard parameter name for a connection URI (type String).
+ *
+ * @since ADBC API revision 1.1.0
+ */
+ AdbcOptionKey<String> PARAM_URI = new AdbcOptionKey<>("uri", String.class);
+
+ /**
+ * The standard parameter name for a connection URL (type String).
+ *
+ * @deprecated Prefer {@link #PARAM_URI} instead.
+ */
+ @Deprecated String PARAM_URL = "adbc.url";
+
+ /**
+ * The standard parameter name for a username (type String).
+ *
+ * @since ADBC API revision 1.1.0
+ */
+ AdbcOptionKey<String> PARAM_USERNAME = new AdbcOptionKey<>("username", String.class);
+
/** The standard parameter name for SQL quirks configuration (type SqlQuirks). */
String PARAM_SQL_QUIRKS = "adbc.sql.quirks";
+ /** ADBC API revision 1.0.0. */
+ long ADBC_VERSION_1_0_0 = 1_000_000;
+ /** ADBC API revision 1.1.0. */
+ long ADBC_VERSION_1_1_0 = 1_001_000;
+
/**
* Open a database via this driver.
*
diff --git a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcInfoCode.java b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcInfoCode.java
index 52c09565..8d5c73ba 100644
--- a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcInfoCode.java
+++ b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcInfoCode.java
@@ -16,7 +16,12 @@
*/
package org.apache.arrow.adbc.core;
-/** Integer IDs used for requesting information about the database/driver. */
+/**
+ * Integer IDs used for requesting information about the database/driver.
+ *
+ * <p>Since ADBC 1.1.0: the range [500, 1_000) is reserved for "XDBC" information, which is the same
+ * metadata provided by the same info code range in the Arrow Flight SQL GetSqlInfo RPC.
+ */
public enum AdbcInfoCode {
/** The database vendor/product name (e.g. the server name) (type: utf8). */
VENDOR_NAME(0),
@@ -31,6 +36,16 @@ public enum AdbcInfoCode {
DRIVER_VERSION(101),
/** The driver Arrow library version (type: utf8). */
DRIVER_ARROW_VERSION(102),
+ /**
+ * The ADBC API version (type: int64).
+ *
+ * <p>The value should be one of the ADBC_VERSION constants.
+ *
+ * @see AdbcDriver#ADBC_VERSION_1_0_0
+ * @see AdbcDriver#ADBC_VERSION_1_1_0
+ * @since ADBC API revision 1.1.0
+ */
+ DRIVER_ADBC_VERSION(103),
;
private final int value;
diff --git a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcOptionKey.java b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcOptionKey.java
new file mode 100644
index 00000000..d5947036
--- /dev/null
+++ b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcOptionKey.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package org.apache.arrow.adbc.core;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * A typesafe option key.
+ *
+ * @since ADBC API revision 1.1.0
+ * @param <T> The option value type.
+ */
+public final class AdbcOptionKey<T> {
+ private final String key;
+ private final Class<T> type;
+
+ public AdbcOptionKey(String key, Class<T> type) {
+ this.key = Objects.requireNonNull(key);
+ this.type = Objects.requireNonNull(type);
+ }
+
+ /**
+ * Set this option in an options map (like for {@link AdbcDriver#open(Map)}.
+ *
+ * @param options The options.
+ * @param value The option value.
+ */
+ public void set(Map<String, Object> options, T value) {
+ options.put(key, value);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ AdbcOptionKey<?> that = (AdbcOptionKey<?>) o;
+ return Objects.equals(key, that.key) && Objects.equals(type, that.type);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(key, type);
+ }
+
+ @Override
+ public String toString() {
+ return "AdbcOptionKey{" + key + ", " + type + '}';
+ }
+}
diff --git a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcDriver.java b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcOptions.java
similarity index 52%
copy from java/core/src/main/java/org/apache/arrow/adbc/core/AdbcDriver.java
copy to java/core/src/main/java/org/apache/arrow/adbc/core/AdbcOptions.java
index 80abd185..efd8eab7 100644
--- a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcDriver.java
+++ b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcOptions.java
@@ -17,19 +17,29 @@
package org.apache.arrow.adbc.core;
-import java.util.Map;
-
-/** A handle to an ADBC database driver. */
-public interface AdbcDriver {
- /** The standard parameter name for a connection URL (type String). */
- String PARAM_URL = "adbc.url";
- /** The standard parameter name for SQL quirks configuration (type SqlQuirks). */
- String PARAM_SQL_QUIRKS = "adbc.sql.quirks";
+/** An ADBC object that supports getting/setting generic options. */
+public interface AdbcOptions {
+ /**
+ * Get a generic option.
+ *
+ * @since ADBC API revision 1.1.0
+ * @param key The option to retrieve.
+ * @return The option value.
+ * @param <T> The option value type.
+ */
+ default <T> T getOption(AdbcOptionKey<T> key) throws AdbcException {
+ throw AdbcException.notImplemented("Unsupported option " + key);
+ }
/**
- * Open a database via this driver.
+ * Set a generic option.
*
- * @param parameters Driver-specific parameters.
+ * @since ADBC API revision 1.1.0
+ * @param key The option to set.
+ * @param value The option value.
+ * @param <T> The option value type.
*/
- AdbcDatabase open(Map<String, Object> parameters) throws AdbcException;
+ default <T> void setOption(AdbcOptionKey<T> key, T value) throws AdbcException {
+ throw AdbcException.notImplemented("Unsupported option " + key);
+ }
}
diff --git a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcStatement.java b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcStatement.java
index ef2be487..a033726b 100644
--- a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcStatement.java
+++ b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcStatement.java
@@ -19,6 +19,7 @@ package org.apache.arrow.adbc.core;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.Iterator;
import java.util.List;
import org.apache.arrow.vector.VectorSchemaRoot;
import org.apache.arrow.vector.ipc.ArrowReader;
@@ -40,8 +41,23 @@ import org.apache.arrow.vector.types.pojo.Schema;
* <p>Statements are not required to be thread-safe, but they can be used from multiple threads so
* long as clients take care to serialize accesses to a statement.
*/
-public interface AdbcStatement extends AutoCloseable {
- /** Set a generic query option. */
+public interface AdbcStatement extends AutoCloseable, AdbcOptions {
+ /**
+ * Cancel execution of a query.
+ *
+ * <p>This method must be thread-safe (other method are not necessarily thread-safe).
+ *
+ * @since ADBC API revision 1.1.0
+ */
+ default void cancel() throws AdbcException {
+ throw AdbcException.notImplemented("Statement does not support cancel");
+ }
+
+ /**
+ * Set a generic query option.
+ *
+ * @deprecated Prefer {@link #setOption(AdbcOptionKey, Object)}.
+ */
default void setOption(String key, Object value) throws AdbcException {
throw AdbcException.notImplemented("Unsupported option " + key);
}
@@ -94,6 +110,37 @@ public interface AdbcStatement extends AutoCloseable {
throw AdbcException.notImplemented("Statement does not support executePartitioned");
}
+ /**
+ * Get the schema of the result set without executing the query.
+ *
+ * @since ADBC API revision 1.1.0
+ */
+ default Schema executeSchema() throws AdbcException {
+ throw AdbcException.notImplemented("Statement does not support executeSchema");
+ }
+
+ /**
+ * Execute a result set-generating query and get a list of partitions of the result set.
+ *
+ * <p>These can be serialized and deserialized for parallel and/or distributed fetching.
+ *
+ * <p>This may invalidate any prior result sets.
+ *
+ * @since ADBC API revision 1.1.0
+ */
+ default Iterator<PartitionResult> pollPartitioned() throws AdbcException {
+ throw AdbcException.notImplemented("Statement does not support pollPartitioned");
+ }
+
+ /**
+ * Get the progress of executing a query.
+ *
+ * @since ADBC API revision 1.1.0
+ */
+ default double getProgress() throws AdbcException {
+ throw AdbcException.notImplemented("Statement does not support getProgress");
+ }
+
/**
* Get the schema for bound parameters.
*
diff --git a/java/core/src/main/java/org/apache/arrow/adbc/core/BulkIngestMode.java b/java/core/src/main/java/org/apache/arrow/adbc/core/BulkIngestMode.java
index 2ab16ac4..e23e8de4 100644
--- a/java/core/src/main/java/org/apache/arrow/adbc/core/BulkIngestMode.java
+++ b/java/core/src/main/java/org/apache/arrow/adbc/core/BulkIngestMode.java
@@ -24,7 +24,20 @@ public enum BulkIngestMode {
/**
* Do not create the table and append data; error if the table does not exist ({@link
* AdbcStatusCode#NOT_FOUND}) or does not match the schema of the data to append ({@link
- * AdbcStatusCode#ALREADY_EXISTS}). *
+ * AdbcStatusCode#ALREADY_EXISTS}).
*/
APPEND,
+ /**
+ * Create the table and insert data; drop the original table if it already exists.
+ *
+ * @since ADBC API revision 1.1.0
+ */
+ REPLACE,
+ /**
+ * Insert data; create the table if it does not exist, or error ({@link
+ * AdbcStatusCode#ALREADY_EXISTS}) if the table exists, but the schema does not match the schema
+ * of the data to append.
+ */
+ CREATE_APPEND,
+ ;
}