diff --git a/c/driver_manager/adbc_version_100_compatibility_test.cc b/c/driver_manager/adbc_version_100_compatibility_test.cc index 43079ecb3e..0b5f05c0d4 100644 --- a/c/driver_manager/adbc_version_100_compatibility_test.cc +++ b/c/driver_manager/adbc_version_100_compatibility_test.cc @@ -57,9 +57,11 @@ class AdbcVersion : public ::testing::Test { TEST_F(AdbcVersion, StructSize) { ASSERT_EQ(sizeof(AdbcErrorVersion100), ADBC_ERROR_1_0_0_SIZE); ASSERT_EQ(sizeof(AdbcError), ADBC_ERROR_1_1_0_SIZE); + ASSERT_EQ(sizeof(AdbcError), ADBC_ERROR_1_2_0_SIZE); ASSERT_EQ(sizeof(AdbcDriverVersion100), ADBC_DRIVER_1_0_0_SIZE); - ASSERT_EQ(sizeof(AdbcDriver), ADBC_DRIVER_1_1_0_SIZE); + ASSERT_EQ(offsetof(struct AdbcDriver, StatementExecuteMulti), ADBC_DRIVER_1_1_0_SIZE); + ASSERT_EQ(sizeof(AdbcDriver), ADBC_DRIVER_1_2_0_SIZE); } // Initialize a version 1.0.0 driver with the version 1.1.0 driver struct. diff --git a/c/include/arrow-adbc/adbc.h b/c/include/arrow-adbc/adbc.h index 57e665f84a..f9186e284d 100644 --- a/c/include/arrow-adbc/adbc.h +++ b/c/include/arrow-adbc/adbc.h @@ -355,6 +355,15 @@ struct ADBC_EXPORT AdbcError { /// \since ADBC API revision 1.1.0 #define ADBC_ERROR_1_1_0_SIZE (sizeof(struct AdbcError)) +/// \brief The size of the AdbcError structure in ADBC 1.2.0. +/// +/// Drivers written for ADBC 1.2.0 and later should never touch more than this +/// portion of an AdbcDriver struct when vendor_code is +/// ADBC_ERROR_VENDOR_CODE_PRIVATE_DATA. +/// +/// \since ADBC API revision 1.2.0 +#define ADBC_ERROR_1_2_0_SIZE (sizeof(struct AdbcError)) + /// \brief Extra key-value metadata for an error. /// /// The fields here are owned by the driver and should not be freed. The @@ -371,6 +380,13 @@ struct ADBC_EXPORT AdbcErrorDetail { size_t value_length; }; +/// \brief Get the vendor code for an error (since the vendor code field was +/// repurposed), or 0 if not available/not set. +/// +/// \since ADBC API revision 1.2.0 +ADBC_EXPORT +int AdbcErrorGetVendorCode(const struct AdbcError* error); + /// \brief Get the number of metadata values available in an error. /// /// \since ADBC API revision 1.1.0 @@ -423,6 +439,14 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream /// \since ADBC API revision 1.1.0 #define ADBC_VERSION_1_1_0 1001000 +/// \brief ADBC revision 1.2.0 +/// +/// When passed to an AdbcDriverInitFunc(), the driver parameter must +/// point to an AdbcDriver. +/// +/// \since ADBC API revision 1.2.0 +#define ADBC_VERSION_1_2_0 1002000 + /// \brief Canonical option value for enabling an option. /// /// For use as the value in SetOption calls. @@ -525,8 +549,144 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream /// \see AdbcConnectionGetInfo /// \see ADBC_VERSION_1_0_0 /// \see ADBC_VERSION_1_1_0 +/// \see ADBC_VERSION_1_2_0 #define ADBC_INFO_DRIVER_ADBC_VERSION 103 +/// \brief Whether the driver supports bulk ingest (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +#define ADBC_INFO_FEATURE_INGEST 200 + +/// \brief Supported bulk ingest modes (type: string list). +/// +/// Values are the mode constants themselves. +/// +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +#define ADBC_INFO_FEATURE_INGEST_MODES 201 + +/// \brief Whether the driver supports ingesting into a temporary table (type: +/// bool). +/// +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_INGEST_OPTION_TEMPORARY +#define ADBC_INFO_FEATURE_INGEST_TEMPORARY 202 + +/// \brief Whether the driver supports specifying the catalog of the table to +/// ingest into (type: bool). +/// +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_INGEST_OPTION_TARGET_CATALOG +#define ADBC_INFO_FEATURE_INGEST_TARGET_CATALOG 203 + +/// \brief Whether the driver supports specifying the catalog of the table to +/// ingest into (type: bool). +/// +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_INGEST_OPTION_TARGET_CATALOG +#define ADBC_INFO_FEATURE_INGEST_TARGET_SCHEMA 204 + +/// \brief Whether the driver supports getting catalog metadata (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcConnectionGetObjects +#define ADBC_INFO_FEATURE_OBJECTS 220 + +/// \brief Whether the driver supports getting table schemas (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcConnectionGetObjects +#define ADBC_INFO_FEATURE_TABLE_SCHEMA 221 + +/// \brief Whether the driver supports getting table types (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcConnectionGetObjects +#define ADBC_INFO_FEATURE_TABLE_TYPES 222 + +/// \brief Whether the driver supports transactions (true), or if autocommit +/// is always enabled (false) (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_CONNECTION_OPTION_AUTOCOMMIT +#define ADBC_INFO_FEATURE_TRANSACTIONS 240 + +/// \brief Whether the driver supports setting the isolation level of +/// transactions (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_CONNECTION_OPTION_ISOLATION_LEVEL +#define ADBC_INFO_FEATURE_TRANSACTION_ISOLATION_LEVEL 241 + +/// \brief Whether the driver supports getting statistics (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcConnectionGetStatistics +#define ADBC_INFO_FEATURE_STATISTICS 242 + +/// \brief Whether the driver supports getting/setting the current catalog +/// (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_CONNECTION_OPTION_CURRENT_CATALOG +#define ADBC_INFO_FEATURE_CURRENT_CATALOG 243 + +/// \brief Whether the driver supports getting/setting the current schema +/// (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_CONNECTION_OPTION_CURRENT_CATALOG +#define ADBC_INFO_FEATURE_CURRENT_DB_SCHEMA 244 + +/// \brief Whether the driver supports binding data (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcStatementBind +/// \see AdbcStatementBindStream +#define ADBC_INFO_FEATURE_BIND 245 + +/// \brief Whether the driver supports partitioned execution (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcConnectionReadPartition +/// \see AdbcStatementExecutePartitions +#define ADBC_INFO_FEATURE_EXECUTE_PARTITIONS 246 + +/// \brief Whether the driver supports multiple result sets (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcStatementExecuteMulti +#define ADBC_INFO_FEATURE_EXECUTE_MULTI 247 + +/// \brief Whether the driver supports getting result set schemas (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcStatementExecuteSchema +/// \see AdbcStatementExecuteSchemaMulti +#define ADBC_INFO_FEATURE_EXECUTE_SCHEMA 248 + +/// \brief Whether the driver supports getting parameter schemas (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcStatementGetParameterSchema +#define ADBC_INFO_FEATURE_PARAMETER_SCHEMA 249 + +/// \brief Whether the driver supports getting error metadata (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcErrorGetDetailCount +/// \see AdbcErrorGetDetail +/// \see AdbcErrorFromArrayStream +/// \see ADBC_ERROR_VENDOR_CODE_PRIVATE_DATA +#define ADBC_INFO_FEATURE_ERROR_METADATA 250 + +/// \defgroup adbc-catalog-metadata ADBC Catalog Metadata Constants +/// Constants for catalog metadata. +/// @{ + /// \brief Return metadata on catalogs, schemas, tables, and columns. /// /// \see AdbcConnectionGetObjects @@ -552,6 +712,88 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream /// \see AdbcConnectionGetObjects #define ADBC_OBJECT_DEPTH_COLUMNS ADBC_OBJECT_DEPTH_ALL +/// \brief This foreign key does not allow update of the corresponding primary +/// key. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeyNoAction`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_ACTION_NO_ACTION 3 + +/// \brief This foreign key will be updated/deleted with corresponding primary +/// key. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeyCascade`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_ACTION_CASCADE 0 + +/// \brief This foreign key will be set to NULL if its corresponding primary +/// key is updated or deleted. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeySetNull`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_ACTION_SET_NULL 2 + +/// \brief This foreign key will be set to its default if its corresponding +/// primary key is updated or deleted. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeySetDefault`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_ACTION_SET_DEFAULT 4 + +/// \brief Similar to ADBC_CONSTRAINT_ACTION_NO_ACTION but may be interpreted +/// differently by the vendor (e.g., raise an error immediately instead of +/// allowing the check to be deferred). +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeyRestrict`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_ACTION_RESTRICT 1 + +/// \brief This constraint is deferrable, and is initially deferred. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeyInitiallyDeferred`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_DEFERRABLE_DEFERRED 5 + +/// \brief This constraint is deferrable, but is initially immediate. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeyInitiallyImmediate`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_DEFERRABLE_IMMEDIATE 6 + +/// \brief This constraint may not be deferred. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeyNotDeferrable`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_NOT_DEFERRABLE 7 + +/// \brief This foreign key allows any of the foreign key columns to be NULL; +/// if so, no match is required in the referenced table. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_MATCH_SIMPLE 0 + +/// \brief This foreign key only allows foreign key columns to be NULL if all +/// of them are NULL; if so, no match is required in the referenced table. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_MATCH_FULL 1 + +/// \brief This foreign key allows any of the foreign key columns to be NULL; +/// if so, non-NULL columns must still match. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_MATCH_PARTIAL 2 + +/// @} + /// \defgroup adbc-table-statistics ADBC Statistic Types /// Standard statistic names for AdbcConnectionGetStatistics. /// @{ @@ -647,6 +889,18 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream /// \since ADBC API revision 1.1.0 #define ADBC_CONNECTION_OPTION_CURRENT_DB_SCHEMA "adbc.connection.db_schema" +/// \brief Whether to run-length-encode common fields within standard metadata +/// collections. +/// +/// The type is boolean. The default is to run-length-encode. +/// +/// \see AdbcConnectionGetMetadataCollection +/// \see AdbcConnectionSetOption +/// \see AdbcConnectionSetOption +/// \since ADBC API revision 1.2.0 +#define ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE \ + "adbc.connection.metadata_collection.run_length_encoded" + /// \brief The name of the canonical option for making query execution /// nonblocking. /// @@ -971,8 +1225,124 @@ struct AdbcPartitions { /// @} +/// \defgroup adbc-statement-multi Multiple Result Set Execution +/// Some databases support executing a statement that returns multiple +/// result sets. This section defines the API for working with such +/// statements and result sets. +/// @{ + +/// \brief A struct for handling a potentially multi-result set execution +/// +/// This struct is populated by AdbcStatementExecuteMulti and can be used to iterate +/// through the result sets of the execution. The caller can use the MultiResultSetNext +/// or MultiResultSetNextPartitions functions on the AdbcMultiResultSet struct to iterate +/// through the result sets. The caller is responsible for calling the release function +/// when finished with the result set. +/// +/// \since ADBC API revision 1.2.0 +struct ADBC_EXPORT AdbcMultiResultSet { + /// \brief opaque implementation-defined state + void* private_data; + + /// \brief The associated driver + struct AdbcDriver* private_driver; +}; + +/// \brief Release the AdbcMultiResultSet and any associated resources. +/// +/// \since ADBC API revision 1.2.0 +/// +/// If all the result sets have not been completely consumed, then the driver +/// should cancel any remaining work if this is called. +/// +/// \param[in] result_set The result set to release. +/// \param[out] error An optional location to return an error message if necessary. +/// +/// \return ADBC_STATUS_OK on success or an appropriate error code. +AdbcStatusCode AdbcMultiResultSetRelease(struct AdbcMultiResultSet* result_set, + struct AdbcError* error); + +/// \brief Get the next ArrowArrayStream from an AdbcMultiResultSet. +/// +/// \since ADBC API revision 1.2.0 +/// +/// The driver can decide whether to allow fetching the next result set +/// as a single stream or as a set of partitions. If the driver does not +/// support fetching the next result set as a stream (indicating it should +/// be fetched as partitions), it should return ADBC_STATUS_NOT_IMPLEMENTED. +/// +/// To indicate that no additional result sets are available, this should return +/// ADBC_STATUS_OK and set the release callback on out to NULL. The expected +/// pattern is that after calling `StatementExecuteMulti`, the caller would +/// then call `MultiResultSetNext` repeatedly until it returns ADBC_STATUS_OK and +/// sets the release callback to NULL, indicating that there are no more result sets. +/// It is not an error to repeatedly call `MultiResultSetNext` after the last result set +/// has been reached; it should simply continue to return ADBC_STATUS_OK with a +/// NULL release callback. +/// +/// \param[in] result_set The result set struct to fetch the next result from. +/// \param[out] out The result stream to populate +/// \param[out] rows_affected The number of rows affected if known, else - +/// \param[out] error An optional location to return an error message if necessary. +/// +/// \return ADBC_STATUS_NOT_IMPLEMENTED if the driver only supports fetching results +/// as partitions or ADBC_STATUS_OK (or an appropriate error code) otherwise. +AdbcStatusCode AdbcMultiResultSetNext(struct AdbcMultiResultSet* result_set, + struct ArrowArrayStream* out, + int64_t* rows_affected, struct AdbcError* error); + +/// \brief Get the next result set from a multi-result-set execution as partitions. +/// +/// \since ADBC API revision 1.2.0 +/// +/// The driver can decide whether to allow fetching the next result set +/// as a single stream or as a set of partitions. If the driver does not +/// support fetching the next result set as partitions (indicating it should +/// be fetched as a stream), it should return ADBC_STATUS_NOT_IMPLEMENTED. +/// +/// To indicate that no additional result sets are available, this should return +/// ADBC_STATUS_OK and set the release callback on partitions to NULL. The expected +/// pattern is that after calling `StatementExecuteMulti`, the caller would +/// then call `MultiResultSetNextPartitions` repeatedly until it returns ADBC_STATUS_OK +/// and sets the release callback to NULL, indicating that there are no more result sets. +/// It is not an error to repeatedly call `MultiResultSetNextPartitions` after the last +/// result set has been reached; it should simply continue to return ADBC_STATUS_OK with +/// a NULL release callback. +/// +/// \param[in] result_set The result set struct to fetch the next result from. +/// \param[out] schema The schema of the result set to populate +/// \param[out] partitions The partitions to populate +/// \param[out] rows_affected The number of rows affected if known, else -1. Pass NULL +/// if the client does not want this information. +/// \param[out] error An optional location to return an error message if necessary. +/// +/// \return ADBC_STATUS_NOT_IMPLEMENTED if the driver only supports fetching results +/// as a stream, ADBC_STATUS_INVALID_STATE if called at an inappropriate time, and +/// ADBC_STATUS_OK (or an appropriate error code) otherwise. +AdbcStatusCode AdbcMultiResultSetNextPartitions(struct AdbcMultiResultSet* result_set, + struct ArrowSchema* schema, + struct AdbcPartitions* partitions, + int64_t* rows_affected, + struct AdbcError* error); /// @} +/// \brief A warning handler function. +/// +/// The handler must not block and must not call any ADBC functions (besides +/// releasing the warning). The warning does not need to be released before +/// returning, but the warning pointer itself may not be valid after the +/// handler returns. +/// +/// There are no requirements on ordering or concurrency of calls to the +/// handler; the driver may call the handler at any time from any thread, +/// including calling the handler concurrently. +/// +/// \param[in] warning The warning information. The application is +/// responsible for releasing the warning, but the warning pointer itself +/// may not be valid after the handler returns. +/// \param[in] user_data The user_data pointer. +typedef void (*AdbcWarningHandler)(const struct AdbcError* warning, void* user_data); + /// \defgroup adbc-driver Driver Initialization /// /// These functions are intended to help support integration between a @@ -1059,19 +1429,6 @@ struct ADBC_EXPORT AdbcDriver { /// 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, which will carry undefined values. - /// - /// 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. - /// /// @{ int (*ErrorGetDetailCount)(const struct AdbcError* error); @@ -1135,6 +1492,43 @@ struct ADBC_EXPORT AdbcDriver { struct AdbcError*); /// @} + + /// \defgroup adbc-1.2.0 ADBC API Revision 1.2.0 + /// + /// Functions added in ADBC 1.2.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_2_0. + /// + /// When the driver manager attempts to initialize a driver at a particular + /// version, such as the case where the driver manager and driver are using different + /// versions of the ADBC spec, the driver should not try to access any functions defined + /// in the spec after that version. + /// + /// @{ + + int (*AdbcErrorGetVendorCode)(const struct AdbcError*); + + AdbcStatusCode (*MultiResultSetNext)(struct AdbcMultiResultSet*, + struct ArrowArrayStream*, int64_t*, + struct AdbcError*); + AdbcStatusCode (*MultiResultSetNextPartitions)(struct AdbcMultiResultSet*, + struct ArrowSchema*, + struct AdbcPartitions*, int64_t*, + struct AdbcError*); + AdbcStatusCode (*MultiResultSetRelease)(struct AdbcMultiResultSet*, struct AdbcError*); + + AdbcStatusCode (*ConnectionSetWarningHandler)(struct AdbcConnection*, + AdbcWarningHandler handler, + void* user_data, struct AdbcError*); + + AdbcStatusCode (*StatementExecuteSchemaMulti)(struct AdbcStatement*, + struct AdbcMultiResultSet*, + struct AdbcError*); + AdbcStatusCode (*StatementExecuteMulti)(struct AdbcStatement*, + struct AdbcMultiResultSet*, struct AdbcError*); + + /// @} }; /// \brief The size of the AdbcDriver structure in ADBC 1.0.0. @@ -1151,7 +1545,15 @@ struct ADBC_EXPORT AdbcDriver { /// ADBC_VERSION_1_1_0. /// /// \since ADBC API revision 1.1.0 -#define ADBC_DRIVER_1_1_0_SIZE (sizeof(struct AdbcDriver)) +#define ADBC_DRIVER_1_1_0_SIZE (offsetof(struct AdbcDriver, StatementExecuteMulti)) + +/// \brief The size of the AdbcDriver structure in ADBC 1.2.0. +/// Drivers written for ADBC 1.2.0 and later should never touch more +/// than this portion of an AdbcDriver struct when given +/// ADBC_VERSION_1_2_0. +/// +/// \since ADBC API revision 1.2.0 +#define ADBC_DRIVER_1_2_0_SIZE (sizeof(struct AdbcDriver)) /// @} @@ -1468,6 +1870,30 @@ ADBC_EXPORT AdbcStatusCode AdbcConnectionRelease(struct AdbcConnection* connection, struct AdbcError* error); +/// \brief Set a warning handler. +/// +/// May be set before or after AdbcConnectionInit. +/// +/// Drivers should not repeat warnings unnecessarily. For example, if a +/// warning is issued for a lossy conversion to Arrow data, ideally it would +/// be reported at most twice: once for the first occurrence, and/or a second +/// time at the end of the result set summarizing how many values were +/// affected. +/// +/// \since ADBC API revision 1.2.0 +/// \param[in] database The database. +/// \param[in] handler The warning handler to use; NULL removes the handler. +/// \param[in] user_data A user data pointer to be passed to the handler. +/// Must live at least until the connection is released or the warning +/// handler is replaced. +/// \param[out] error An optional location to return an error +/// message if necessary. +/// \return ADBC_STATUS_NOT_IMPLEMENTED if warning handlers are not supported +ADBC_EXPORT +AdbcStatusCode AdbcConnectionSetWarningHandler(struct AdbcConnection* connection, + AdbcWarningHandler handler, + void* user_data, struct AdbcError* error); + /// \brief Cancel the in-progress operation on a connection. /// /// This can be called during AdbcConnectionGetObjects (or similar), @@ -1622,20 +2048,58 @@ AdbcStatusCode AdbcConnectionGetInfo(struct AdbcConnection* connection, /// | constraint_type | utf8 not null | (1) | /// | constraint_column_names | list not null | (2) | /// | constraint_column_usage | list | (3) | -/// -/// 1. One of 'CHECK', 'FOREIGN KEY', 'PRIMARY KEY', or 'UNIQUE'. +/// | constraint_expression | utf8 | (4) | +/// | constraint_update_rule | int16 | (5) | +/// | constraint_delete_rule | int16 | (5) | +/// | constraint_enforced | bool | (6) | +/// | constraint_deferrability | int16 | (7) | +/// | constraint_match_type | int16 | (8) | +/// +/// 1. One of 'CHECK', 'FOREIGN KEY', 'PRIMARY KEY', or 'UNIQUE', or a +/// vendor-specific type. /// 2. The columns on the current table that are constrained, in /// order. /// 3. For FOREIGN KEY only, the referenced table and columns. +/// 4. [Since version 1.2.0] The vendor-specific definition of the constraint +/// (e.g. the SQL expression to be checked). This field is optional. +/// 5. [Since version 1.2.0] The action to be taken when the primary key is +/// updated or deleted. The value is one of the ADBC_CONSTRAINT_ACTION_ +/// constants. This field is optional. +/// 6. [Since version 1.2.0] Whether the constraint is currently enabled. +/// This field is optional. +/// 7. [Since version 1.2.0] Whether the constraint can be deferred, and if +/// so, whether it starts deferred. The value is one of the +/// ADBC_CONSTRAINT_DEFERRABLE_ constants or +/// ADBC_CONSTRAINT_NOT_DEFERRABLE. This field is optional. +/// 8. [Since version 1.2.0] How the foreign key constraint should be matched. +/// The value is one of the ADBC_CONSTRAINT_MATCH_ constants. This field +/// is optional. /// /// USAGE_SCHEMA is a Struct with fields: /// -/// | Field Name | Field Type | -/// |--------------------------|-------------------------| -/// | fk_catalog | utf8 | -/// | fk_db_schema | utf8 | -/// | fk_table | utf8 not null | -/// | fk_column_name | utf8 not null | +/// | Field Name | Field Type | Comments | +/// |--------------------------|-------------------------|----------| +/// | fk_catalog | utf8 | | +/// | fk_db_schema | utf8 | | +/// | fk_table | utf8 not null | | +/// | fk_column_name | utf8 not null | | +/// | fk_key_seq | int32 | (1) | +/// | fk_pk_name | utf8 | (2) | +/// +/// 1. [Since version 1.2.0] The ordinal position of the column within the +/// foreign key. If present, the driver should sort the rows on this +/// column. This field is optional. +/// 2. [Since version 1.2.0] The name of the referenced primary key. This +/// field is optional. +/// +/// Starting in version 1.2.0, optional fields were introduced to the schema. +/// Optional fields may not be present in the returned schema/data and +/// applications should check for their presence before using them. Drivers +/// may choose to include optional fields (with null values) even if not +/// supported, but are not required to. If an optional field is present, all +/// optional fields defined before it in the schema must be present (but the +/// values may still be null if the driver does not actually support that +/// field). /// /// This AdbcConnection must outlive the returned ArrowArrayStream. /// @@ -1670,6 +2134,360 @@ AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int d struct ArrowArrayStream* out, struct AdbcError* error); +/// \brief Fetch (catalog) metadata from the database. +/// +/// The metadata to fetch is defined by the `collection` parameter. The result +/// is an Arrow dataset with a schema defined by the collection. For example, +/// a client may request a list of tables in the database, or a list of +/// supported data types. Drivers may implement collections beyond those +/// defined by ADBC, but must use a vendor-specific prefix +/// (e.g. `postgresql.`) to avoid conflicts with future standardized +/// collections. Drivers must not use the `adbc.` prefix. +/// +/// The result may be filtered by `filters`, which is an array of (nullable) +/// strings. `num_filters` must be set to the number of filter arguments +/// passed. +/// +/// All drivers must implement a collection called "meta" (which is aliased to +/// NULL and blank string) that defines the available collections. See +/// ADBC_METADATA_COLLECTION_META. +/// +/// Drivers may add more fields at the end of standard schemas to reflect +/// vendor-specific metadata. Applications must access these using an offset +/// from the end of the schema and cannot assume that the index of the field +/// will remain stable. Drivers must add the fields at the end should prefix +/// field names with the vendor/driver name to differentiate them +/// (e.g. 'POSTGRESQL:owner'). +/// +/// Similarly, future standard revisions may add more fields to existing +/// standard schemas. Applications must not assume the number of fields is +/// fixed. +/// +/// This AdbcConnection must outlive the returned ArrowArrayStream. +/// +/// \param[in] connection The database connection. +/// \param[in] collection The collection to fetch. +/// \param[out] out The result set. +/// \param[out] error Error details, if an error occurs. +/// \since ADBC API revision 1.2.0 +ADBC_EXPORT +AdbcStatusCode AdbcConnectionGetMetadataCollection( + struct AdbcConnection* connection, const char* collection, size_t num_filters, + const char** filters, struct ArrowArrayStream* out, struct AdbcError* error); + +/// \brief The "meta" collection returns the available metadata collections. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | collection_name | utf8 not null | | +/// | collection_description | utf8 | | +/// | collection_schema | extension | | +/// | collection_filters | list | | +/// +/// FILTER_SCHEMA is a Struct with fields: +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | filter_description | utf8 | | +/// | required | bool not null | | +#define ADBC_METADATA_COLLECTION_META "meta" + +/// \brief The "catalogs" collection returns the catalogs defined in the +/// database. +/// +/// Some systems may not have the concept of catalogs, in which case this +/// collection should contain a single entry with an empty, non-null name. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | catalog_name | utf8 | | +/// | catalog_remarks | utf8 | (1) | +/// +/// (1) A description of the catalog. +/// +/// Filters: +/// 1. The catalog name to filter by. May be a search pattern. +#define ADBC_METADATA_COLLECTION_CATALOGS "catalogs" + +/// \brief The "schemas" collection returns the schemas defined in the +/// database. +/// +/// Some systems may not have the concept of schemas, in which case this +/// collection should contain a single entry per catalog with an empty, +/// non-null name. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | catalog_name | utf8 | (R) | +/// | db_schema_name | utf8 | | +/// | db_schema_remarks | utf8 | (1) | +/// +/// (R) This field is run-length encoded by default; it can be disabled via +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. +/// +/// (1) A description of the schema. +/// +/// Filters: +/// 1. The catalog name to filter by. May be a search pattern. +/// 2. The schema name to filter by. May be a search pattern. +#define ADBC_METADATA_COLLECTION_SCHEMAS "schemas" + +/// \brief The "tables" collection returns the tables defined in the +/// database. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | catalog_name | utf8 | (R) | +/// | db_schema_name | utf8 | (R) | +/// | table_name | utf8 not null | | +/// | table_type | utf8 not null | | +/// | table_definition | utf8 | (1) | +/// | table_remarks | utf8 | (2) | +/// | table_schema | extension | (3) | +/// +/// (R) This field is run-length encoded by default; it can be disabled via +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. +/// +/// (1) The table or view definition (e.g. the SQL DDL statement). +/// (2) A description of the table. +/// (3) The Arrow schema of the table, equivalent to +/// AdbcConnectionGetTableSchema. +/// +/// Filters: +/// 1. The catalog name to filter by. May be a search pattern. +/// 2. The schema name to filter by. May be a search pattern. +/// 3. The table name to filter by. May be a search pattern. +/// 4. The remaining arguments are a list of table types to filter by. If +/// omitted, then tables of all types will be returned. +#define ADBC_METADATA_COLLECTION_TABLES "tables" + +/// \brief The "columns" collection returns table columns. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | catalog_name | utf8 | (R) | +/// | db_schema_name | utf8 | (R) | +/// | table_name | utf8 not null | (R) | +/// | column_name | utf8 not null | | +/// | ordinal_position | int32 | (1) | +/// | remarks | utf8 | (2) | +/// | xdbc_data_type | int16 | (3) | +/// | xdbc_type_name | utf8 | (3) | +/// | xdbc_column_size | int32 | (3) | +/// | xdbc_decimal_digits | int16 | (3) | +/// | xdbc_num_prec_radix | int16 | (3) | +/// | xdbc_nullable | int16 | (3) | +/// | xdbc_column_def | utf8 | (3) | +/// | xdbc_sql_data_type | int16 | (3) | +/// | xdbc_datetime_sub | int16 | (3) | +/// | xdbc_char_octet_length | int32 | (3) | +/// | xdbc_is_nullable | utf8 | (3) | +/// | xdbc_scope_catalog | utf8 | (3) | +/// | xdbc_scope_schema | utf8 | (3) | +/// | xdbc_scope_table | utf8 | (3) | +/// | xdbc_is_autoincrement | bool | (3) | +/// | xdbc_is_generatedcolumn | bool | (3) | +/// | xdbc_source_data_type | bool | (3) | +/// +/// (R) This field is run-length encoded by default; it can be disabled via +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. +/// +/// 1. The column's ordinal position in the table (starting from 1). +/// 2. Database-specific description of the column. +/// 3. Optional value. Should be null if not supported by the driver. +/// xdbc_ values are meant to provide JDBC/ODBC-compatible metadata +/// in an agnostic manner. +/// +/// Filters: +/// 1. The catalog name to filter by. May be a search pattern. +/// 2. The schema name to filter by. May be a search pattern. +/// 3. The table name to filter by. May be a search pattern. +/// 4. The remaining arguments are a list of table types to filter by. If +/// omitted, then tables of all types will be returned. +#define ADBC_METADATA_COLLECTION_COLUMNS "columns" + +/// \brief The "imported_keys" collection, given a table, describes the +/// primary key(s) referenced by the given table's foreign key(s). +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|-------------------------|----------| +/// | pk_catalog_name | utf8 | | +/// | pk_schema_name | utf8 | | +/// | pk_table_name | utf8 not null | | +/// | pk_column_name | utf8 not null | | +/// | pk_name | utf8 | | +/// | fk_catalog_name | utf8 | | +/// | fk_schema_name | utf8 | | +/// | fk_table_name | utf8 not null | | +/// | fk_column_name | utf8 not null | | +/// | fk_name | utf8 | | +/// | key_seq | int16 | (1) | +/// | constraint_update_rule | int16 | (2) | +/// | constraint_delete_rule | int16 | (3) | +/// | constraint_enforced | bool | (3) | +/// | constraint_deferrability | int16 | (4) | +/// | constraint_match_type | int16 | (5) | +/// +/// 1. The 1-based index of the column pair within the foreign key (1 => first +/// column of the foreign key, 2 => second column of the foreign key, ...). +/// 2. If applicable, the action to be taken when the primary key is updated +/// or deleted. The value is one of the ADBC_CONSTRAINT_ACTION_ constants. +/// 3. Whether the constraint is currently enabled. +/// 4. Whether the constraint can be deferred, and if so, whether it starts +/// deferred. The value is one of the ADBC_CONSTRAINT_DEFERRABLE_ +/// constants or ADBC_CONSTRAINT_NOT_DEFERRABLE. +/// 5. How the foreign key constraint should be matched. The value is one of +/// the ADBC_CONSTRAINT_MATCH_ constants. +/// +/// Filters: +/// 1. The catalog of the foreign key table; required but may be NULL. +/// 2. The schema of the foreign key table; required but may be NULL. +/// 3. The name of the foreign key table; required. +#define ADBC_METADATA_COLLECTION_IMPORTED_KEYS "imported_keys" + +/// \brief The "exported_keys" collection, given a table, describes the +/// foreign key(s) referencing the given table's primary key(s). +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|-------------------------|----------| +/// | pk_catalog_name | utf8 | | +/// | pk_schema_name | utf8 | | +/// | pk_table_name | utf8 not null | | +/// | pk_column_name | utf8 not null | | +/// | pk_name | utf8 | | +/// | fk_catalog_name | utf8 | | +/// | fk_schema_name | utf8 | | +/// | fk_table_name | utf8 not null | | +/// | fk_column_name | utf8 not null | | +/// | fk_name | utf8 | | +/// | key_seq | int16 | (1) | +/// | constraint_update_rule | int16 | (2) | +/// | constraint_delete_rule | int16 | (3) | +/// | constraint_enforced | bool | (3) | +/// | constraint_deferrability | int16 | (4) | +/// | constraint_match_type | int16 | (5) | +/// +/// 1. The 1-based index of the column pair within the foreign key (1 => first +/// column of the foreign key, 2 => second column of the foreign key, ...). +/// 2. If applicable, the action to be taken when the primary key is updated +/// or deleted. The value is one of the ADBC_CONSTRAINT_ACTION_ constants. +/// 3. Whether the constraint is currently enabled. +/// 4. Whether the constraint can be deferred, and if so, whether it starts +/// deferred. The value is one of the ADBC_CONSTRAINT_DEFERRABLE_ +/// constants or ADBC_CONSTRAINT_NOT_DEFERRABLE. +/// 5. How the foreign key constraint should be matched. The value is one of +/// the ADBC_CONSTRAINT_MATCH_ constants. +/// +/// Filters: +/// 1. The catalog of the primary key table; required but may be NULL. +/// 2. The schema of the primary key table; required but may be NULL. +/// 3. The name of the primary key table; required. +#define ADBC_METADATA_COLLECTION_EXPORTED_KEYS "exported_keys" + +/// \brief The "cross_reference" collection, given a "parent" table and a +/// "foreign" table, describes the foreign key(s) in the "foreign" table +/// referencing the "parent" table's primary key(s) or unique columns. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|-------------------------|----------| +/// | pk_catalog_name | utf8 | | +/// | pk_schema_name | utf8 | | +/// | pk_table_name | utf8 not null | | +/// | pk_column_name | utf8 not null | | +/// | pk_name | utf8 | | +/// | fk_catalog_name | utf8 | | +/// | fk_schema_name | utf8 | | +/// | fk_table_name | utf8 not null | | +/// | fk_column_name | utf8 not null | | +/// | fk_name | utf8 | | +/// | key_seq | int16 | (1) | +/// | constraint_update_rule | int16 | (2) | +/// | constraint_delete_rule | int16 | (3) | +/// | constraint_enforced | bool | (3) | +/// | constraint_deferrability | int16 | (4) | +/// | constraint_match_type | int16 | (5) | +/// +/// 1. The 1-based index of the column pair within the foreign key (1 => first +/// column of the foreign key, 2 => second column of the foreign key, ...). +/// 2. If applicable, the action to be taken when the primary key is updated +/// or deleted. The value is one of the ADBC_CONSTRAINT_ACTION_ constants. +/// 3. Whether the constraint is currently enabled. +/// 4. Whether the constraint can be deferred, and if so, whether it starts +/// deferred. The value is one of the ADBC_CONSTRAINT_DEFERRABLE_ +/// constants or ADBC_CONSTRAINT_NOT_DEFERRABLE. +/// 5. How the foreign key constraint should be matched. The value is one of +/// the ADBC_CONSTRAINT_MATCH_ constants. +/// +/// Filters: +/// 1. The catalog of the parent table; required but may be NULL. +/// 2. The schema of the parent table; required but may be NULL. +/// 3. The name of the parent table; required. +/// 4. The catalog of the foreign table; required but may be NULL. +/// 5. The schema of the foreign table; required but may be NULL. +/// 6. The name of the foreign table; required. +#define ADBC_METADATA_COLLECTION_CROSS_REFERENCE "cross_reference" + +/// \brief The "constraints" collection describes constraints on the selected +/// tables: primary keys, foreign keys, unique columns, and check +/// constraints. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|-------------------------|----------| +/// | catalog_name | utf8 | (R) | +/// | schema_name | utf8 | (R) | +/// | table_name | utf8 not null | (R) | +/// | constraint_name | utf8 | | +/// | constraint_type | utf8 not null | (1) | +/// | constraint_column_names | list not null | (2) | +/// | constraint_expression | utf8 | (3) | +/// | constraint_update_rule | int16 | (4) | +/// | constraint_delete_rule | int16 | (4) | +/// | constraint_enforced | bool | (5) | +/// | constraint_deferrability | int16 | (6) | +/// | constraint_match_type | int16 | (7) | +/// +/// (R) This field is run-length encoded by default; it can be disabled via +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. +/// +/// 1. One of 'CHECK', 'FOREIGN KEY', 'PRIMARY KEY', or 'UNIQUE', or a +/// vendor-specific type. +/// 2. The columns on the current table that are constrained, in +/// order. +/// 3. The vendor-specific definition of the constraint (e.g. the SQL +/// expression to be checked). +/// 4. If applicable, the action to be taken when the primary key is updated +/// or deleted. The value is one of the ADBC_CONSTRAINT_ACTION_ constants. +/// 5. Whether the constraint is currently enabled. +/// 6. Whether the constraint can be deferred, and if so, whether it starts +/// deferred. The value is one of the ADBC_CONSTRAINT_DEFERRABLE_ +/// constants or ADBC_CONSTRAINT_NOT_DEFERRABLE. +/// 7. How the foreign key constraint should be matched. The value is one of +/// the ADBC_CONSTRAINT_MATCH_ constants. +#define ADBC_METADATA_COLLECTION_CONSTRAINTS "constraints" + +/// \brief The "namespaces" collection returns a level of namespaces defined +/// in the database. +/// +/// This API generally results in an "N+1" query pattern. This is intended for +/// systems that do not follow the SQL catalog-schema-table hierarchy. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | namespace_parent | list not null | | +/// | namespace_name | utf8 not null | | +/// +/// Filters: +/// 1. The namespace name to filter by. May be a search pattern. +/// 2. Variadic: the parent namespace(s) to filter by. If omitted, return all +/// top-level namespaces. +/// +/// To filter by parent namespaces but not by namespace name (i.e. to request +/// all namespaces within a certain namespace), pass NULL for the namespace +/// name and then the parent namespaces. For example, to request all +/// namespaces within "foo.bar", pass NULL, "foo", "bar". To request all +/// top-level namespaces, pass no filters (or equivalently, only NULL). +#define ADBC_METADATA_COLLECTION_NAMESPACES "namespaces" + /// \brief Get a string option of the connection. /// /// This must always be thread-safe (other operations are not), though @@ -2018,6 +2836,72 @@ AdbcStatusCode AdbcStatementExecuteQuery(struct AdbcStatement* statement, struct ArrowArrayStream* out, int64_t* rows_affected, struct AdbcError* error); +/// \defgroup adbc-statement-multi Multiple Result Set Execution +/// Some databases support executing a statement that returns multiple +/// result sets. This section defines the API for working with such +/// statements and result sets. +/// @{ + +/// \brief Retrieve schema for statement that potentially returns multiple result sets +/// +/// \since ADBC API revision 1.2.0 +/// +/// This can be used to retrieve the schemas of all result sets without +/// executing the statement. If the driver does not support this, it should return +/// ADBC_STATUS_NOT_IMPLEMENTED. +/// +/// The ArrowArrayStream objects populated by calls to `MultiResultSetNext` with the +/// results struct returned by this function should have a valid schema but no data (i.e. +/// `get_next` should return EOS immediately). This allows clients to inspect the schemas +/// of all result sets before consuming any data, which can be useful for certain +/// applications such as query planning or UI display of results. +/// +/// \param[in] statement The statement to execute. +/// \param[out] results The result set struct to populate with the schemas of the result +/// sets. +/// \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, +/// and ADBC_STATUS_OK (or an appropriate error code) otherwise. +ADBC_EXPORT +AdbcStatusCode AdbcStatementExecuteSchemaMulti(struct AdbcStatement* statement, + struct AdbcMultiResultSet* results, + struct AdbcError* error); + +/// \brief Execute a statement that potentially returns multiple result sets +/// +/// \since ADBC API revision 1.2.0 +/// +/// To execute a statement which might potentially return multiple result sets, +/// this can be called in place of AdbcStatementExecuteQuery if the driver supports it. +/// If supported, the driver will populate the AdbcMultiResultSet structure with all +/// necessary information to iterate through the result sets. The caller can then +/// use the MultiResultSetNext or MultiResultSetNextPartitions functions on the +/// AdbcMultiResultSet struct to iterate through the result sets. +/// +/// A driver MAY support executing this function while the previous result set is +/// still being consumed (i.e. before the previous ArrowArrayStream is released), but +/// this is not required. If the driver does not support this, it should return +/// ADBC_STATUS_INVALID_STATE if the previous result set is still active. +/// +/// A driver implementing this function must also implement the AdbcMultiResultSet struct +/// and its associated functions. +/// +/// \param[in] statement The statement to execute. +/// \param[out] results The result set struct to populate with the results of the +/// execution. +/// \param[out] error An optional location to return an error message if necessary. +/// +/// \return ADBC_STATUS_NOT_IMPLEMENTED if the driver does not support multi-result set +/// execution, +/// and ADBC_STATUS_OK (or an appropriate error code) otherwise. +ADBC_EXPORT +AdbcStatusCode AdbcStatementExecuteMulti(struct AdbcStatement* statement, + struct AdbcMultiResultSet* results, + struct AdbcError* error); + +/// @} + /// \brief Get the schema of the result set of a query without /// executing it. /// diff --git a/go/adbc/drivermgr/arrow-adbc/adbc.h b/go/adbc/drivermgr/arrow-adbc/adbc.h index 57e665f84a..f9186e284d 100644 --- a/go/adbc/drivermgr/arrow-adbc/adbc.h +++ b/go/adbc/drivermgr/arrow-adbc/adbc.h @@ -355,6 +355,15 @@ struct ADBC_EXPORT AdbcError { /// \since ADBC API revision 1.1.0 #define ADBC_ERROR_1_1_0_SIZE (sizeof(struct AdbcError)) +/// \brief The size of the AdbcError structure in ADBC 1.2.0. +/// +/// Drivers written for ADBC 1.2.0 and later should never touch more than this +/// portion of an AdbcDriver struct when vendor_code is +/// ADBC_ERROR_VENDOR_CODE_PRIVATE_DATA. +/// +/// \since ADBC API revision 1.2.0 +#define ADBC_ERROR_1_2_0_SIZE (sizeof(struct AdbcError)) + /// \brief Extra key-value metadata for an error. /// /// The fields here are owned by the driver and should not be freed. The @@ -371,6 +380,13 @@ struct ADBC_EXPORT AdbcErrorDetail { size_t value_length; }; +/// \brief Get the vendor code for an error (since the vendor code field was +/// repurposed), or 0 if not available/not set. +/// +/// \since ADBC API revision 1.2.0 +ADBC_EXPORT +int AdbcErrorGetVendorCode(const struct AdbcError* error); + /// \brief Get the number of metadata values available in an error. /// /// \since ADBC API revision 1.1.0 @@ -423,6 +439,14 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream /// \since ADBC API revision 1.1.0 #define ADBC_VERSION_1_1_0 1001000 +/// \brief ADBC revision 1.2.0 +/// +/// When passed to an AdbcDriverInitFunc(), the driver parameter must +/// point to an AdbcDriver. +/// +/// \since ADBC API revision 1.2.0 +#define ADBC_VERSION_1_2_0 1002000 + /// \brief Canonical option value for enabling an option. /// /// For use as the value in SetOption calls. @@ -525,8 +549,144 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream /// \see AdbcConnectionGetInfo /// \see ADBC_VERSION_1_0_0 /// \see ADBC_VERSION_1_1_0 +/// \see ADBC_VERSION_1_2_0 #define ADBC_INFO_DRIVER_ADBC_VERSION 103 +/// \brief Whether the driver supports bulk ingest (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +#define ADBC_INFO_FEATURE_INGEST 200 + +/// \brief Supported bulk ingest modes (type: string list). +/// +/// Values are the mode constants themselves. +/// +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +#define ADBC_INFO_FEATURE_INGEST_MODES 201 + +/// \brief Whether the driver supports ingesting into a temporary table (type: +/// bool). +/// +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_INGEST_OPTION_TEMPORARY +#define ADBC_INFO_FEATURE_INGEST_TEMPORARY 202 + +/// \brief Whether the driver supports specifying the catalog of the table to +/// ingest into (type: bool). +/// +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_INGEST_OPTION_TARGET_CATALOG +#define ADBC_INFO_FEATURE_INGEST_TARGET_CATALOG 203 + +/// \brief Whether the driver supports specifying the catalog of the table to +/// ingest into (type: bool). +/// +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_INGEST_OPTION_TARGET_CATALOG +#define ADBC_INFO_FEATURE_INGEST_TARGET_SCHEMA 204 + +/// \brief Whether the driver supports getting catalog metadata (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcConnectionGetObjects +#define ADBC_INFO_FEATURE_OBJECTS 220 + +/// \brief Whether the driver supports getting table schemas (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcConnectionGetObjects +#define ADBC_INFO_FEATURE_TABLE_SCHEMA 221 + +/// \brief Whether the driver supports getting table types (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcConnectionGetObjects +#define ADBC_INFO_FEATURE_TABLE_TYPES 222 + +/// \brief Whether the driver supports transactions (true), or if autocommit +/// is always enabled (false) (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_CONNECTION_OPTION_AUTOCOMMIT +#define ADBC_INFO_FEATURE_TRANSACTIONS 240 + +/// \brief Whether the driver supports setting the isolation level of +/// transactions (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_CONNECTION_OPTION_ISOLATION_LEVEL +#define ADBC_INFO_FEATURE_TRANSACTION_ISOLATION_LEVEL 241 + +/// \brief Whether the driver supports getting statistics (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcConnectionGetStatistics +#define ADBC_INFO_FEATURE_STATISTICS 242 + +/// \brief Whether the driver supports getting/setting the current catalog +/// (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_CONNECTION_OPTION_CURRENT_CATALOG +#define ADBC_INFO_FEATURE_CURRENT_CATALOG 243 + +/// \brief Whether the driver supports getting/setting the current schema +/// (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see ADBC_CONNECTION_OPTION_CURRENT_CATALOG +#define ADBC_INFO_FEATURE_CURRENT_DB_SCHEMA 244 + +/// \brief Whether the driver supports binding data (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcStatementBind +/// \see AdbcStatementBindStream +#define ADBC_INFO_FEATURE_BIND 245 + +/// \brief Whether the driver supports partitioned execution (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcConnectionReadPartition +/// \see AdbcStatementExecutePartitions +#define ADBC_INFO_FEATURE_EXECUTE_PARTITIONS 246 + +/// \brief Whether the driver supports multiple result sets (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcStatementExecuteMulti +#define ADBC_INFO_FEATURE_EXECUTE_MULTI 247 + +/// \brief Whether the driver supports getting result set schemas (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcStatementExecuteSchema +/// \see AdbcStatementExecuteSchemaMulti +#define ADBC_INFO_FEATURE_EXECUTE_SCHEMA 248 + +/// \brief Whether the driver supports getting parameter schemas (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcStatementGetParameterSchema +#define ADBC_INFO_FEATURE_PARAMETER_SCHEMA 249 + +/// \brief Whether the driver supports getting error metadata (type: bool). +/// \since ADBC API revision 1.2.0 +/// \see AdbcConnectionGetInfo +/// \see AdbcErrorGetDetailCount +/// \see AdbcErrorGetDetail +/// \see AdbcErrorFromArrayStream +/// \see ADBC_ERROR_VENDOR_CODE_PRIVATE_DATA +#define ADBC_INFO_FEATURE_ERROR_METADATA 250 + +/// \defgroup adbc-catalog-metadata ADBC Catalog Metadata Constants +/// Constants for catalog metadata. +/// @{ + /// \brief Return metadata on catalogs, schemas, tables, and columns. /// /// \see AdbcConnectionGetObjects @@ -552,6 +712,88 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream /// \see AdbcConnectionGetObjects #define ADBC_OBJECT_DEPTH_COLUMNS ADBC_OBJECT_DEPTH_ALL +/// \brief This foreign key does not allow update of the corresponding primary +/// key. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeyNoAction`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_ACTION_NO_ACTION 3 + +/// \brief This foreign key will be updated/deleted with corresponding primary +/// key. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeyCascade`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_ACTION_CASCADE 0 + +/// \brief This foreign key will be set to NULL if its corresponding primary +/// key is updated or deleted. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeySetNull`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_ACTION_SET_NULL 2 + +/// \brief This foreign key will be set to its default if its corresponding +/// primary key is updated or deleted. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeySetDefault`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_ACTION_SET_DEFAULT 4 + +/// \brief Similar to ADBC_CONSTRAINT_ACTION_NO_ACTION but may be interpreted +/// differently by the vendor (e.g., raise an error immediately instead of +/// allowing the check to be deferred). +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeyRestrict`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_ACTION_RESTRICT 1 + +/// \brief This constraint is deferrable, and is initially deferred. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeyInitiallyDeferred`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_DEFERRABLE_DEFERRED 5 + +/// \brief This constraint is deferrable, but is initially immediate. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeyInitiallyImmediate`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_DEFERRABLE_IMMEDIATE 6 + +/// \brief This constraint may not be deferred. +/// +/// \note Value corresponds to JDBC `DatabaseMetaData#importedKeyNotDeferrable`. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_NOT_DEFERRABLE 7 + +/// \brief This foreign key allows any of the foreign key columns to be NULL; +/// if so, no match is required in the referenced table. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_MATCH_SIMPLE 0 + +/// \brief This foreign key only allows foreign key columns to be NULL if all +/// of them are NULL; if so, no match is required in the referenced table. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_MATCH_FULL 1 + +/// \brief This foreign key allows any of the foreign key columns to be NULL; +/// if so, non-NULL columns must still match. +/// +/// \see AdbcConnectionGetObjects +#define ADBC_CONSTRAINT_MATCH_PARTIAL 2 + +/// @} + /// \defgroup adbc-table-statistics ADBC Statistic Types /// Standard statistic names for AdbcConnectionGetStatistics. /// @{ @@ -647,6 +889,18 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream /// \since ADBC API revision 1.1.0 #define ADBC_CONNECTION_OPTION_CURRENT_DB_SCHEMA "adbc.connection.db_schema" +/// \brief Whether to run-length-encode common fields within standard metadata +/// collections. +/// +/// The type is boolean. The default is to run-length-encode. +/// +/// \see AdbcConnectionGetMetadataCollection +/// \see AdbcConnectionSetOption +/// \see AdbcConnectionSetOption +/// \since ADBC API revision 1.2.0 +#define ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE \ + "adbc.connection.metadata_collection.run_length_encoded" + /// \brief The name of the canonical option for making query execution /// nonblocking. /// @@ -971,8 +1225,124 @@ struct AdbcPartitions { /// @} +/// \defgroup adbc-statement-multi Multiple Result Set Execution +/// Some databases support executing a statement that returns multiple +/// result sets. This section defines the API for working with such +/// statements and result sets. +/// @{ + +/// \brief A struct for handling a potentially multi-result set execution +/// +/// This struct is populated by AdbcStatementExecuteMulti and can be used to iterate +/// through the result sets of the execution. The caller can use the MultiResultSetNext +/// or MultiResultSetNextPartitions functions on the AdbcMultiResultSet struct to iterate +/// through the result sets. The caller is responsible for calling the release function +/// when finished with the result set. +/// +/// \since ADBC API revision 1.2.0 +struct ADBC_EXPORT AdbcMultiResultSet { + /// \brief opaque implementation-defined state + void* private_data; + + /// \brief The associated driver + struct AdbcDriver* private_driver; +}; + +/// \brief Release the AdbcMultiResultSet and any associated resources. +/// +/// \since ADBC API revision 1.2.0 +/// +/// If all the result sets have not been completely consumed, then the driver +/// should cancel any remaining work if this is called. +/// +/// \param[in] result_set The result set to release. +/// \param[out] error An optional location to return an error message if necessary. +/// +/// \return ADBC_STATUS_OK on success or an appropriate error code. +AdbcStatusCode AdbcMultiResultSetRelease(struct AdbcMultiResultSet* result_set, + struct AdbcError* error); + +/// \brief Get the next ArrowArrayStream from an AdbcMultiResultSet. +/// +/// \since ADBC API revision 1.2.0 +/// +/// The driver can decide whether to allow fetching the next result set +/// as a single stream or as a set of partitions. If the driver does not +/// support fetching the next result set as a stream (indicating it should +/// be fetched as partitions), it should return ADBC_STATUS_NOT_IMPLEMENTED. +/// +/// To indicate that no additional result sets are available, this should return +/// ADBC_STATUS_OK and set the release callback on out to NULL. The expected +/// pattern is that after calling `StatementExecuteMulti`, the caller would +/// then call `MultiResultSetNext` repeatedly until it returns ADBC_STATUS_OK and +/// sets the release callback to NULL, indicating that there are no more result sets. +/// It is not an error to repeatedly call `MultiResultSetNext` after the last result set +/// has been reached; it should simply continue to return ADBC_STATUS_OK with a +/// NULL release callback. +/// +/// \param[in] result_set The result set struct to fetch the next result from. +/// \param[out] out The result stream to populate +/// \param[out] rows_affected The number of rows affected if known, else - +/// \param[out] error An optional location to return an error message if necessary. +/// +/// \return ADBC_STATUS_NOT_IMPLEMENTED if the driver only supports fetching results +/// as partitions or ADBC_STATUS_OK (or an appropriate error code) otherwise. +AdbcStatusCode AdbcMultiResultSetNext(struct AdbcMultiResultSet* result_set, + struct ArrowArrayStream* out, + int64_t* rows_affected, struct AdbcError* error); + +/// \brief Get the next result set from a multi-result-set execution as partitions. +/// +/// \since ADBC API revision 1.2.0 +/// +/// The driver can decide whether to allow fetching the next result set +/// as a single stream or as a set of partitions. If the driver does not +/// support fetching the next result set as partitions (indicating it should +/// be fetched as a stream), it should return ADBC_STATUS_NOT_IMPLEMENTED. +/// +/// To indicate that no additional result sets are available, this should return +/// ADBC_STATUS_OK and set the release callback on partitions to NULL. The expected +/// pattern is that after calling `StatementExecuteMulti`, the caller would +/// then call `MultiResultSetNextPartitions` repeatedly until it returns ADBC_STATUS_OK +/// and sets the release callback to NULL, indicating that there are no more result sets. +/// It is not an error to repeatedly call `MultiResultSetNextPartitions` after the last +/// result set has been reached; it should simply continue to return ADBC_STATUS_OK with +/// a NULL release callback. +/// +/// \param[in] result_set The result set struct to fetch the next result from. +/// \param[out] schema The schema of the result set to populate +/// \param[out] partitions The partitions to populate +/// \param[out] rows_affected The number of rows affected if known, else -1. Pass NULL +/// if the client does not want this information. +/// \param[out] error An optional location to return an error message if necessary. +/// +/// \return ADBC_STATUS_NOT_IMPLEMENTED if the driver only supports fetching results +/// as a stream, ADBC_STATUS_INVALID_STATE if called at an inappropriate time, and +/// ADBC_STATUS_OK (or an appropriate error code) otherwise. +AdbcStatusCode AdbcMultiResultSetNextPartitions(struct AdbcMultiResultSet* result_set, + struct ArrowSchema* schema, + struct AdbcPartitions* partitions, + int64_t* rows_affected, + struct AdbcError* error); /// @} +/// \brief A warning handler function. +/// +/// The handler must not block and must not call any ADBC functions (besides +/// releasing the warning). The warning does not need to be released before +/// returning, but the warning pointer itself may not be valid after the +/// handler returns. +/// +/// There are no requirements on ordering or concurrency of calls to the +/// handler; the driver may call the handler at any time from any thread, +/// including calling the handler concurrently. +/// +/// \param[in] warning The warning information. The application is +/// responsible for releasing the warning, but the warning pointer itself +/// may not be valid after the handler returns. +/// \param[in] user_data The user_data pointer. +typedef void (*AdbcWarningHandler)(const struct AdbcError* warning, void* user_data); + /// \defgroup adbc-driver Driver Initialization /// /// These functions are intended to help support integration between a @@ -1059,19 +1429,6 @@ struct ADBC_EXPORT AdbcDriver { /// 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, which will carry undefined values. - /// - /// 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. - /// /// @{ int (*ErrorGetDetailCount)(const struct AdbcError* error); @@ -1135,6 +1492,43 @@ struct ADBC_EXPORT AdbcDriver { struct AdbcError*); /// @} + + /// \defgroup adbc-1.2.0 ADBC API Revision 1.2.0 + /// + /// Functions added in ADBC 1.2.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_2_0. + /// + /// When the driver manager attempts to initialize a driver at a particular + /// version, such as the case where the driver manager and driver are using different + /// versions of the ADBC spec, the driver should not try to access any functions defined + /// in the spec after that version. + /// + /// @{ + + int (*AdbcErrorGetVendorCode)(const struct AdbcError*); + + AdbcStatusCode (*MultiResultSetNext)(struct AdbcMultiResultSet*, + struct ArrowArrayStream*, int64_t*, + struct AdbcError*); + AdbcStatusCode (*MultiResultSetNextPartitions)(struct AdbcMultiResultSet*, + struct ArrowSchema*, + struct AdbcPartitions*, int64_t*, + struct AdbcError*); + AdbcStatusCode (*MultiResultSetRelease)(struct AdbcMultiResultSet*, struct AdbcError*); + + AdbcStatusCode (*ConnectionSetWarningHandler)(struct AdbcConnection*, + AdbcWarningHandler handler, + void* user_data, struct AdbcError*); + + AdbcStatusCode (*StatementExecuteSchemaMulti)(struct AdbcStatement*, + struct AdbcMultiResultSet*, + struct AdbcError*); + AdbcStatusCode (*StatementExecuteMulti)(struct AdbcStatement*, + struct AdbcMultiResultSet*, struct AdbcError*); + + /// @} }; /// \brief The size of the AdbcDriver structure in ADBC 1.0.0. @@ -1151,7 +1545,15 @@ struct ADBC_EXPORT AdbcDriver { /// ADBC_VERSION_1_1_0. /// /// \since ADBC API revision 1.1.0 -#define ADBC_DRIVER_1_1_0_SIZE (sizeof(struct AdbcDriver)) +#define ADBC_DRIVER_1_1_0_SIZE (offsetof(struct AdbcDriver, StatementExecuteMulti)) + +/// \brief The size of the AdbcDriver structure in ADBC 1.2.0. +/// Drivers written for ADBC 1.2.0 and later should never touch more +/// than this portion of an AdbcDriver struct when given +/// ADBC_VERSION_1_2_0. +/// +/// \since ADBC API revision 1.2.0 +#define ADBC_DRIVER_1_2_0_SIZE (sizeof(struct AdbcDriver)) /// @} @@ -1468,6 +1870,30 @@ ADBC_EXPORT AdbcStatusCode AdbcConnectionRelease(struct AdbcConnection* connection, struct AdbcError* error); +/// \brief Set a warning handler. +/// +/// May be set before or after AdbcConnectionInit. +/// +/// Drivers should not repeat warnings unnecessarily. For example, if a +/// warning is issued for a lossy conversion to Arrow data, ideally it would +/// be reported at most twice: once for the first occurrence, and/or a second +/// time at the end of the result set summarizing how many values were +/// affected. +/// +/// \since ADBC API revision 1.2.0 +/// \param[in] database The database. +/// \param[in] handler The warning handler to use; NULL removes the handler. +/// \param[in] user_data A user data pointer to be passed to the handler. +/// Must live at least until the connection is released or the warning +/// handler is replaced. +/// \param[out] error An optional location to return an error +/// message if necessary. +/// \return ADBC_STATUS_NOT_IMPLEMENTED if warning handlers are not supported +ADBC_EXPORT +AdbcStatusCode AdbcConnectionSetWarningHandler(struct AdbcConnection* connection, + AdbcWarningHandler handler, + void* user_data, struct AdbcError* error); + /// \brief Cancel the in-progress operation on a connection. /// /// This can be called during AdbcConnectionGetObjects (or similar), @@ -1622,20 +2048,58 @@ AdbcStatusCode AdbcConnectionGetInfo(struct AdbcConnection* connection, /// | constraint_type | utf8 not null | (1) | /// | constraint_column_names | list not null | (2) | /// | constraint_column_usage | list | (3) | -/// -/// 1. One of 'CHECK', 'FOREIGN KEY', 'PRIMARY KEY', or 'UNIQUE'. +/// | constraint_expression | utf8 | (4) | +/// | constraint_update_rule | int16 | (5) | +/// | constraint_delete_rule | int16 | (5) | +/// | constraint_enforced | bool | (6) | +/// | constraint_deferrability | int16 | (7) | +/// | constraint_match_type | int16 | (8) | +/// +/// 1. One of 'CHECK', 'FOREIGN KEY', 'PRIMARY KEY', or 'UNIQUE', or a +/// vendor-specific type. /// 2. The columns on the current table that are constrained, in /// order. /// 3. For FOREIGN KEY only, the referenced table and columns. +/// 4. [Since version 1.2.0] The vendor-specific definition of the constraint +/// (e.g. the SQL expression to be checked). This field is optional. +/// 5. [Since version 1.2.0] The action to be taken when the primary key is +/// updated or deleted. The value is one of the ADBC_CONSTRAINT_ACTION_ +/// constants. This field is optional. +/// 6. [Since version 1.2.0] Whether the constraint is currently enabled. +/// This field is optional. +/// 7. [Since version 1.2.0] Whether the constraint can be deferred, and if +/// so, whether it starts deferred. The value is one of the +/// ADBC_CONSTRAINT_DEFERRABLE_ constants or +/// ADBC_CONSTRAINT_NOT_DEFERRABLE. This field is optional. +/// 8. [Since version 1.2.0] How the foreign key constraint should be matched. +/// The value is one of the ADBC_CONSTRAINT_MATCH_ constants. This field +/// is optional. /// /// USAGE_SCHEMA is a Struct with fields: /// -/// | Field Name | Field Type | -/// |--------------------------|-------------------------| -/// | fk_catalog | utf8 | -/// | fk_db_schema | utf8 | -/// | fk_table | utf8 not null | -/// | fk_column_name | utf8 not null | +/// | Field Name | Field Type | Comments | +/// |--------------------------|-------------------------|----------| +/// | fk_catalog | utf8 | | +/// | fk_db_schema | utf8 | | +/// | fk_table | utf8 not null | | +/// | fk_column_name | utf8 not null | | +/// | fk_key_seq | int32 | (1) | +/// | fk_pk_name | utf8 | (2) | +/// +/// 1. [Since version 1.2.0] The ordinal position of the column within the +/// foreign key. If present, the driver should sort the rows on this +/// column. This field is optional. +/// 2. [Since version 1.2.0] The name of the referenced primary key. This +/// field is optional. +/// +/// Starting in version 1.2.0, optional fields were introduced to the schema. +/// Optional fields may not be present in the returned schema/data and +/// applications should check for their presence before using them. Drivers +/// may choose to include optional fields (with null values) even if not +/// supported, but are not required to. If an optional field is present, all +/// optional fields defined before it in the schema must be present (but the +/// values may still be null if the driver does not actually support that +/// field). /// /// This AdbcConnection must outlive the returned ArrowArrayStream. /// @@ -1670,6 +2134,360 @@ AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int d struct ArrowArrayStream* out, struct AdbcError* error); +/// \brief Fetch (catalog) metadata from the database. +/// +/// The metadata to fetch is defined by the `collection` parameter. The result +/// is an Arrow dataset with a schema defined by the collection. For example, +/// a client may request a list of tables in the database, or a list of +/// supported data types. Drivers may implement collections beyond those +/// defined by ADBC, but must use a vendor-specific prefix +/// (e.g. `postgresql.`) to avoid conflicts with future standardized +/// collections. Drivers must not use the `adbc.` prefix. +/// +/// The result may be filtered by `filters`, which is an array of (nullable) +/// strings. `num_filters` must be set to the number of filter arguments +/// passed. +/// +/// All drivers must implement a collection called "meta" (which is aliased to +/// NULL and blank string) that defines the available collections. See +/// ADBC_METADATA_COLLECTION_META. +/// +/// Drivers may add more fields at the end of standard schemas to reflect +/// vendor-specific metadata. Applications must access these using an offset +/// from the end of the schema and cannot assume that the index of the field +/// will remain stable. Drivers must add the fields at the end should prefix +/// field names with the vendor/driver name to differentiate them +/// (e.g. 'POSTGRESQL:owner'). +/// +/// Similarly, future standard revisions may add more fields to existing +/// standard schemas. Applications must not assume the number of fields is +/// fixed. +/// +/// This AdbcConnection must outlive the returned ArrowArrayStream. +/// +/// \param[in] connection The database connection. +/// \param[in] collection The collection to fetch. +/// \param[out] out The result set. +/// \param[out] error Error details, if an error occurs. +/// \since ADBC API revision 1.2.0 +ADBC_EXPORT +AdbcStatusCode AdbcConnectionGetMetadataCollection( + struct AdbcConnection* connection, const char* collection, size_t num_filters, + const char** filters, struct ArrowArrayStream* out, struct AdbcError* error); + +/// \brief The "meta" collection returns the available metadata collections. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | collection_name | utf8 not null | | +/// | collection_description | utf8 | | +/// | collection_schema | extension | | +/// | collection_filters | list | | +/// +/// FILTER_SCHEMA is a Struct with fields: +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | filter_description | utf8 | | +/// | required | bool not null | | +#define ADBC_METADATA_COLLECTION_META "meta" + +/// \brief The "catalogs" collection returns the catalogs defined in the +/// database. +/// +/// Some systems may not have the concept of catalogs, in which case this +/// collection should contain a single entry with an empty, non-null name. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | catalog_name | utf8 | | +/// | catalog_remarks | utf8 | (1) | +/// +/// (1) A description of the catalog. +/// +/// Filters: +/// 1. The catalog name to filter by. May be a search pattern. +#define ADBC_METADATA_COLLECTION_CATALOGS "catalogs" + +/// \brief The "schemas" collection returns the schemas defined in the +/// database. +/// +/// Some systems may not have the concept of schemas, in which case this +/// collection should contain a single entry per catalog with an empty, +/// non-null name. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | catalog_name | utf8 | (R) | +/// | db_schema_name | utf8 | | +/// | db_schema_remarks | utf8 | (1) | +/// +/// (R) This field is run-length encoded by default; it can be disabled via +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. +/// +/// (1) A description of the schema. +/// +/// Filters: +/// 1. The catalog name to filter by. May be a search pattern. +/// 2. The schema name to filter by. May be a search pattern. +#define ADBC_METADATA_COLLECTION_SCHEMAS "schemas" + +/// \brief The "tables" collection returns the tables defined in the +/// database. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | catalog_name | utf8 | (R) | +/// | db_schema_name | utf8 | (R) | +/// | table_name | utf8 not null | | +/// | table_type | utf8 not null | | +/// | table_definition | utf8 | (1) | +/// | table_remarks | utf8 | (2) | +/// | table_schema | extension | (3) | +/// +/// (R) This field is run-length encoded by default; it can be disabled via +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. +/// +/// (1) The table or view definition (e.g. the SQL DDL statement). +/// (2) A description of the table. +/// (3) The Arrow schema of the table, equivalent to +/// AdbcConnectionGetTableSchema. +/// +/// Filters: +/// 1. The catalog name to filter by. May be a search pattern. +/// 2. The schema name to filter by. May be a search pattern. +/// 3. The table name to filter by. May be a search pattern. +/// 4. The remaining arguments are a list of table types to filter by. If +/// omitted, then tables of all types will be returned. +#define ADBC_METADATA_COLLECTION_TABLES "tables" + +/// \brief The "columns" collection returns table columns. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | catalog_name | utf8 | (R) | +/// | db_schema_name | utf8 | (R) | +/// | table_name | utf8 not null | (R) | +/// | column_name | utf8 not null | | +/// | ordinal_position | int32 | (1) | +/// | remarks | utf8 | (2) | +/// | xdbc_data_type | int16 | (3) | +/// | xdbc_type_name | utf8 | (3) | +/// | xdbc_column_size | int32 | (3) | +/// | xdbc_decimal_digits | int16 | (3) | +/// | xdbc_num_prec_radix | int16 | (3) | +/// | xdbc_nullable | int16 | (3) | +/// | xdbc_column_def | utf8 | (3) | +/// | xdbc_sql_data_type | int16 | (3) | +/// | xdbc_datetime_sub | int16 | (3) | +/// | xdbc_char_octet_length | int32 | (3) | +/// | xdbc_is_nullable | utf8 | (3) | +/// | xdbc_scope_catalog | utf8 | (3) | +/// | xdbc_scope_schema | utf8 | (3) | +/// | xdbc_scope_table | utf8 | (3) | +/// | xdbc_is_autoincrement | bool | (3) | +/// | xdbc_is_generatedcolumn | bool | (3) | +/// | xdbc_source_data_type | bool | (3) | +/// +/// (R) This field is run-length encoded by default; it can be disabled via +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. +/// +/// 1. The column's ordinal position in the table (starting from 1). +/// 2. Database-specific description of the column. +/// 3. Optional value. Should be null if not supported by the driver. +/// xdbc_ values are meant to provide JDBC/ODBC-compatible metadata +/// in an agnostic manner. +/// +/// Filters: +/// 1. The catalog name to filter by. May be a search pattern. +/// 2. The schema name to filter by. May be a search pattern. +/// 3. The table name to filter by. May be a search pattern. +/// 4. The remaining arguments are a list of table types to filter by. If +/// omitted, then tables of all types will be returned. +#define ADBC_METADATA_COLLECTION_COLUMNS "columns" + +/// \brief The "imported_keys" collection, given a table, describes the +/// primary key(s) referenced by the given table's foreign key(s). +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|-------------------------|----------| +/// | pk_catalog_name | utf8 | | +/// | pk_schema_name | utf8 | | +/// | pk_table_name | utf8 not null | | +/// | pk_column_name | utf8 not null | | +/// | pk_name | utf8 | | +/// | fk_catalog_name | utf8 | | +/// | fk_schema_name | utf8 | | +/// | fk_table_name | utf8 not null | | +/// | fk_column_name | utf8 not null | | +/// | fk_name | utf8 | | +/// | key_seq | int16 | (1) | +/// | constraint_update_rule | int16 | (2) | +/// | constraint_delete_rule | int16 | (3) | +/// | constraint_enforced | bool | (3) | +/// | constraint_deferrability | int16 | (4) | +/// | constraint_match_type | int16 | (5) | +/// +/// 1. The 1-based index of the column pair within the foreign key (1 => first +/// column of the foreign key, 2 => second column of the foreign key, ...). +/// 2. If applicable, the action to be taken when the primary key is updated +/// or deleted. The value is one of the ADBC_CONSTRAINT_ACTION_ constants. +/// 3. Whether the constraint is currently enabled. +/// 4. Whether the constraint can be deferred, and if so, whether it starts +/// deferred. The value is one of the ADBC_CONSTRAINT_DEFERRABLE_ +/// constants or ADBC_CONSTRAINT_NOT_DEFERRABLE. +/// 5. How the foreign key constraint should be matched. The value is one of +/// the ADBC_CONSTRAINT_MATCH_ constants. +/// +/// Filters: +/// 1. The catalog of the foreign key table; required but may be NULL. +/// 2. The schema of the foreign key table; required but may be NULL. +/// 3. The name of the foreign key table; required. +#define ADBC_METADATA_COLLECTION_IMPORTED_KEYS "imported_keys" + +/// \brief The "exported_keys" collection, given a table, describes the +/// foreign key(s) referencing the given table's primary key(s). +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|-------------------------|----------| +/// | pk_catalog_name | utf8 | | +/// | pk_schema_name | utf8 | | +/// | pk_table_name | utf8 not null | | +/// | pk_column_name | utf8 not null | | +/// | pk_name | utf8 | | +/// | fk_catalog_name | utf8 | | +/// | fk_schema_name | utf8 | | +/// | fk_table_name | utf8 not null | | +/// | fk_column_name | utf8 not null | | +/// | fk_name | utf8 | | +/// | key_seq | int16 | (1) | +/// | constraint_update_rule | int16 | (2) | +/// | constraint_delete_rule | int16 | (3) | +/// | constraint_enforced | bool | (3) | +/// | constraint_deferrability | int16 | (4) | +/// | constraint_match_type | int16 | (5) | +/// +/// 1. The 1-based index of the column pair within the foreign key (1 => first +/// column of the foreign key, 2 => second column of the foreign key, ...). +/// 2. If applicable, the action to be taken when the primary key is updated +/// or deleted. The value is one of the ADBC_CONSTRAINT_ACTION_ constants. +/// 3. Whether the constraint is currently enabled. +/// 4. Whether the constraint can be deferred, and if so, whether it starts +/// deferred. The value is one of the ADBC_CONSTRAINT_DEFERRABLE_ +/// constants or ADBC_CONSTRAINT_NOT_DEFERRABLE. +/// 5. How the foreign key constraint should be matched. The value is one of +/// the ADBC_CONSTRAINT_MATCH_ constants. +/// +/// Filters: +/// 1. The catalog of the primary key table; required but may be NULL. +/// 2. The schema of the primary key table; required but may be NULL. +/// 3. The name of the primary key table; required. +#define ADBC_METADATA_COLLECTION_EXPORTED_KEYS "exported_keys" + +/// \brief The "cross_reference" collection, given a "parent" table and a +/// "foreign" table, describes the foreign key(s) in the "foreign" table +/// referencing the "parent" table's primary key(s) or unique columns. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|-------------------------|----------| +/// | pk_catalog_name | utf8 | | +/// | pk_schema_name | utf8 | | +/// | pk_table_name | utf8 not null | | +/// | pk_column_name | utf8 not null | | +/// | pk_name | utf8 | | +/// | fk_catalog_name | utf8 | | +/// | fk_schema_name | utf8 | | +/// | fk_table_name | utf8 not null | | +/// | fk_column_name | utf8 not null | | +/// | fk_name | utf8 | | +/// | key_seq | int16 | (1) | +/// | constraint_update_rule | int16 | (2) | +/// | constraint_delete_rule | int16 | (3) | +/// | constraint_enforced | bool | (3) | +/// | constraint_deferrability | int16 | (4) | +/// | constraint_match_type | int16 | (5) | +/// +/// 1. The 1-based index of the column pair within the foreign key (1 => first +/// column of the foreign key, 2 => second column of the foreign key, ...). +/// 2. If applicable, the action to be taken when the primary key is updated +/// or deleted. The value is one of the ADBC_CONSTRAINT_ACTION_ constants. +/// 3. Whether the constraint is currently enabled. +/// 4. Whether the constraint can be deferred, and if so, whether it starts +/// deferred. The value is one of the ADBC_CONSTRAINT_DEFERRABLE_ +/// constants or ADBC_CONSTRAINT_NOT_DEFERRABLE. +/// 5. How the foreign key constraint should be matched. The value is one of +/// the ADBC_CONSTRAINT_MATCH_ constants. +/// +/// Filters: +/// 1. The catalog of the parent table; required but may be NULL. +/// 2. The schema of the parent table; required but may be NULL. +/// 3. The name of the parent table; required. +/// 4. The catalog of the foreign table; required but may be NULL. +/// 5. The schema of the foreign table; required but may be NULL. +/// 6. The name of the foreign table; required. +#define ADBC_METADATA_COLLECTION_CROSS_REFERENCE "cross_reference" + +/// \brief The "constraints" collection describes constraints on the selected +/// tables: primary keys, foreign keys, unique columns, and check +/// constraints. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|-------------------------|----------| +/// | catalog_name | utf8 | (R) | +/// | schema_name | utf8 | (R) | +/// | table_name | utf8 not null | (R) | +/// | constraint_name | utf8 | | +/// | constraint_type | utf8 not null | (1) | +/// | constraint_column_names | list not null | (2) | +/// | constraint_expression | utf8 | (3) | +/// | constraint_update_rule | int16 | (4) | +/// | constraint_delete_rule | int16 | (4) | +/// | constraint_enforced | bool | (5) | +/// | constraint_deferrability | int16 | (6) | +/// | constraint_match_type | int16 | (7) | +/// +/// (R) This field is run-length encoded by default; it can be disabled via +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. +/// +/// 1. One of 'CHECK', 'FOREIGN KEY', 'PRIMARY KEY', or 'UNIQUE', or a +/// vendor-specific type. +/// 2. The columns on the current table that are constrained, in +/// order. +/// 3. The vendor-specific definition of the constraint (e.g. the SQL +/// expression to be checked). +/// 4. If applicable, the action to be taken when the primary key is updated +/// or deleted. The value is one of the ADBC_CONSTRAINT_ACTION_ constants. +/// 5. Whether the constraint is currently enabled. +/// 6. Whether the constraint can be deferred, and if so, whether it starts +/// deferred. The value is one of the ADBC_CONSTRAINT_DEFERRABLE_ +/// constants or ADBC_CONSTRAINT_NOT_DEFERRABLE. +/// 7. How the foreign key constraint should be matched. The value is one of +/// the ADBC_CONSTRAINT_MATCH_ constants. +#define ADBC_METADATA_COLLECTION_CONSTRAINTS "constraints" + +/// \brief The "namespaces" collection returns a level of namespaces defined +/// in the database. +/// +/// This API generally results in an "N+1" query pattern. This is intended for +/// systems that do not follow the SQL catalog-schema-table hierarchy. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | namespace_parent | list not null | | +/// | namespace_name | utf8 not null | | +/// +/// Filters: +/// 1. The namespace name to filter by. May be a search pattern. +/// 2. Variadic: the parent namespace(s) to filter by. If omitted, return all +/// top-level namespaces. +/// +/// To filter by parent namespaces but not by namespace name (i.e. to request +/// all namespaces within a certain namespace), pass NULL for the namespace +/// name and then the parent namespaces. For example, to request all +/// namespaces within "foo.bar", pass NULL, "foo", "bar". To request all +/// top-level namespaces, pass no filters (or equivalently, only NULL). +#define ADBC_METADATA_COLLECTION_NAMESPACES "namespaces" + /// \brief Get a string option of the connection. /// /// This must always be thread-safe (other operations are not), though @@ -2018,6 +2836,72 @@ AdbcStatusCode AdbcStatementExecuteQuery(struct AdbcStatement* statement, struct ArrowArrayStream* out, int64_t* rows_affected, struct AdbcError* error); +/// \defgroup adbc-statement-multi Multiple Result Set Execution +/// Some databases support executing a statement that returns multiple +/// result sets. This section defines the API for working with such +/// statements and result sets. +/// @{ + +/// \brief Retrieve schema for statement that potentially returns multiple result sets +/// +/// \since ADBC API revision 1.2.0 +/// +/// This can be used to retrieve the schemas of all result sets without +/// executing the statement. If the driver does not support this, it should return +/// ADBC_STATUS_NOT_IMPLEMENTED. +/// +/// The ArrowArrayStream objects populated by calls to `MultiResultSetNext` with the +/// results struct returned by this function should have a valid schema but no data (i.e. +/// `get_next` should return EOS immediately). This allows clients to inspect the schemas +/// of all result sets before consuming any data, which can be useful for certain +/// applications such as query planning or UI display of results. +/// +/// \param[in] statement The statement to execute. +/// \param[out] results The result set struct to populate with the schemas of the result +/// sets. +/// \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, +/// and ADBC_STATUS_OK (or an appropriate error code) otherwise. +ADBC_EXPORT +AdbcStatusCode AdbcStatementExecuteSchemaMulti(struct AdbcStatement* statement, + struct AdbcMultiResultSet* results, + struct AdbcError* error); + +/// \brief Execute a statement that potentially returns multiple result sets +/// +/// \since ADBC API revision 1.2.0 +/// +/// To execute a statement which might potentially return multiple result sets, +/// this can be called in place of AdbcStatementExecuteQuery if the driver supports it. +/// If supported, the driver will populate the AdbcMultiResultSet structure with all +/// necessary information to iterate through the result sets. The caller can then +/// use the MultiResultSetNext or MultiResultSetNextPartitions functions on the +/// AdbcMultiResultSet struct to iterate through the result sets. +/// +/// A driver MAY support executing this function while the previous result set is +/// still being consumed (i.e. before the previous ArrowArrayStream is released), but +/// this is not required. If the driver does not support this, it should return +/// ADBC_STATUS_INVALID_STATE if the previous result set is still active. +/// +/// A driver implementing this function must also implement the AdbcMultiResultSet struct +/// and its associated functions. +/// +/// \param[in] statement The statement to execute. +/// \param[out] results The result set struct to populate with the results of the +/// execution. +/// \param[out] error An optional location to return an error message if necessary. +/// +/// \return ADBC_STATUS_NOT_IMPLEMENTED if the driver does not support multi-result set +/// execution, +/// and ADBC_STATUS_OK (or an appropriate error code) otherwise. +ADBC_EXPORT +AdbcStatusCode AdbcStatementExecuteMulti(struct AdbcStatement* statement, + struct AdbcMultiResultSet* results, + struct AdbcError* error); + +/// @} + /// \brief Get the schema of the result set of a query without /// executing it. /// diff --git a/r/adbcdrivermanager/src/radbc.cc b/r/adbcdrivermanager/src/radbc.cc index 3010c59643..8c70a894d6 100644 --- a/r/adbcdrivermanager/src/radbc.cc +++ b/r/adbcdrivermanager/src/radbc.cc @@ -105,7 +105,8 @@ extern "C" SEXP RAdbcAllocateDriver(void) { R_RegisterCFinalizer(driver_xptr, &finalize_driver_xptr); // Make sure we error when the ADBC spec is updated - static_assert(sizeof(AdbcDriver) == ADBC_DRIVER_1_1_0_SIZE); + static_assert(offsetof(struct AdbcDriver, StatementExecuteMulti) == + ADBC_DRIVER_1_1_0_SIZE); SEXP version_sexp = PROTECT(Rf_ScalarInteger(ADBC_VERSION_1_1_0)); const char* names[] = {"driver", "version", ""};