From 4248d7caacd703d4bc77f312387b2d60b82d24bc Mon Sep 17 00:00:00 2001 From: Matt Topol Date: Tue, 17 Feb 2026 21:36:29 -0500 Subject: [PATCH 1/5] feat: Spec multi-result-set API (#3871) Extracted from #3607 with influence by the comments there and https://github.com/apache/arrow-adbc/compare/main...CurtHagenlocher:arrow-adbc:MoreResults, this contains a proposal for handling multi-result set query execution via ADBC by adding a new function for drivers, `AdbcStatementNextResultSet`. This also includes the necessary changes for an ADBC API Revision 1.2.0 (macro defines and so on). The comment above the function includes all the semantic definitions of the behavior. --- .../adbc_version_100_compatibility_test.cc | 4 +- c/include/arrow-adbc/adbc.h | 238 ++++++++++++++++-- go/adbc/drivermgr/arrow-adbc/adbc.h | 238 ++++++++++++++++-- r/adbcdrivermanager/src/radbc.cc | 3 +- 4 files changed, 453 insertions(+), 30 deletions(-) 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..228c557b36 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 @@ -423,6 +432,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,6 +542,7 @@ 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 Return metadata on catalogs, schemas, tables, and columns. @@ -973,6 +991,107 @@ 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); +/// @} + /// \defgroup adbc-driver Driver Initialization /// /// These functions are intended to help support integration between a @@ -1059,19 +1178,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 +1241,36 @@ 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. + /// + /// @{ + + 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 (*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 +1287,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)) /// @} @@ -2018,6 +2162,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..228c557b36 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 @@ -423,6 +432,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,6 +542,7 @@ 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 Return metadata on catalogs, schemas, tables, and columns. @@ -973,6 +991,107 @@ 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); +/// @} + /// \defgroup adbc-driver Driver Initialization /// /// These functions are intended to help support integration between a @@ -1059,19 +1178,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 +1241,36 @@ 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. + /// + /// @{ + + 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 (*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 +1287,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)) /// @} @@ -2018,6 +2162,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", ""}; From 7db48f3e8d04a78f078eb402ce280868c9759dd5 Mon Sep 17 00:00:00 2001 From: David Li Date: Wed, 25 Feb 2026 17:00:08 +0900 Subject: [PATCH 2/5] feat(format): add AdbcConnectionSetWarningHandler (#3872) Closes #1243. --- c/include/arrow-adbc/adbc.h | 48 +++++++++++++++++++++++++++-- go/adbc/drivermgr/arrow-adbc/adbc.h | 48 +++++++++++++++++++++++++++-- 2 files changed, 92 insertions(+), 4 deletions(-) diff --git a/c/include/arrow-adbc/adbc.h b/c/include/arrow-adbc/adbc.h index 228c557b36..5982e31572 100644 --- a/c/include/arrow-adbc/adbc.h +++ b/c/include/arrow-adbc/adbc.h @@ -989,8 +989,6 @@ 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 @@ -1092,6 +1090,23 @@ AdbcStatusCode AdbcMultiResultSetNextPartitions(struct AdbcMultiResultSet* resul 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 @@ -1264,6 +1279,11 @@ struct ADBC_EXPORT AdbcDriver { 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*); @@ -1612,6 +1632,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), diff --git a/go/adbc/drivermgr/arrow-adbc/adbc.h b/go/adbc/drivermgr/arrow-adbc/adbc.h index 228c557b36..5982e31572 100644 --- a/go/adbc/drivermgr/arrow-adbc/adbc.h +++ b/go/adbc/drivermgr/arrow-adbc/adbc.h @@ -989,8 +989,6 @@ 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 @@ -1092,6 +1090,23 @@ AdbcStatusCode AdbcMultiResultSetNextPartitions(struct AdbcMultiResultSet* resul 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 @@ -1264,6 +1279,11 @@ struct ADBC_EXPORT AdbcDriver { 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*); @@ -1612,6 +1632,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), From d593a6872c6c1176410f43de1a8a52a0c4eb0b4c Mon Sep 17 00:00:00 2001 From: David Li Date: Tue, 3 Mar 2026 18:14:36 +0900 Subject: [PATCH 3/5] feat(format): add GetInfo codes for driver features (#4012) Closes #3791. --- c/include/arrow-adbc/adbc.h | 131 ++++++++++++++++++++++++++++ go/adbc/drivermgr/arrow-adbc/adbc.h | 131 ++++++++++++++++++++++++++++ 2 files changed, 262 insertions(+) diff --git a/c/include/arrow-adbc/adbc.h b/c/include/arrow-adbc/adbc.h index 5982e31572..3733daad17 100644 --- a/c/include/arrow-adbc/adbc.h +++ b/c/include/arrow-adbc/adbc.h @@ -545,6 +545,137 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream /// \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 + /// \brief Return metadata on catalogs, schemas, tables, and columns. /// /// \see AdbcConnectionGetObjects diff --git a/go/adbc/drivermgr/arrow-adbc/adbc.h b/go/adbc/drivermgr/arrow-adbc/adbc.h index 5982e31572..3733daad17 100644 --- a/go/adbc/drivermgr/arrow-adbc/adbc.h +++ b/go/adbc/drivermgr/arrow-adbc/adbc.h @@ -545,6 +545,137 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream /// \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 + /// \brief Return metadata on catalogs, schemas, tables, and columns. /// /// \see AdbcConnectionGetObjects From dca687dae9cfb9b9b02a12a5069067ea59b7bce8 Mon Sep 17 00:00:00 2001 From: David Li Date: Mon, 2 Mar 2026 09:56:05 +0900 Subject: [PATCH 4/5] feat(format): expose functions/procedures in catalog metadata Closes #3983. --- c/include/arrow-adbc/adbc.h | 90 +++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/c/include/arrow-adbc/adbc.h b/c/include/arrow-adbc/adbc.h index 3733daad17..ef8f81a9de 100644 --- a/c/include/arrow-adbc/adbc.h +++ b/c/include/arrow-adbc/adbc.h @@ -1989,6 +1989,96 @@ AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int d struct ArrowArrayStream* out, struct AdbcError* error); +/// \brief Get a hierarchical view of all functions and procedures. +/// +/// The result is an Arrow dataset with the following schema: +/// +/// | Field Name | Field Type | +/// |--------------------------|-------------------------| +/// | catalog_name | utf8 | +/// | catalog_db_schemas | list | +/// +/// DB_SCHEMA_SCHEMA is a Struct with fields: +/// +/// | Field Name | Field Type | +/// |--------------------------|-------------------------| +/// | db_schema_name | utf8 | +/// | db_schema_routines | list | +/// +/// ROUTINE_SCHEMA is a Struct with fields: +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|-------------------------|----------| +/// | routine_name | utf8 not null | | +/// | routine_specific_name | utf8 not null | (1) | +/// | routine_type | utf8 not null | (2) | +/// | routine_remarks | utf8 | (3) | +/// | routine_parameters | list | (4) | +/// | routine_result | list | (4) | +/// | routine_parameter_schema | binary | (5) | +/// | routine_result_schema | binary | (5) | +/// +/// 1. A name that uniquely identifies the routine, to disambiguate +/// overloads. +/// 2. 'FUNCTION', 'PROCEDURE', or a vendor-specific name (e.g. 'TABLE +/// FUNCTION'). +/// 3. Vendor-specific description of the routine. +/// 4. Metadata about the accepted parameters and return values as structured +/// Arrow data. Only populated if include_columns is set, otherwise null. +/// 5. Metadata about the accepted parameters and return values as an Arrow +/// schema, serialized as an IPC message containing a schema Flatbuffers +/// structure. Only populated if include_arrow_schema is set, otherwise +/// null. +/// +/// PARAMETER_SCHEMA is a Struct with fields: +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|-------------------------|----------| +/// | param_name | utf8 not null | | +/// | ordinal_position | int32 | (1) | +/// | remarks | utf8 | (2) | +/// | param_type | utf8 | (3) | +/// | xdbc_data_type | int16 | (3) | +/// | xdbc_type_name | utf8 | (3) | +/// | xdbc_precision | int32 | (3) | +/// | xdbc_length | int32 | (3) | +/// | xdbc_scale | int16 | (3) | +/// | xdbc_num_prec_radix | int16 | (3) | +/// | xdbc_nullable | int16 | (3) | +/// | xdbc_char_octet_length | int32 | (3) | +/// | xdbc_is_nullable | utf8 | (3) | +/// +/// 1. The ordinal position of the parameter or return value (1-indexed). +/// 2. Vendor-specific description of the parameter or return value. +/// 3. 'IN', 'OUT', 'INOUT', or a vendor-specific name. +/// 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. +/// +/// \param[in] connection The database connection. +/// \param[in] catalog Only show routines in the given catalog. If NULL, +/// do not filter by catalog. If an empty string, only show routines +/// without a catalog. May be a search pattern (see section +/// documentation). +/// \param[in] db_schema Only show routines in the given database schema. If +/// NULL, do not filter by database schema. If an empty string, only show +/// routines without a database schema. May be a search pattern (see section +/// documentation). +/// \param[in] routine_name Only show routines with the given name. If NULL, do not +/// filter by name. May be a search pattern (see section documentation). +/// \param[in] include_columns If non-zero, include (if applicable) metadata +/// about parameters and return values as structured data. +/// \param[in] include_arrow_schema If non-zero, include (if applicable) +/// metadata about parameters and return values as a serialized Arrow +/// schema. +/// \param[out] out The result set. +/// \param[out] error Error details, if an error occurs. +ADBC_EXPORT +AdbcStatusCode AdbcConnectionGetObjectsRoutines( + struct AdbcConnection* connection, const char* catalog, const char* db_schema, + const char* routine_name, int include_columns, int include_arrow_schema, + struct ArrowArrayStream* out, struct AdbcError* error); + /// \brief Get a string option of the connection. /// /// This must always be thread-safe (other operations are not), though From 005a9eecf84a8207630a50c1ef83d25ca2039499 Mon Sep 17 00:00:00 2001 From: David Li Date: Thu, 5 Mar 2026 16:51:36 +0900 Subject: [PATCH 5/5] add examples/definition --- c/include/arrow-adbc/adbc.h | 83 +++++++++++++---------- go/adbc/drivermgr/arrow-adbc/adbc.h | 101 ++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 36 deletions(-) diff --git a/c/include/arrow-adbc/adbc.h b/c/include/arrow-adbc/adbc.h index ef8f81a9de..3e52fda720 100644 --- a/c/include/arrow-adbc/adbc.h +++ b/c/include/arrow-adbc/adbc.h @@ -1411,6 +1411,10 @@ struct ADBC_EXPORT AdbcDriver { struct AdbcError*); AdbcStatusCode (*MultiResultSetRelease)(struct AdbcMultiResultSet*, struct AdbcError*); + AdbcStatusCode (*ConnectionGetObjectsRoutines)(struct AdbcConnection*, const char*, + const char*, const char*, int, int, + struct ArrowArrayStream*, + struct AdbcError*); AdbcStatusCode (*ConnectionSetWarningHandler)(struct AdbcConnection*, AdbcWarningHandler handler, void* user_data, struct AdbcError*); @@ -1993,60 +1997,66 @@ AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int d /// /// The result is an Arrow dataset with the following schema: /// -/// | Field Name | Field Type | -/// |--------------------------|-------------------------| -/// | catalog_name | utf8 | -/// | catalog_db_schemas | list | +/// | Field Name | Field Type | +/// |-----------------------------|-------------------------| +/// | catalog_name | utf8 | +/// | catalog_db_schemas | list | /// /// DB_SCHEMA_SCHEMA is a Struct with fields: /// -/// | Field Name | Field Type | -/// |--------------------------|-------------------------| -/// | db_schema_name | utf8 | -/// | db_schema_routines | list | +/// | Field Name | Field Type | +/// |-----------------------------|-------------------------| +/// | db_schema_name | utf8 | +/// | db_schema_routines | list | /// /// ROUTINE_SCHEMA is a Struct with fields: /// -/// | Field Name | Field Type | Comments | -/// |--------------------------|-------------------------|----------| -/// | routine_name | utf8 not null | | -/// | routine_specific_name | utf8 not null | (1) | -/// | routine_type | utf8 not null | (2) | -/// | routine_remarks | utf8 | (3) | -/// | routine_parameters | list | (4) | -/// | routine_result | list | (4) | -/// | routine_parameter_schema | binary | (5) | -/// | routine_result_schema | binary | (5) | +/// | Field Name | Field Type | Comments | +/// |-----------------------------|-------------------------|----------| +/// | routine_name | utf8 not null | | +/// | routine_specific_name | utf8 not null | (1) | +/// | routine_type | utf8 not null | (2) | +/// | routine_remarks | utf8 | (3) | +/// | routine_examples | list | (3) | +/// | routine_definition | utf8 | (4) | +/// | routine_definition_language | utf8 | (4) | +/// | routine_parameters | list | (5) | +/// | routine_result | list | (5) | +/// | routine_parameter_schema | binary | (6) | +/// | routine_result_schema | binary | (6) | /// /// 1. A name that uniquely identifies the routine, to disambiguate /// overloads. /// 2. 'FUNCTION', 'PROCEDURE', or a vendor-specific name (e.g. 'TABLE /// FUNCTION'). -/// 3. Vendor-specific description of the routine. -/// 4. Metadata about the accepted parameters and return values as structured +/// 3. Vendor-specific description or help text, along with examples of the +/// syntax. +/// 4. The definition (e.g. SQL text used to create a procedure) and the +/// language of the definition (e.g. SQL, Python) +/// 5. Metadata about the accepted parameters and return values as structured /// Arrow data. Only populated if include_columns is set, otherwise null. -/// 5. Metadata about the accepted parameters and return values as an Arrow +/// 6. Metadata about the accepted parameters and return values as an Arrow /// schema, serialized as an IPC message containing a schema Flatbuffers /// structure. Only populated if include_arrow_schema is set, otherwise /// null. /// /// PARAMETER_SCHEMA is a Struct with fields: /// -/// | Field Name | Field Type | Comments | -/// |--------------------------|-------------------------|----------| -/// | param_name | utf8 not null | | -/// | ordinal_position | int32 | (1) | -/// | remarks | utf8 | (2) | -/// | param_type | utf8 | (3) | -/// | xdbc_data_type | int16 | (3) | -/// | xdbc_type_name | utf8 | (3) | -/// | xdbc_precision | int32 | (3) | -/// | xdbc_length | int32 | (3) | -/// | xdbc_scale | int16 | (3) | -/// | xdbc_num_prec_radix | int16 | (3) | -/// | xdbc_nullable | int16 | (3) | -/// | xdbc_char_octet_length | int32 | (3) | -/// | xdbc_is_nullable | utf8 | (3) | +/// | Field Name | Field Type | Comments | +/// |-----------------------------|-------------------------|----------| +/// | param_name | utf8 not null | | +/// | ordinal_position | int32 | (1) | +/// | remarks | utf8 | (2) | +/// | param_type | utf8 | (3) | +/// | xdbc_data_type | int16 | (3) | +/// | xdbc_type_name | utf8 | (3) | +/// | xdbc_precision | int32 | (3) | +/// | xdbc_length | int32 | (3) | +/// | xdbc_scale | int16 | (3) | +/// | xdbc_num_prec_radix | int16 | (3) | +/// | xdbc_nullable | int16 | (3) | +/// | xdbc_char_octet_length | int32 | (3) | +/// | xdbc_is_nullable | utf8 | (3) | /// /// 1. The ordinal position of the parameter or return value (1-indexed). /// 2. Vendor-specific description of the parameter or return value. @@ -2055,6 +2065,7 @@ AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int d /// xdbc_ values are meant to provide JDBC/ODBC-compatible metadata /// in an agnostic manner. /// +/// \since ADBC API revision 1.2.0 /// \param[in] connection The database connection. /// \param[in] catalog Only show routines in the given catalog. If NULL, /// do not filter by catalog. If an empty string, only show routines diff --git a/go/adbc/drivermgr/arrow-adbc/adbc.h b/go/adbc/drivermgr/arrow-adbc/adbc.h index 3733daad17..3e52fda720 100644 --- a/go/adbc/drivermgr/arrow-adbc/adbc.h +++ b/go/adbc/drivermgr/arrow-adbc/adbc.h @@ -1411,6 +1411,10 @@ struct ADBC_EXPORT AdbcDriver { struct AdbcError*); AdbcStatusCode (*MultiResultSetRelease)(struct AdbcMultiResultSet*, struct AdbcError*); + AdbcStatusCode (*ConnectionGetObjectsRoutines)(struct AdbcConnection*, const char*, + const char*, const char*, int, int, + struct ArrowArrayStream*, + struct AdbcError*); AdbcStatusCode (*ConnectionSetWarningHandler)(struct AdbcConnection*, AdbcWarningHandler handler, void* user_data, struct AdbcError*); @@ -1989,6 +1993,103 @@ AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int d struct ArrowArrayStream* out, struct AdbcError* error); +/// \brief Get a hierarchical view of all functions and procedures. +/// +/// The result is an Arrow dataset with the following schema: +/// +/// | Field Name | Field Type | +/// |-----------------------------|-------------------------| +/// | catalog_name | utf8 | +/// | catalog_db_schemas | list | +/// +/// DB_SCHEMA_SCHEMA is a Struct with fields: +/// +/// | Field Name | Field Type | +/// |-----------------------------|-------------------------| +/// | db_schema_name | utf8 | +/// | db_schema_routines | list | +/// +/// ROUTINE_SCHEMA is a Struct with fields: +/// +/// | Field Name | Field Type | Comments | +/// |-----------------------------|-------------------------|----------| +/// | routine_name | utf8 not null | | +/// | routine_specific_name | utf8 not null | (1) | +/// | routine_type | utf8 not null | (2) | +/// | routine_remarks | utf8 | (3) | +/// | routine_examples | list | (3) | +/// | routine_definition | utf8 | (4) | +/// | routine_definition_language | utf8 | (4) | +/// | routine_parameters | list | (5) | +/// | routine_result | list | (5) | +/// | routine_parameter_schema | binary | (6) | +/// | routine_result_schema | binary | (6) | +/// +/// 1. A name that uniquely identifies the routine, to disambiguate +/// overloads. +/// 2. 'FUNCTION', 'PROCEDURE', or a vendor-specific name (e.g. 'TABLE +/// FUNCTION'). +/// 3. Vendor-specific description or help text, along with examples of the +/// syntax. +/// 4. The definition (e.g. SQL text used to create a procedure) and the +/// language of the definition (e.g. SQL, Python) +/// 5. Metadata about the accepted parameters and return values as structured +/// Arrow data. Only populated if include_columns is set, otherwise null. +/// 6. Metadata about the accepted parameters and return values as an Arrow +/// schema, serialized as an IPC message containing a schema Flatbuffers +/// structure. Only populated if include_arrow_schema is set, otherwise +/// null. +/// +/// PARAMETER_SCHEMA is a Struct with fields: +/// +/// | Field Name | Field Type | Comments | +/// |-----------------------------|-------------------------|----------| +/// | param_name | utf8 not null | | +/// | ordinal_position | int32 | (1) | +/// | remarks | utf8 | (2) | +/// | param_type | utf8 | (3) | +/// | xdbc_data_type | int16 | (3) | +/// | xdbc_type_name | utf8 | (3) | +/// | xdbc_precision | int32 | (3) | +/// | xdbc_length | int32 | (3) | +/// | xdbc_scale | int16 | (3) | +/// | xdbc_num_prec_radix | int16 | (3) | +/// | xdbc_nullable | int16 | (3) | +/// | xdbc_char_octet_length | int32 | (3) | +/// | xdbc_is_nullable | utf8 | (3) | +/// +/// 1. The ordinal position of the parameter or return value (1-indexed). +/// 2. Vendor-specific description of the parameter or return value. +/// 3. 'IN', 'OUT', 'INOUT', or a vendor-specific name. +/// 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. +/// +/// \since ADBC API revision 1.2.0 +/// \param[in] connection The database connection. +/// \param[in] catalog Only show routines in the given catalog. If NULL, +/// do not filter by catalog. If an empty string, only show routines +/// without a catalog. May be a search pattern (see section +/// documentation). +/// \param[in] db_schema Only show routines in the given database schema. If +/// NULL, do not filter by database schema. If an empty string, only show +/// routines without a database schema. May be a search pattern (see section +/// documentation). +/// \param[in] routine_name Only show routines with the given name. If NULL, do not +/// filter by name. May be a search pattern (see section documentation). +/// \param[in] include_columns If non-zero, include (if applicable) metadata +/// about parameters and return values as structured data. +/// \param[in] include_arrow_schema If non-zero, include (if applicable) +/// metadata about parameters and return values as a serialized Arrow +/// schema. +/// \param[out] out The result set. +/// \param[out] error Error details, if an error occurs. +ADBC_EXPORT +AdbcStatusCode AdbcConnectionGetObjectsRoutines( + struct AdbcConnection* connection, const char* catalog, const char* db_schema, + const char* routine_name, int include_columns, int include_arrow_schema, + struct ArrowArrayStream* out, struct AdbcError* error); + /// \brief Get a string option of the connection. /// /// This must always be thread-safe (other operations are not), though