From 4248d7caacd703d4bc77f312387b2d60b82d24bc Mon Sep 17 00:00:00 2001 From: Matt Topol Date: Tue, 17 Feb 2026 21:36:29 -0500 Subject: [PATCH 1/9] 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/9] 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/9] 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 0b5a9532ddd1760d341bf6f771df9d5ad1cae5b2 Mon Sep 17 00:00:00 2001 From: David Li Date: Wed, 11 Mar 2026 15:05:35 +0900 Subject: [PATCH 4/9] feat(format): add AdbcErrorGetVendorCode (#3873) Closes #1576. --- c/include/arrow-adbc/adbc.h | 9 +++++++++ go/adbc/drivermgr/arrow-adbc/adbc.h | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/c/include/arrow-adbc/adbc.h b/c/include/arrow-adbc/adbc.h index 3733daad17..4afd72be39 100644 --- a/c/include/arrow-adbc/adbc.h +++ b/c/include/arrow-adbc/adbc.h @@ -380,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 @@ -1402,6 +1409,8 @@ struct ADBC_EXPORT AdbcDriver { /// /// @{ + int (*AdbcErrorGetVendorCode)(const struct AdbcError*); + AdbcStatusCode (*MultiResultSetNext)(struct AdbcMultiResultSet*, struct ArrowArrayStream*, int64_t*, struct AdbcError*); diff --git a/go/adbc/drivermgr/arrow-adbc/adbc.h b/go/adbc/drivermgr/arrow-adbc/adbc.h index 3733daad17..4afd72be39 100644 --- a/go/adbc/drivermgr/arrow-adbc/adbc.h +++ b/go/adbc/drivermgr/arrow-adbc/adbc.h @@ -380,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 @@ -1402,6 +1409,8 @@ struct ADBC_EXPORT AdbcDriver { /// /// @{ + int (*AdbcErrorGetVendorCode)(const struct AdbcError*); + AdbcStatusCode (*MultiResultSetNext)(struct AdbcMultiResultSet*, struct ArrowArrayStream*, int64_t*, struct AdbcError*); From 03b19c96e03f96fd8f2a1e5d591d370be225360f Mon Sep 17 00:00:00 2001 From: David Li Date: Wed, 11 Mar 2026 15:05:57 +0900 Subject: [PATCH 5/9] feat(format): add more constraint metadata to GetObjects (#4008) - Add `constraint_expression` - Add various fields for foreign keys Closes #3987. Closes #3989. --- c/include/arrow-adbc/adbc.h | 140 ++++++++++++++++++++++++++-- go/adbc/drivermgr/arrow-adbc/adbc.h | 140 ++++++++++++++++++++++++++-- 2 files changed, 264 insertions(+), 16 deletions(-) diff --git a/c/include/arrow-adbc/adbc.h b/c/include/arrow-adbc/adbc.h index 4afd72be39..a461795ce0 100644 --- a/c/include/arrow-adbc/adbc.h +++ b/c/include/arrow-adbc/adbc.h @@ -683,6 +683,10 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream /// \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 @@ -708,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. /// @{ @@ -1950,20 +2036,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. /// diff --git a/go/adbc/drivermgr/arrow-adbc/adbc.h b/go/adbc/drivermgr/arrow-adbc/adbc.h index 4afd72be39..a461795ce0 100644 --- a/go/adbc/drivermgr/arrow-adbc/adbc.h +++ b/go/adbc/drivermgr/arrow-adbc/adbc.h @@ -683,6 +683,10 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream /// \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 @@ -708,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. /// @{ @@ -1950,20 +2036,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. /// From dbe9fd7fede019d8d4da2df871e2ce6044dac01f Mon Sep 17 00:00:00 2001 From: David Li Date: Mon, 20 Jul 2026 15:48:53 +0900 Subject: [PATCH 6/9] feat(format): add generic metadata API Closes #4400. --- c/include/arrow-adbc/adbc.h | 61 +++++++++++++++++++++++++++++ go/adbc/drivermgr/arrow-adbc/adbc.h | 61 +++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/c/include/arrow-adbc/adbc.h b/c/include/arrow-adbc/adbc.h index a461795ce0..7438d5b752 100644 --- a/c/include/arrow-adbc/adbc.h +++ b/c/include/arrow-adbc/adbc.h @@ -2122,6 +2122,67 @@ 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. +/// +/// 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. +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. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | catalog_name | utf8 | (1) | +/// +/// Filters: +/// 1. The catalog name to filter by. May be a search pattern. +#define ADBC_METADATA_COLLECTION_CATALOGS "catalogs" +#define ADBC_METADATA_COLLECTION_SCHEMAS "schemas" +#define ADBC_METADATA_COLLECTION_TABLES "tables" +// TODO: for systems with more hierarchy levels than SQL catalog-schema-table +#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 diff --git a/go/adbc/drivermgr/arrow-adbc/adbc.h b/go/adbc/drivermgr/arrow-adbc/adbc.h index a461795ce0..7438d5b752 100644 --- a/go/adbc/drivermgr/arrow-adbc/adbc.h +++ b/go/adbc/drivermgr/arrow-adbc/adbc.h @@ -2122,6 +2122,67 @@ 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. +/// +/// 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. +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. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | catalog_name | utf8 | (1) | +/// +/// Filters: +/// 1. The catalog name to filter by. May be a search pattern. +#define ADBC_METADATA_COLLECTION_CATALOGS "catalogs" +#define ADBC_METADATA_COLLECTION_SCHEMAS "schemas" +#define ADBC_METADATA_COLLECTION_TABLES "tables" +// TODO: for systems with more hierarchy levels than SQL catalog-schema-table +#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 From dfd3580ea2825cb21bf441bf46efe75fecdba33d Mon Sep 17 00:00:00 2001 From: David Li Date: Tue, 21 Jul 2026 13:23:30 +0900 Subject: [PATCH 7/9] expand definitions --- c/include/arrow-adbc/adbc.h | 255 +++++++++++++++++++++++++++- go/adbc/drivermgr/arrow-adbc/adbc.h | 255 +++++++++++++++++++++++++++- 2 files changed, 506 insertions(+), 4 deletions(-) diff --git a/c/include/arrow-adbc/adbc.h b/c/include/arrow-adbc/adbc.h index 7438d5b752..c0ec1390ad 100644 --- a/c/include/arrow-adbc/adbc.h +++ b/c/include/arrow-adbc/adbc.h @@ -2146,6 +2146,7 @@ AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int d /// \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, @@ -2171,16 +2172,266 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// \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 | (1) | +/// | catalog_name | utf8 | | /// /// 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 | | +/// | db_schema_name | utf8 | | +/// +/// 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 | | +/// | db_schema_name | utf8 | | +/// | table_name | utf8 not null | | +/// | table_type | utf8 not null | | +/// +/// 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" -// TODO: for systems with more hierarchy levels than SQL catalog-schema-table + +/// \brief The "columns" collection returns table columns. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | catalog_name | utf8 | | +/// | db_schema_name | utf8 | | +/// | table_name | utf8 not null | | +/// | 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) | +/// +/// 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 | | +/// | schema_name | utf8 | | +/// | table_name | utf8 not null | | +/// | 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) | +/// +/// 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. +/// +/// TODO(lidavidm): do we define this now? We'll probably have to duplicate every +/// collection to account for it, and this is less efficient for the "traditional" 3-part +/// hierarchy (since you have to recurse into each namespace individually here) #define ADBC_METADATA_COLLECTION_NAMESPACES "namespaces" /// \brief Get a string option of the connection. diff --git a/go/adbc/drivermgr/arrow-adbc/adbc.h b/go/adbc/drivermgr/arrow-adbc/adbc.h index 7438d5b752..c0ec1390ad 100644 --- a/go/adbc/drivermgr/arrow-adbc/adbc.h +++ b/go/adbc/drivermgr/arrow-adbc/adbc.h @@ -2146,6 +2146,7 @@ AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int d /// \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, @@ -2171,16 +2172,266 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// \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 | (1) | +/// | catalog_name | utf8 | | /// /// 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 | | +/// | db_schema_name | utf8 | | +/// +/// 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 | | +/// | db_schema_name | utf8 | | +/// | table_name | utf8 not null | | +/// | table_type | utf8 not null | | +/// +/// 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" -// TODO: for systems with more hierarchy levels than SQL catalog-schema-table + +/// \brief The "columns" collection returns table columns. +/// +/// | Field Name | Field Type | Comments | +/// |--------------------------|------------------------------|----------| +/// | catalog_name | utf8 | | +/// | db_schema_name | utf8 | | +/// | table_name | utf8 not null | | +/// | 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) | +/// +/// 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 | | +/// | schema_name | utf8 | | +/// | table_name | utf8 not null | | +/// | 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) | +/// +/// 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. +/// +/// TODO(lidavidm): do we define this now? We'll probably have to duplicate every +/// collection to account for it, and this is less efficient for the "traditional" 3-part +/// hierarchy (since you have to recurse into each namespace individually here) #define ADBC_METADATA_COLLECTION_NAMESPACES "namespaces" /// \brief Get a string option of the connection. From bac030ba88f57f890c9767e6079f034041cdfaa1 Mon Sep 17 00:00:00 2001 From: David Li Date: Wed, 22 Jul 2026 11:55:16 +0900 Subject: [PATCH 8/9] define RLE --- c/include/arrow-adbc/adbc.h | 54 ++++++++++++++++++++++------- go/adbc/drivermgr/arrow-adbc/adbc.h | 54 ++++++++++++++++++++++------- 2 files changed, 82 insertions(+), 26 deletions(-) diff --git a/c/include/arrow-adbc/adbc.h b/c/include/arrow-adbc/adbc.h index c0ec1390ad..8acc6cda56 100644 --- a/c/include/arrow-adbc/adbc.h +++ b/c/include/arrow-adbc/adbc.h @@ -889,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. /// @@ -2192,9 +2204,12 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// /// | Field Name | Field Type | Comments | /// |--------------------------|------------------------------|----------| -/// | catalog_name | utf8 | | +/// | catalog_name | utf8 | (R) | /// | db_schema_name | utf8 | | /// +/// (R) This field is run-length encoded by default; it can be disabled via +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. +/// /// 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. @@ -2205,11 +2220,14 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// /// | Field Name | Field Type | Comments | /// |--------------------------|------------------------------|----------| -/// | catalog_name | utf8 | | -/// | db_schema_name | utf8 | | +/// | catalog_name | utf8 | (R) | +/// | db_schema_name | utf8 | (R) | /// | table_name | utf8 not null | | /// | table_type | utf8 not null | | /// +/// (R) This field is run-length encoded by default; it can be disabled via +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. +/// /// 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. @@ -2222,9 +2240,9 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// /// | Field Name | Field Type | Comments | /// |--------------------------|------------------------------|----------| -/// | catalog_name | utf8 | | -/// | db_schema_name | utf8 | | -/// | table_name | utf8 not null | | +/// | 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) | @@ -2245,6 +2263,9 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// | xdbc_is_autoincrement | bool | (3) | /// | xdbc_is_generatedcolumn | 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. @@ -2386,9 +2407,9 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// /// | Field Name | Field Type | Comments | /// |--------------------------|-------------------------|----------| -/// | catalog_name | utf8 | | -/// | schema_name | utf8 | | -/// | table_name | utf8 not null | | +/// | 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) | @@ -2399,6 +2420,9 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// | 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 @@ -2428,10 +2452,14 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// /// Filters: /// 1. The namespace name to filter by. May be a search pattern. -/// -/// TODO(lidavidm): do we define this now? We'll probably have to duplicate every -/// collection to account for it, and this is less efficient for the "traditional" 3-part -/// hierarchy (since you have to recurse into each namespace individually here) +/// 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. diff --git a/go/adbc/drivermgr/arrow-adbc/adbc.h b/go/adbc/drivermgr/arrow-adbc/adbc.h index c0ec1390ad..8acc6cda56 100644 --- a/go/adbc/drivermgr/arrow-adbc/adbc.h +++ b/go/adbc/drivermgr/arrow-adbc/adbc.h @@ -889,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. /// @@ -2192,9 +2204,12 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// /// | Field Name | Field Type | Comments | /// |--------------------------|------------------------------|----------| -/// | catalog_name | utf8 | | +/// | catalog_name | utf8 | (R) | /// | db_schema_name | utf8 | | /// +/// (R) This field is run-length encoded by default; it can be disabled via +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. +/// /// 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. @@ -2205,11 +2220,14 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// /// | Field Name | Field Type | Comments | /// |--------------------------|------------------------------|----------| -/// | catalog_name | utf8 | | -/// | db_schema_name | utf8 | | +/// | catalog_name | utf8 | (R) | +/// | db_schema_name | utf8 | (R) | /// | table_name | utf8 not null | | /// | table_type | utf8 not null | | /// +/// (R) This field is run-length encoded by default; it can be disabled via +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. +/// /// 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. @@ -2222,9 +2240,9 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// /// | Field Name | Field Type | Comments | /// |--------------------------|------------------------------|----------| -/// | catalog_name | utf8 | | -/// | db_schema_name | utf8 | | -/// | table_name | utf8 not null | | +/// | 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) | @@ -2245,6 +2263,9 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// | xdbc_is_autoincrement | bool | (3) | /// | xdbc_is_generatedcolumn | 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. @@ -2386,9 +2407,9 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// /// | Field Name | Field Type | Comments | /// |--------------------------|-------------------------|----------| -/// | catalog_name | utf8 | | -/// | schema_name | utf8 | | -/// | table_name | utf8 not null | | +/// | 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) | @@ -2399,6 +2420,9 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// | 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 @@ -2428,10 +2452,14 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// /// Filters: /// 1. The namespace name to filter by. May be a search pattern. -/// -/// TODO(lidavidm): do we define this now? We'll probably have to duplicate every -/// collection to account for it, and this is less efficient for the "traditional" 3-part -/// hierarchy (since you have to recurse into each namespace individually here) +/// 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. From 54a3f2f37b131eebf8bc6922543b1d7dc95dbf19 Mon Sep 17 00:00:00 2001 From: David Li Date: Wed, 22 Jul 2026 12:58:02 +0900 Subject: [PATCH 9/9] add fields from #4050 --- c/include/arrow-adbc/adbc.h | 34 +++++++++++++++++++++++++---- go/adbc/drivermgr/arrow-adbc/adbc.h | 34 +++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/c/include/arrow-adbc/adbc.h b/c/include/arrow-adbc/adbc.h index 8acc6cda56..f9186e284d 100644 --- a/c/include/arrow-adbc/adbc.h +++ b/c/include/arrow-adbc/adbc.h @@ -2152,6 +2152,17 @@ AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int d /// 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. @@ -2190,6 +2201,9 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// | 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. @@ -2206,9 +2220,12 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// |--------------------------|------------------------------|----------| /// | 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. +/// 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. @@ -2224,9 +2241,17 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// | 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. +/// 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. @@ -2262,9 +2287,10 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// | 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. +/// 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. @@ -2421,7 +2447,7 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// | 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. +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. /// /// 1. One of 'CHECK', 'FOREIGN KEY', 'PRIMARY KEY', or 'UNIQUE', or a /// vendor-specific type. diff --git a/go/adbc/drivermgr/arrow-adbc/adbc.h b/go/adbc/drivermgr/arrow-adbc/adbc.h index 8acc6cda56..f9186e284d 100644 --- a/go/adbc/drivermgr/arrow-adbc/adbc.h +++ b/go/adbc/drivermgr/arrow-adbc/adbc.h @@ -2152,6 +2152,17 @@ AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection* connection, int d /// 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. @@ -2190,6 +2201,9 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// | 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. @@ -2206,9 +2220,12 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// |--------------------------|------------------------------|----------| /// | 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. +/// 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. @@ -2224,9 +2241,17 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// | 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. +/// 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. @@ -2262,9 +2287,10 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// | 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. +/// 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. @@ -2421,7 +2447,7 @@ AdbcStatusCode AdbcConnectionGetMetadataCollection( /// | 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. +/// ADBC_CONNECTION_OPTION_METADATA_COLLECTION_RLE. /// /// 1. One of 'CHECK', 'FOREIGN KEY', 'PRIMARY KEY', or 'UNIQUE', or a /// vendor-specific type.