diff --git a/.github/workflows/nightly-verify.yml b/.github/workflows/nightly-verify.yml index 5caa2b26c5..4d27fe661f 100644 --- a/.github/workflows/nightly-verify.yml +++ b/.github/workflows/nightly-verify.yml @@ -201,10 +201,23 @@ jobs: pushd arrow-adbc docker compose run --rm cpp-gcc-latest + - name: cpp-shared-no-common-entrypoints-test + run: | + pushd arrow-adbc + docker compose run --rm cpp-shared-no-common-entrypoints-test + + - name: cpp-static-test + run: | + pushd arrow-adbc + docker compose run --rm cpp-static-test + - name: python-debug run: | + # Need to set this or ASAN inside the container gets stuck + # printing a loop of DEADLYSIGNAL + sudo sysctl vm.mmap_rnd_bits=28 pushd arrow-adbc - docker compose run -e PYTHON=3.12 --rm python-debug + docker compose run -e PYTHON=3.13 --rm python-debug source-verify-docker: name: "Verify Source (OS)/${{ matrix.os }} ${{ matrix.version }}" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9289142cbe..afcab0e181 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -114,7 +114,7 @@ repos: name: Ensure CGO adbc.h is syncd language: script pass_filenames: true - files: '^c/include/arrow-adbc/.*\.h$' + files: '^c/include/arrow-adbc/[^/]*\.h$' entry: "./ci/scripts/run_cgo_drivermgr_check.sh" # https://infra.apache.org/github-actions-policy.html - id: check-pin diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt index 746547636c..2ad7faacfa 100644 --- a/c/CMakeLists.txt +++ b/c/CMakeLists.txt @@ -29,6 +29,12 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) include(CTest) +set(ADBC_TARGET_COMPILE_DEFINITIONS) +if(NOT ADBC_DEFINE_COMMON_ENTRYPOINTS) + message(STATUS "Defining ADBC_NO_COMMON_ENTRYPOINTS") + set(ADBC_TARGET_COMPILE_DEFINITIONS "ADBC_NO_COMMON_ENTRYPOINTS") +endif() + if(ADBC_WITH_VENDORED_FMT) add_subdirectory(vendor/fmt EXCLUDE_FROM_ALL) set_target_properties(fmt PROPERTIES POSITION_INDEPENDENT_CODE ON) @@ -58,6 +64,8 @@ if(ADBC_INTEGRATION_DUCKDB) endif() if(ADBC_DRIVER_FLIGHTSQL) + install(FILES "${REPOSITORY_ROOT}/c/include/arrow-adbc/driver/flightsql.h" + DESTINATION include/arrow-adbc/driver) add_subdirectory(driver/flightsql) endif() @@ -69,18 +77,26 @@ if(ADBC_DRIVER_MANAGER) endif() if(ADBC_DRIVER_POSTGRESQL) + install(FILES "${REPOSITORY_ROOT}/c/include/arrow-adbc/driver/postgresql.h" + DESTINATION include/arrow-adbc/driver) add_subdirectory(driver/postgresql) endif() if(ADBC_DRIVER_SQLITE) + install(FILES "${REPOSITORY_ROOT}/c/include/arrow-adbc/driver/sqlite.h" + DESTINATION include/arrow-adbc/driver) add_subdirectory(driver/sqlite) endif() if(ADBC_DRIVER_SNOWFLAKE) + install(FILES "${REPOSITORY_ROOT}/c/include/arrow-adbc/driver/snowflake.h" + DESTINATION include/arrow-adbc/driver) add_subdirectory(driver/snowflake) endif() if(ADBC_DRIVER_BIGQUERY) + install(FILES "${REPOSITORY_ROOT}/c/include/arrow-adbc/driver/bigquery.h" + DESTINATION include/arrow-adbc/driver) add_subdirectory(driver/bigquery) endif() diff --git a/c/cmake_modules/BuildUtils.cmake b/c/cmake_modules/BuildUtils.cmake index 55b726d305..db9a64a9eb 100644 --- a/c/cmake_modules/BuildUtils.cmake +++ b/c/cmake_modules/BuildUtils.cmake @@ -67,12 +67,6 @@ function(add_thirdparty_lib LIB_NAME LIB_TYPE LIB) endif() endfunction() -function(REUSE_PRECOMPILED_HEADER_LIB TARGET_NAME LIB_NAME) - if(ADBC_USE_PRECOMPILED_HEADERS) - target_precompile_headers(${TARGET_NAME} REUSE_FROM ${LIB_NAME}) - endif() -endfunction() - function(arrow_install_cmake_package PACKAGE_NAME EXPORT_NAME) set(CONFIG_CMAKE "${PACKAGE_NAME}Config.cmake") set(BUILT_CONFIG_CMAKE "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_CMAKE}") @@ -102,11 +96,9 @@ function(ADD_ARROW_LIB LIB_NAME) BUILD_STATIC CMAKE_PACKAGE_NAME PKG_CONFIG_NAME - SHARED_LINK_FLAGS - PRECOMPILED_HEADER_LIB) + SHARED_LINK_FLAGS) set(multi_value_args SOURCES - PRECOMPILED_HEADERS OUTPUTS STATIC_LINK_LIBS SHARED_LINK_LIBS @@ -172,12 +164,6 @@ function(ADD_ARROW_LIB LIB_NAME) if(ARG_DEPENDENCIES) add_dependencies(${LIB_NAME}_objlib ${ARG_DEPENDENCIES}) endif() - if(ARG_PRECOMPILED_HEADER_LIB) - reuse_precompiled_header_lib(${LIB_NAME}_objlib ${ARG_PRECOMPILED_HEADER_LIB}) - endif() - if(ARG_PRECOMPILED_HEADERS AND ADBC_USE_PRECOMPILED_HEADERS) - target_precompile_headers(${LIB_NAME}_objlib PRIVATE ${ARG_PRECOMPILED_HEADERS}) - endif() set(LIB_DEPS $) set(LIB_INCLUDES) set(EXTRA_DEPS) @@ -220,10 +206,6 @@ function(ADD_ARROW_LIB LIB_NAME) add_dependencies(${LIB_NAME}_shared ${EXTRA_DEPS}) endif() - if(ARG_PRECOMPILED_HEADER_LIB) - reuse_precompiled_header_lib(${LIB_NAME}_shared ${ARG_PRECOMPILED_HEADER_LIB}) - endif() - if(ARG_OUTPUTS) list(APPEND ${ARG_OUTPUTS} ${LIB_NAME}_shared) endif() @@ -318,10 +300,6 @@ function(ADD_ARROW_LIB LIB_NAME) add_dependencies(${LIB_NAME}_static ${EXTRA_DEPS}) endif() - if(ARG_PRECOMPILED_HEADER_LIB) - reuse_precompiled_header_lib(${LIB_NAME}_static ${ARG_PRECOMPILED_HEADER_LIB}) - endif() - if(ARG_OUTPUTS) list(APPEND ${ARG_OUTPUTS} ${LIB_NAME}_static) endif() @@ -550,10 +528,8 @@ endfunction() # names must exist function(ADD_TEST_CASE REL_TEST_NAME) set(options NO_VALGRIND ENABLED) - set(one_value_args PRECOMPILED_HEADER_LIB) set(multi_value_args SOURCES - PRECOMPILED_HEADERS STATIC_LINK_LIBS EXTRA_LINK_LIBS EXTRA_INCLUDES @@ -613,14 +589,6 @@ function(ADD_TEST_CASE REL_TEST_NAME) target_link_libraries(${TEST_NAME} PRIVATE ${ADBC_TEST_LINK_LIBS}) endif() - if(ARG_PRECOMPILED_HEADER_LIB) - reuse_precompiled_header_lib(${TEST_NAME} ${ARG_PRECOMPILED_HEADER_LIB}) - endif() - - if(ARG_PRECOMPILED_HEADERS AND ADBC_USE_PRECOMPILED_HEADERS) - target_precompile_headers(${TEST_NAME} PRIVATE ${ARG_PRECOMPILED_HEADERS}) - endif() - if(ARG_EXTRA_LINK_LIBS) target_link_libraries(${TEST_NAME} PRIVATE ${ARG_EXTRA_LINK_LIBS}) endif() diff --git a/c/cmake_modules/DefineOptions.cmake b/c/cmake_modules/DefineOptions.cmake index c022d523a1..d0e8085260 100644 --- a/c/cmake_modules/DefineOptions.cmake +++ b/c/cmake_modules/DefineOptions.cmake @@ -98,34 +98,13 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") define_option(ADBC_BUILD_SHARED "Build shared libraries" ON) - define_option_string(ADBC_PACKAGE_KIND - "Arbitrary string that identifies the kind of package;\ -(for informational purposes)" "") - define_option_string(ADBC_GIT_ID "The Arrow git commit id (if any)" "") define_option_string(ADBC_GIT_DESCRIPTION "The Arrow git commit description (if any)" "") - define_option(ADBC_NO_DEPRECATED_API "Exclude deprecated APIs from build" OFF) - define_option(ADBC_USE_CCACHE "Use ccache when compiling (if available)" ON) - define_option(ADBC_USE_PRECOMPILED_HEADERS "Use precompiled headers when compiling" OFF) - - # Arm64 architectures and extensions can lead to exploding combinations. - # So set it directly through cmake command line. - # - # If you change this, you need to change the definition in - # python/CMakeLists.txt too. - define_option_string(ADBC_ARMV8_ARCH - "Arm64 arch and extensions" - "armv8-a" # Default - "armv8-a" - "armv8-a+crc+crypto") - - define_option(ADBC_ALTIVEC "Build with Altivec if compiler has support" ON) - define_option(ADBC_RPATH_ORIGIN "Build Arrow libraries with RATH set to \$ORIGIN" OFF) define_option(ADBC_INSTALL_NAME_RPATH @@ -230,7 +209,11 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") #---------------------------------------------------------------------- set_option_category("Advanced developer") - option(ADBC_BUILD_CONFIG_SUMMARY_JSON "Summarize build configuration in a JSON file" ON) + define_option(ADBC_BUILD_CONFIG_SUMMARY_JSON + "Summarize build configuration in a JSON file" ON) + + define_option(ADBC_DEFINE_COMMON_ENTRYPOINTS + "Define the Adbc functions in static/shared driver libraries" ON) #---------------------------------------------------------------------- set_option_category("Project components") diff --git a/c/cmake_modules/GoUtils.cmake b/c/cmake_modules/GoUtils.cmake index 87b1a957c2..20ce95e8eb 100644 --- a/c/cmake_modules/GoUtils.cmake +++ b/c/cmake_modules/GoUtils.cmake @@ -57,7 +57,7 @@ function(adbc_add_static_library target_name base_name) PROPERTIES IMPORTED_LOCATION "${_IMPORT_PREFIX}/bin/${static_base_name}") else() - set(prefix "${_IMPORT_PREFIX}/${ADBC_IMPORT_LIB_DIR}") + set(prefix "${_IMPORT_PREFIX}/${ADBC_INSTALL_LIBDIR}") set_target_properties(${target_name} PROPERTIES IMPORTED_LOCATION "${prefix}/${static_base_name}") @@ -74,7 +74,7 @@ function(add_go_lib GO_MOD_DIR GO_LIBNAME) PKG_CONFIG_NAME BUILD_STATIC BUILD_SHARED) - set(multi_value_args SOURCES OUTPUTS) + set(multi_value_args SOURCES DEFINES OUTPUTS) cmake_parse_arguments(ARG "${options}" @@ -135,10 +135,15 @@ function(add_go_lib GO_MOD_DIR GO_LIBNAME) "${GO_BUILD_FLAGS} $<$:-gcflags=\"-N -l\">") # if we're building debug mode then change the default CGO_CFLAGS and CGO_CXXFLAGS from "-g O2" to "-g3" - set(GO_ENV_VARS - "CGO_ENABLED=1 $<$:CGO_CFLAGS=-g3> $<$:CGO_CXXFLAGS=-g3>" - ) - separate_arguments(GO_ENV_VARS NATIVE_COMMAND "${GO_ENV_VARS}") + set(GO_FLAGS "$<$:-g3>") + foreach(DEFINE ${ARG_DEFINES}) + string(APPEND GO_FLAGS " -D${DEFINE}") + endforeach() + + set(GO_ENV_VARS) + list(APPEND GO_ENV_VARS "CGO_ENABLED=1") + list(APPEND GO_ENV_VARS "CGO_CFLAGS=${GO_FLAGS}") + list(APPEND GO_ENV_VARS "CGO_CXXFLAGS=${GO_FLAGS}") if(BUILD_SHARED) set(LIB_NAME_SHARED diff --git a/c/driver/bigquery/AdbcDriverBigQueryConfig.cmake.in b/c/driver/bigquery/AdbcDriverBigQueryConfig.cmake.in index 98f5c44e45..9573ecf0a4 100644 --- a/c/driver/bigquery/AdbcDriverBigQueryConfig.cmake.in +++ b/c/driver/bigquery/AdbcDriverBigQueryConfig.cmake.in @@ -33,7 +33,7 @@ if(ADBC_BUILD_SHARED) endif() if(ADBC_BUILD_STATIC) - adbc_add_shared_library( + adbc_add_static_library( AdbcDriverBigQuery::adbc_driver_bigquery_static adbc_driver_bigquery) endif() diff --git a/c/driver/bigquery/CMakeLists.txt b/c/driver/bigquery/CMakeLists.txt index 94192908f6..7dc63b90bc 100644 --- a/c/driver/bigquery/CMakeLists.txt +++ b/c/driver/bigquery/CMakeLists.txt @@ -32,6 +32,8 @@ add_go_lib("${REPOSITORY_ROOT}/go/adbc/pkg/bigquery/" adbc-driver-bigquery SHARED_LINK_FLAGS ${LDFLAGS} + DEFINES + ${ADBC_TARGET_COMPILE_DEFINITIONS} OUTPUTS ADBC_LIBRARIES) diff --git a/c/driver/common/AdbcDriverCommonConfig.cmake.in b/c/driver/common/AdbcDriverCommonConfig.cmake.in new file mode 100644 index 0000000000..165e0b6aaf --- /dev/null +++ b/c/driver/common/AdbcDriverCommonConfig.cmake.in @@ -0,0 +1,24 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +@PACKAGE_INIT@ + +set(ADBC_VERSION "@ADBC_VERSION@") + +include("${CMAKE_CURRENT_LIST_DIR}/AdbcDriverCommonTargets.cmake") + +check_required_components(AdbcDriverCommon) diff --git a/c/driver/common/CMakeLists.txt b/c/driver/common/CMakeLists.txt index 5855056bb4..07b9a50ad6 100644 --- a/c/driver/common/CMakeLists.txt +++ b/c/driver/common/CMakeLists.txt @@ -21,6 +21,22 @@ set_target_properties(adbc_driver_common PROPERTIES POSITION_INDEPENDENT_CODE ON target_include_directories(adbc_driver_common PRIVATE "${REPOSITORY_ROOT}/c/include") target_link_libraries(adbc_driver_common PUBLIC nanoarrow::nanoarrow) +# For static builds, we need to install the static library here so downstream +# applications can link to it +if(ADBC_BUILD_STATIC) + if(ADBC_WITH_VENDORED_NANOARROW) + message(WARNING "adbc_driver_common is not installed when ADBC_WITH_VENDORED_NANOARROW is ON. To use the static libraries, for now you must provide nanoarrow instead of using the vendored copy" + ) + else() + install(TARGETS adbc_driver_common ${INSTALL_IS_OPTIONAL} + EXPORT adbc_driver_common_targets + RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + arrow_install_cmake_package(AdbcDriverCommon adbc_driver_common_targets) + endif() +endif() + if(ADBC_BUILD_TESTS) add_test_case(driver_common_test PREFIX diff --git a/c/driver/common/utils.c b/c/driver/common/utils.c index 00ebd51939..4dc8214ef5 100644 --- a/c/driver/common/utils.c +++ b/c/driver/common/utils.c @@ -27,7 +27,7 @@ static size_t kErrorBufferSize = 1024; -int AdbcStatusCodeToErrno(AdbcStatusCode code) { +int InternalAdbcStatusCodeToErrno(AdbcStatusCode code) { switch (code) { case ADBC_STATUS_OK: return 0; @@ -104,14 +104,15 @@ static void ReleaseError(struct AdbcError* error) { error->release = NULL; } -void SetError(struct AdbcError* error, const char* format, ...) { +void InternalAdbcSetError(struct AdbcError* error, const char* format, ...) { va_list args; va_start(args, format); - SetErrorVariadic(error, format, args); + InternalAdbcSetErrorVariadic(error, format, args); va_end(args); } -void SetErrorVariadic(struct AdbcError* error, const char* format, va_list args) { +void InternalAdbcSetErrorVariadic(struct AdbcError* error, const char* format, + va_list args) { if (!error) return; if (error->release) { // TODO: combine the errors if possible @@ -147,8 +148,8 @@ void SetErrorVariadic(struct AdbcError* error, const char* format, va_list args) vsnprintf(error->message, kErrorBufferSize, format, args); } -void AppendErrorDetail(struct AdbcError* error, const char* key, const uint8_t* detail, - size_t detail_length) { +void InternalAdbcAppendErrorDetail(struct AdbcError* error, const char* key, + const uint8_t* detail, size_t detail_length) { if (error->release != ReleaseErrorWithDetails) return; struct AdbcErrorDetails* details = (struct AdbcErrorDetails*)error->private_data; @@ -212,7 +213,7 @@ void AppendErrorDetail(struct AdbcError* error, const char* key, const uint8_t* details->count++; } -int CommonErrorGetDetailCount(const struct AdbcError* error) { +int InternalAdbcCommonErrorGetDetailCount(const struct AdbcError* error) { if (error->release != ReleaseErrorWithDetails) { return 0; } @@ -220,7 +221,8 @@ int CommonErrorGetDetailCount(const struct AdbcError* error) { return details->count; } -struct AdbcErrorDetail CommonErrorGetDetail(const struct AdbcError* error, int index) { +struct AdbcErrorDetail InternalAdbcCommonErrorGetDetail(const struct AdbcError* error, + int index) { if (error->release != ReleaseErrorWithDetails) { return (struct AdbcErrorDetail){NULL, NULL, 0}; } @@ -235,11 +237,12 @@ struct AdbcErrorDetail CommonErrorGetDetail(const struct AdbcError* error, int i }; } -bool IsCommonError(const struct AdbcError* error) { +bool InternalAdbcIsCommonError(const struct AdbcError* error) { return error->release == ReleaseErrorWithDetails || error->release == ReleaseError; } -int StringBuilderInit(struct StringBuilder* builder, size_t initial_size) { +int InternalAdbcStringBuilderInit(struct InternalAdbcStringBuilder* builder, + size_t initial_size) { builder->buffer = (char*)malloc(initial_size); if (builder->buffer == NULL) return errno; @@ -248,7 +251,8 @@ int StringBuilderInit(struct StringBuilder* builder, size_t initial_size) { return 0; } -int StringBuilderAppend(struct StringBuilder* builder, const char* fmt, ...) { +int InternalAdbcStringBuilderAppend(struct InternalAdbcStringBuilder* builder, + const char* fmt, ...) { va_list argptr; int bytes_available = (int)builder->capacity - (int)builder->size; @@ -278,16 +282,16 @@ int StringBuilderAppend(struct StringBuilder* builder, const char* fmt, ...) { return 0; } -void StringBuilderReset(struct StringBuilder* builder) { +void InternalAdbcStringBuilderReset(struct InternalAdbcStringBuilder* builder) { if (builder->buffer) { free(builder->buffer); } memset(builder, 0, sizeof(*builder)); } -AdbcStatusCode AdbcInitConnectionGetInfoSchema(struct ArrowSchema* schema, - struct ArrowArray* array, - struct AdbcError* error) { +AdbcStatusCode InternalAdbcInitConnectionGetInfoSchema(struct ArrowSchema* schema, + struct ArrowArray* array, + struct AdbcError* error) { // TODO: use C equivalent of UniqueSchema to avoid incomplete schema // on error ArrowSchemaInit(schema); @@ -351,10 +355,10 @@ AdbcStatusCode AdbcInitConnectionGetInfoSchema(struct ArrowSchema* schema, return ADBC_STATUS_OK; } // NOLINT(whitespace/indent) -AdbcStatusCode AdbcConnectionGetInfoAppendString(struct ArrowArray* array, - uint32_t info_code, - const char* info_value, - struct AdbcError* error) { +AdbcStatusCode InternalAdbcConnectionGetInfoAppendString(struct ArrowArray* array, + uint32_t info_code, + const char* info_value, + struct AdbcError* error) { CHECK_NA(INTERNAL, ArrowArrayAppendUInt(array->children[0], info_code), error); // Append to type variant struct ArrowStringView value = ArrowCharView(info_value); @@ -366,9 +370,10 @@ AdbcStatusCode AdbcConnectionGetInfoAppendString(struct ArrowArray* array, return ADBC_STATUS_OK; } -AdbcStatusCode AdbcConnectionGetInfoAppendInt(struct ArrowArray* array, - uint32_t info_code, int64_t info_value, - struct AdbcError* error) { +AdbcStatusCode InternalAdbcConnectionGetInfoAppendInt(struct ArrowArray* array, + uint32_t info_code, + int64_t info_value, + struct AdbcError* error) { CHECK_NA(INTERNAL, ArrowArrayAppendUInt(array->children[0], info_code), error); // Append to type variant CHECK_NA(INTERNAL, ArrowArrayAppendInt(array->children[1]->children[2], info_value), @@ -379,8 +384,8 @@ AdbcStatusCode AdbcConnectionGetInfoAppendInt(struct ArrowArray* array, return ADBC_STATUS_OK; } -AdbcStatusCode AdbcInitConnectionObjectsSchema(struct ArrowSchema* schema, - struct AdbcError* error) { +AdbcStatusCode InternalAdbcInitConnectionObjectsSchema(struct ArrowSchema* schema, + struct AdbcError* error) { ArrowSchemaInit(schema); CHECK_NA(INTERNAL, ArrowSchemaSetTypeStruct(schema, /*num_columns=*/2), error); CHECK_NA(INTERNAL, ArrowSchemaSetType(schema->children[0], NANOARROW_TYPE_STRING), @@ -563,7 +568,8 @@ AdbcStatusCode AdbcInitConnectionObjectsSchema(struct ArrowSchema* schema, return ADBC_STATUS_OK; } -struct AdbcGetObjectsData* AdbcGetObjectsDataInit(struct ArrowArrayView* array_view) { +struct AdbcGetObjectsData* InternalAdbcGetObjectsDataInit( + struct ArrowArrayView* array_view) { struct AdbcGetObjectsData* get_objects_data = (struct AdbcGetObjectsData*)calloc(1, sizeof(struct AdbcGetObjectsData)); if (get_objects_data == NULL) { @@ -895,11 +901,11 @@ struct AdbcGetObjectsData* AdbcGetObjectsDataInit(struct ArrowArrayView* array_v return get_objects_data; error_handler: - AdbcGetObjectsDataDelete(get_objects_data); + InternalAdbcGetObjectsDataDelete(get_objects_data); return NULL; } -void AdbcGetObjectsDataDelete(struct AdbcGetObjectsData* get_objects_data) { +void InternalAdbcGetObjectsDataDelete(struct AdbcGetObjectsData* get_objects_data) { for (int64_t catalog_index = 0; catalog_index < get_objects_data->n_catalogs; catalog_index++) { struct AdbcGetObjectsCatalog* catalog = get_objects_data->catalogs[catalog_index]; @@ -946,7 +952,7 @@ void AdbcGetObjectsDataDelete(struct AdbcGetObjectsData* get_objects_data) { free(get_objects_data); } -struct AdbcGetObjectsCatalog* AdbcGetObjectsDataGetCatalogByName( +struct AdbcGetObjectsCatalog* InternalAdbcGetObjectsDataGetCatalogByName( struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name) { if (catalog_name != NULL) { for (int64_t i = 0; i < get_objects_data->n_catalogs; i++) { @@ -960,12 +966,12 @@ struct AdbcGetObjectsCatalog* AdbcGetObjectsDataGetCatalogByName( return NULL; } -struct AdbcGetObjectsSchema* AdbcGetObjectsDataGetSchemaByName( +struct AdbcGetObjectsSchema* InternalAdbcGetObjectsDataGetSchemaByName( struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name, const char* const schema_name) { if (schema_name != NULL) { struct AdbcGetObjectsCatalog* catalog = - AdbcGetObjectsDataGetCatalogByName(get_objects_data, catalog_name); + InternalAdbcGetObjectsDataGetCatalogByName(get_objects_data, catalog_name); if (catalog != NULL) { for (int64_t i = 0; i < catalog->n_db_schemas; i++) { struct AdbcGetObjectsSchema* schema = catalog->catalog_db_schemas[i]; @@ -979,12 +985,12 @@ struct AdbcGetObjectsSchema* AdbcGetObjectsDataGetSchemaByName( return NULL; } -struct AdbcGetObjectsTable* AdbcGetObjectsDataGetTableByName( +struct AdbcGetObjectsTable* InternalAdbcGetObjectsDataGetTableByName( struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name, const char* const schema_name, const char* const table_name) { if (table_name != NULL) { - struct AdbcGetObjectsSchema* schema = - AdbcGetObjectsDataGetSchemaByName(get_objects_data, catalog_name, schema_name); + struct AdbcGetObjectsSchema* schema = InternalAdbcGetObjectsDataGetSchemaByName( + get_objects_data, catalog_name, schema_name); if (schema != NULL) { for (int64_t i = 0; i < schema->n_db_schema_tables; i++) { struct AdbcGetObjectsTable* table = schema->db_schema_tables[i]; @@ -998,12 +1004,12 @@ struct AdbcGetObjectsTable* AdbcGetObjectsDataGetTableByName( return NULL; } -struct AdbcGetObjectsColumn* AdbcGetObjectsDataGetColumnByName( +struct AdbcGetObjectsColumn* InternalAdbcGetObjectsDataGetColumnByName( struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name, const char* const schema_name, const char* const table_name, const char* const column_name) { if (column_name != NULL) { - struct AdbcGetObjectsTable* table = AdbcGetObjectsDataGetTableByName( + struct AdbcGetObjectsTable* table = InternalAdbcGetObjectsDataGetTableByName( get_objects_data, catalog_name, schema_name, table_name); if (table != NULL) { for (int64_t i = 0; i < table->n_table_columns; i++) { @@ -1018,12 +1024,12 @@ struct AdbcGetObjectsColumn* AdbcGetObjectsDataGetColumnByName( return NULL; } -struct AdbcGetObjectsConstraint* AdbcGetObjectsDataGetConstraintByName( +struct AdbcGetObjectsConstraint* InternalAdbcGetObjectsDataGetConstraintByName( struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name, const char* const schema_name, const char* const table_name, const char* const constraint_name) { if (constraint_name != NULL) { - struct AdbcGetObjectsTable* table = AdbcGetObjectsDataGetTableByName( + struct AdbcGetObjectsTable* table = InternalAdbcGetObjectsDataGetTableByName( get_objects_data, catalog_name, schema_name, table_name); if (table != NULL) { for (int64_t i = 0; i < table->n_table_constraints; i++) { diff --git a/c/driver/common/utils.h b/c/driver/common/utils.h index d204821b2b..fa727d0505 100644 --- a/c/driver/common/utils.h +++ b/c/driver/common/utils.h @@ -29,7 +29,7 @@ extern "C" { #endif -int AdbcStatusCodeToErrno(AdbcStatusCode code); +int InternalAdbcStatusCodeToErrno(AdbcStatusCode code); // If using mingw's c99-compliant printf, we need a different format-checking attribute #if defined(__USE_MINGW_ANSI_STDIO) && defined(__MINGW_PRINTF_FORMAT) @@ -41,64 +41,69 @@ int AdbcStatusCodeToErrno(AdbcStatusCode code); #endif /// Set error message using a format string. -void SetError(struct AdbcError* error, const char* format, - ...) ADBC_CHECK_PRINTF_ATTRIBUTE; +void InternalAdbcSetError(struct AdbcError* error, const char* format, + ...) ADBC_CHECK_PRINTF_ATTRIBUTE; /// Set error message using a format string. -void SetErrorVariadic(struct AdbcError* error, const char* format, va_list args); +void InternalAdbcSetErrorVariadic(struct AdbcError* error, const char* format, + va_list args); /// Add an error detail. -void AppendErrorDetail(struct AdbcError* error, const char* key, const uint8_t* detail, - size_t detail_length); +void InternalAdbcAppendErrorDetail(struct AdbcError* error, const char* key, + const uint8_t* detail, size_t detail_length); -int CommonErrorGetDetailCount(const struct AdbcError* error); -struct AdbcErrorDetail CommonErrorGetDetail(const struct AdbcError* error, int index); -bool IsCommonError(const struct AdbcError* error); +int InternalAdbcCommonErrorGetDetailCount(const struct AdbcError* error); +struct AdbcErrorDetail InternalAdbcCommonErrorGetDetail(const struct AdbcError* error, + int index); +bool InternalAdbcIsCommonError(const struct AdbcError* error); -struct StringBuilder { +struct InternalAdbcStringBuilder { char* buffer; // Not including null terminator size_t size; size_t capacity; }; -int StringBuilderInit(struct StringBuilder* builder, size_t initial_size); +int InternalAdbcStringBuilderInit(struct InternalAdbcStringBuilder* builder, + size_t initial_size); -int ADBC_CHECK_PRINTF_ATTRIBUTE StringBuilderAppend(struct StringBuilder* builder, - const char* fmt, ...); -void StringBuilderReset(struct StringBuilder* builder); +int ADBC_CHECK_PRINTF_ATTRIBUTE InternalAdbcStringBuilderAppend( + struct InternalAdbcStringBuilder* builder, const char* fmt, ...); +void InternalAdbcStringBuilderReset(struct InternalAdbcStringBuilder* builder); #undef ADBC_CHECK_PRINTF_ATTRIBUTE /// Check an NanoArrow status code. -#define CHECK_NA(CODE, EXPR, ERROR) \ - do { \ - ArrowErrorCode arrow_error_code = (EXPR); \ - if (arrow_error_code != 0) { \ - SetError(ERROR, "%s failed: (%d) %s\nDetail: %s:%d", #EXPR, arrow_error_code, \ - strerror(arrow_error_code), __FILE__, __LINE__); \ - return ADBC_STATUS_##CODE; \ - } \ +#define CHECK_NA(CODE, EXPR, ERROR) \ + do { \ + ArrowErrorCode arrow_error_code = (EXPR); \ + if (arrow_error_code != 0) { \ + InternalAdbcSetError(ERROR, "%s failed: (%d) %s\nDetail: %s:%d", #EXPR, \ + arrow_error_code, strerror(arrow_error_code), __FILE__, \ + __LINE__); \ + return ADBC_STATUS_##CODE; \ + } \ } while (0) /// Check an NanoArrow status code. -#define CHECK_NA_DETAIL(CODE, EXPR, NA_ERROR, ERROR) \ - do { \ - ArrowErrorCode arrow_error_code = (EXPR); \ - if (arrow_error_code != 0) { \ - SetError(ERROR, "%s failed: (%d) %s: %s\nDetail: %s:%d", #EXPR, arrow_error_code, \ - strerror(arrow_error_code), (NA_ERROR)->message, __FILE__, __LINE__); \ - return ADBC_STATUS_##CODE; \ - } \ +#define CHECK_NA_DETAIL(CODE, EXPR, NA_ERROR, ERROR) \ + do { \ + ArrowErrorCode arrow_error_code = (EXPR); \ + if (arrow_error_code != 0) { \ + InternalAdbcSetError(ERROR, "%s failed: (%d) %s: %s\nDetail: %s:%d", #EXPR, \ + arrow_error_code, strerror(arrow_error_code), \ + (NA_ERROR)->message, __FILE__, __LINE__); \ + return ADBC_STATUS_##CODE; \ + } \ } while (0) /// Check a generic status. -#define RAISE(CODE, EXPR, ERRMSG, ERROR) \ - do { \ - if (!(EXPR)) { \ - SetError(ERROR, "%s failed: %s\nDetail: %s:%d", #EXPR, ERRMSG, __FILE__, \ - __LINE__); \ - return ADBC_STATUS_##CODE; \ - } \ +#define RAISE(CODE, EXPR, ERRMSG, ERROR) \ + do { \ + if (!(EXPR)) { \ + InternalAdbcSetError(ERROR, "%s failed: %s\nDetail: %s:%d", #EXPR, ERRMSG, \ + __FILE__, __LINE__); \ + return ADBC_STATUS_##CODE; \ + } \ } while (0) /// Check an NanoArrow status code. @@ -217,24 +222,25 @@ struct AdbcGetObjectsData { // does not copy any data from array // returns NULL on error -struct AdbcGetObjectsData* AdbcGetObjectsDataInit(struct ArrowArrayView* array_view); -void AdbcGetObjectsDataDelete(struct AdbcGetObjectsData* get_objects_data); +struct AdbcGetObjectsData* InternalAdbcGetObjectsDataInit( + struct ArrowArrayView* array_view); +void InternalAdbcGetObjectsDataDelete(struct AdbcGetObjectsData* get_objects_data); // returns NULL on error // for now all arguments are required -struct AdbcGetObjectsCatalog* AdbcGetObjectsDataGetCatalogByName( +struct AdbcGetObjectsCatalog* InternalAdbcGetObjectsDataGetCatalogByName( struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name); -struct AdbcGetObjectsSchema* AdbcGetObjectsDataGetSchemaByName( +struct AdbcGetObjectsSchema* InternalAdbcGetObjectsDataGetSchemaByName( struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name, const char* const schema_name); -struct AdbcGetObjectsTable* AdbcGetObjectsDataGetTableByName( +struct AdbcGetObjectsTable* InternalAdbcGetObjectsDataGetTableByName( struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name, const char* const schema_name, const char* const table_name); -struct AdbcGetObjectsColumn* AdbcGetObjectsDataGetColumnByName( +struct AdbcGetObjectsColumn* InternalAdbcGetObjectsDataGetColumnByName( struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name, const char* const schema_name, const char* const table_name, const char* const column_name); -struct AdbcGetObjectsConstraint* AdbcGetObjectsDataGetConstraintByName( +struct AdbcGetObjectsConstraint* InternalAdbcGetObjectsDataGetConstraintByName( struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name, const char* const schema_name, const char* const table_name, const char* const constraint_name); diff --git a/c/driver/common/utils_test.cc b/c/driver/common/utils_test.cc index 489af163fd..a772ef4ade 100644 --- a/c/driver/common/utils_test.cc +++ b/c/driver/common/utils_test.cc @@ -26,76 +26,76 @@ #include "utils.h" TEST(TestStringBuilder, TestBasic) { - struct StringBuilder str; + struct InternalAdbcStringBuilder str; int ret; - ret = StringBuilderInit(&str, /*initial_size=*/64); + ret = InternalAdbcStringBuilderInit(&str, /*initial_size=*/64); EXPECT_EQ(ret, 0); EXPECT_EQ(str.capacity, 64); - ret = StringBuilderAppend(&str, "%s", "BASIC TEST"); + ret = InternalAdbcStringBuilderAppend(&str, "%s", "BASIC TEST"); EXPECT_EQ(ret, 0); EXPECT_EQ(str.size, 10); EXPECT_STREQ(str.buffer, "BASIC TEST"); - StringBuilderReset(&str); + InternalAdbcStringBuilderReset(&str); } TEST(TestStringBuilder, TestBoundary) { - struct StringBuilder str; + struct InternalAdbcStringBuilder str; int ret; - ret = StringBuilderInit(&str, /*initial_size=*/10); + ret = InternalAdbcStringBuilderInit(&str, /*initial_size=*/10); EXPECT_EQ(ret, 0); EXPECT_EQ(str.capacity, 10); - ret = StringBuilderAppend(&str, "%s", "BASIC TEST"); + ret = InternalAdbcStringBuilderAppend(&str, "%s", "BASIC TEST"); EXPECT_EQ(ret, 0); // should resize to include \0 EXPECT_EQ(str.capacity, 11); EXPECT_EQ(str.size, 10); EXPECT_STREQ(str.buffer, "BASIC TEST"); - StringBuilderReset(&str); + InternalAdbcStringBuilderReset(&str); } TEST(TestStringBuilder, TestMultipleAppends) { - struct StringBuilder str; + struct InternalAdbcStringBuilder str; int ret; - ret = StringBuilderInit(&str, /*initial_size=*/2); + ret = InternalAdbcStringBuilderInit(&str, /*initial_size=*/2); EXPECT_EQ(ret, 0); EXPECT_EQ(str.capacity, 2); - ret = StringBuilderAppend(&str, "%s", "BASIC"); + ret = InternalAdbcStringBuilderAppend(&str, "%s", "BASIC"); EXPECT_EQ(ret, 0); EXPECT_EQ(str.capacity, 6); EXPECT_EQ(str.size, 5); EXPECT_STREQ(str.buffer, "BASIC"); - ret = StringBuilderAppend(&str, "%s", " TEST"); + ret = InternalAdbcStringBuilderAppend(&str, "%s", " TEST"); EXPECT_EQ(ret, 0); EXPECT_EQ(str.capacity, 11); EXPECT_EQ(str.size, 10); EXPECT_STREQ(str.buffer, "BASIC TEST"); - StringBuilderReset(&str); + InternalAdbcStringBuilderReset(&str); } TEST(ErrorDetails, Adbc100) { struct AdbcError error; std::memset(&error, 0, ADBC_ERROR_1_1_0_SIZE); - SetError(&error, "My message"); + InternalAdbcSetError(&error, "My message"); ASSERT_EQ(nullptr, error.private_data); ASSERT_EQ(nullptr, error.private_driver); { std::string detail = "detail"; - AppendErrorDetail(&error, "key", reinterpret_cast(detail.data()), - detail.size()); + InternalAdbcAppendErrorDetail( + &error, "key", reinterpret_cast(detail.data()), detail.size()); } - ASSERT_EQ(0, CommonErrorGetDetailCount(&error)); - struct AdbcErrorDetail detail = CommonErrorGetDetail(&error, 0); + ASSERT_EQ(0, InternalAdbcCommonErrorGetDetailCount(&error)); + struct AdbcErrorDetail detail = InternalAdbcCommonErrorGetDetail(&error, 0); ASSERT_EQ(nullptr, detail.key); ASSERT_EQ(nullptr, detail.value); ASSERT_EQ(0, detail.value_length); @@ -105,29 +105,29 @@ TEST(ErrorDetails, Adbc100) { TEST(ErrorDetails, Adbc110) { struct AdbcError error = ADBC_ERROR_INIT; - SetError(&error, "My message"); + InternalAdbcSetError(&error, "My message"); ASSERT_NE(nullptr, error.private_data); ASSERT_EQ(nullptr, error.private_driver); { std::string detail = "detail"; - AppendErrorDetail(&error, "key", reinterpret_cast(detail.data()), - detail.size()); + InternalAdbcAppendErrorDetail( + &error, "key", reinterpret_cast(detail.data()), detail.size()); } - ASSERT_EQ(1, CommonErrorGetDetailCount(&error)); - struct AdbcErrorDetail detail = CommonErrorGetDetail(&error, 0); + ASSERT_EQ(1, InternalAdbcCommonErrorGetDetailCount(&error)); + struct AdbcErrorDetail detail = InternalAdbcCommonErrorGetDetail(&error, 0); ASSERT_STREQ("key", detail.key); ASSERT_EQ("detail", std::string_view(reinterpret_cast(detail.value), detail.value_length)); - detail = CommonErrorGetDetail(&error, -1); + detail = InternalAdbcCommonErrorGetDetail(&error, -1); ASSERT_EQ(nullptr, detail.key); ASSERT_EQ(nullptr, detail.value); ASSERT_EQ(0, detail.value_length); - detail = CommonErrorGetDetail(&error, 2); + detail = InternalAdbcCommonErrorGetDetail(&error, 2); ASSERT_EQ(nullptr, detail.key); ASSERT_EQ(nullptr, detail.value); ASSERT_EQ(0, detail.value_length); @@ -139,7 +139,7 @@ TEST(ErrorDetails, Adbc110) { TEST(ErrorDetails, RoundTripValues) { struct AdbcError error = ADBC_ERROR_INIT; - SetError(&error, "My message"); + InternalAdbcSetError(&error, "My message"); struct Detail { std::string key; @@ -152,13 +152,13 @@ TEST(ErrorDetails, RoundTripValues) { }; for (const auto& detail : details) { - AppendErrorDetail(&error, detail.key.c_str(), detail.value.data(), - detail.value.size()); + InternalAdbcAppendErrorDetail(&error, detail.key.c_str(), detail.value.data(), + detail.value.size()); } - ASSERT_EQ(details.size(), CommonErrorGetDetailCount(&error)); + ASSERT_EQ(details.size(), InternalAdbcCommonErrorGetDetailCount(&error)); for (int i = 0; i < static_cast(details.size()); i++) { - struct AdbcErrorDetail detail = CommonErrorGetDetail(&error, i); + struct AdbcErrorDetail detail = InternalAdbcCommonErrorGetDetail(&error, i); ASSERT_EQ(details[i].key, detail.key); ASSERT_EQ(details[i].value.size(), detail.value_length); ASSERT_THAT(std::vector(detail.value, detail.value + detail.value_length), @@ -209,42 +209,45 @@ TEST(AdbcGetObjectsData, GetObjectsByName) { mock_table.table_constraints = constraints; mock_table.n_table_constraints = 2; - EXPECT_EQ(AdbcGetObjectsDataGetTableByName(&mock_data, "mock_catalog", "mock_schema", - "table"), + EXPECT_EQ(InternalAdbcGetObjectsDataGetTableByName(&mock_data, "mock_catalog", + "mock_schema", "table"), &mock_table); - EXPECT_EQ(AdbcGetObjectsDataGetTableByName(&mock_data, "mock_catalog", "mock_schema", - "table_suffix"), + EXPECT_EQ(InternalAdbcGetObjectsDataGetTableByName(&mock_data, "mock_catalog", + "mock_schema", "table_suffix"), &mock_table_suffix); - EXPECT_EQ(AdbcGetObjectsDataGetTableByName(&mock_data, "mock_catalog", "mock_schema", - "nonexistent"), + EXPECT_EQ(InternalAdbcGetObjectsDataGetTableByName(&mock_data, "mock_catalog", + "mock_schema", "nonexistent"), nullptr); - EXPECT_EQ(AdbcGetObjectsDataGetCatalogByName(&mock_data, "mock_catalog"), + EXPECT_EQ(InternalAdbcGetObjectsDataGetCatalogByName(&mock_data, "mock_catalog"), &mock_catalog); - EXPECT_EQ(AdbcGetObjectsDataGetCatalogByName(&mock_data, "nonexistent"), nullptr); + EXPECT_EQ(InternalAdbcGetObjectsDataGetCatalogByName(&mock_data, "nonexistent"), + nullptr); - EXPECT_EQ(AdbcGetObjectsDataGetSchemaByName(&mock_data, "mock_catalog", "mock_schema"), + EXPECT_EQ(InternalAdbcGetObjectsDataGetSchemaByName(&mock_data, "mock_catalog", + "mock_schema"), &mock_schema); - EXPECT_EQ(AdbcGetObjectsDataGetSchemaByName(&mock_data, "mock_catalog", "nonexistent"), + EXPECT_EQ(InternalAdbcGetObjectsDataGetSchemaByName(&mock_data, "mock_catalog", + "nonexistent"), nullptr); - EXPECT_EQ(AdbcGetObjectsDataGetColumnByName(&mock_data, "mock_catalog", "mock_schema", - "table", "column"), + EXPECT_EQ(InternalAdbcGetObjectsDataGetColumnByName(&mock_data, "mock_catalog", + "mock_schema", "table", "column"), &mock_column); - EXPECT_EQ(AdbcGetObjectsDataGetColumnByName(&mock_data, "mock_catalog", "mock_schema", - "table", "column_suffix"), + EXPECT_EQ(InternalAdbcGetObjectsDataGetColumnByName( + &mock_data, "mock_catalog", "mock_schema", "table", "column_suffix"), &mock_column_suffix); - EXPECT_EQ(AdbcGetObjectsDataGetColumnByName(&mock_data, "mock_catalog", "mock_schema", - "table", "nonexistent"), + EXPECT_EQ(InternalAdbcGetObjectsDataGetColumnByName( + &mock_data, "mock_catalog", "mock_schema", "table", "nonexistent"), nullptr); - EXPECT_EQ(AdbcGetObjectsDataGetConstraintByName(&mock_data, "mock_catalog", - "mock_schema", "table", "constraint"), + EXPECT_EQ(InternalAdbcGetObjectsDataGetConstraintByName( + &mock_data, "mock_catalog", "mock_schema", "table", "constraint"), &mock_constraint); - EXPECT_EQ(AdbcGetObjectsDataGetConstraintByName( + EXPECT_EQ(InternalAdbcGetObjectsDataGetConstraintByName( &mock_data, "mock_catalog", "mock_schema", "table", "constraint_suffix"), &mock_constraint_suffix); - EXPECT_EQ(AdbcGetObjectsDataGetConstraintByName(&mock_data, "mock_catalog", - "mock_schema", "table", "nonexistent"), + EXPECT_EQ(InternalAdbcGetObjectsDataGetConstraintByName( + &mock_data, "mock_catalog", "mock_schema", "table", "nonexistent"), nullptr); } diff --git a/c/driver/flightsql/AdbcDriverFlightSQLConfig.cmake.in b/c/driver/flightsql/AdbcDriverFlightSQLConfig.cmake.in index d43363266d..c414275852 100644 --- a/c/driver/flightsql/AdbcDriverFlightSQLConfig.cmake.in +++ b/c/driver/flightsql/AdbcDriverFlightSQLConfig.cmake.in @@ -33,7 +33,7 @@ if(ADBC_BUILD_SHARED) endif() if(ADBC_BUILD_STATIC) - adbc_add_shared_library( + adbc_add_static_library( AdbcDriverFlightSQL::adbc_driver_flightsql_static adbc_driver_flightsql) endif() diff --git a/c/driver/flightsql/CMakeLists.txt b/c/driver/flightsql/CMakeLists.txt index 2983c6a49c..9f60cbf07a 100644 --- a/c/driver/flightsql/CMakeLists.txt +++ b/c/driver/flightsql/CMakeLists.txt @@ -32,6 +32,8 @@ add_go_lib("${REPOSITORY_ROOT}/go/adbc/pkg/flightsql/" adbc-driver-flightsql SHARED_LINK_FLAGS ${LDFLAGS} + DEFINES + ${ADBC_TARGET_COMPILE_DEFINITIONS} OUTPUTS ADBC_LIBRARIES) diff --git a/c/driver/flightsql/dremio_flightsql_test.cc b/c/driver/flightsql/dremio_flightsql_test.cc index 341845d0e2..38944837d1 100644 --- a/c/driver/flightsql/dremio_flightsql_test.cc +++ b/c/driver/flightsql/dremio_flightsql_test.cc @@ -37,7 +37,7 @@ class DremioFlightSqlQuirks : public adbc_validation::DriverQuirks { const char* user_raw = std::getenv("ADBC_DREMIO_FLIGHTSQL_USER"); const char* pass_raw = std::getenv("ADBC_DREMIO_FLIGHTSQL_PASS"); if (!uri_raw || !user_raw || !pass_raw) { - SetError(error, "Missing required environment variables"); + InternalAdbcSetError(error, "Missing required environment variables"); return ADBC_STATUS_INVALID_ARGUMENT; } EXPECT_THAT(AdbcDatabaseSetOption(database, "uri", uri_raw, error), diff --git a/c/driver/flightsql/sqlite_flightsql_test.cc b/c/driver/flightsql/sqlite_flightsql_test.cc index 033467b7f4..dfe9776bd7 100644 --- a/c/driver/flightsql/sqlite_flightsql_test.cc +++ b/c/driver/flightsql/sqlite_flightsql_test.cc @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -35,10 +36,6 @@ using adbc_validation::IsOkErrno; using adbc_validation::IsOkStatus; -extern "C" { -AdbcStatusCode FlightSQLDriverInit(int, void*, struct AdbcError*); -} - #define CHECK_OK(EXPR) \ do { \ if (auto adbc_status = (EXPR); adbc_status != ADBC_STATUS_OK) { \ @@ -244,12 +241,12 @@ TEST_F(SqliteFlightSqlTest, AdbcDriverBackwardsCompatibility) { std::memset(&driver, 0, ADBC_DRIVER_1_1_0_SIZE); driver.ErrorGetDetailCount = Canary; - ASSERT_THAT(::FlightSQLDriverInit(ADBC_VERSION_1_0_0, &driver, &error), + ASSERT_THAT(::AdbcDriverFlightsqlInit(ADBC_VERSION_1_0_0, &driver, &error), IsOkStatus(&error)); ASSERT_EQ(Canary, driver.ErrorGetDetailCount); - ASSERT_THAT(::FlightSQLDriverInit(424242, &driver, &error), + ASSERT_THAT(::AdbcDriverFlightsqlInit(424242, &driver, &error), adbc_validation::IsStatus(ADBC_STATUS_NOT_IMPLEMENTED, &error)); } diff --git a/c/driver/framework/AdbcDriverFrameworkConfig.cmake.in b/c/driver/framework/AdbcDriverFrameworkConfig.cmake.in new file mode 100644 index 0000000000..09a2ea3096 --- /dev/null +++ b/c/driver/framework/AdbcDriverFrameworkConfig.cmake.in @@ -0,0 +1,24 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +@PACKAGE_INIT@ + +set(ADBC_VERSION "@ADBC_VERSION@") + +include("${CMAKE_CURRENT_LIST_DIR}/AdbcDriverFrameworkTargets.cmake") + +check_required_components(AdbcDriverFramework) diff --git a/c/driver/framework/CMakeLists.txt b/c/driver/framework/CMakeLists.txt index fa2e03b978..464f3640cf 100644 --- a/c/driver/framework/CMakeLists.txt +++ b/c/driver/framework/CMakeLists.txt @@ -20,11 +20,26 @@ include(FetchContent) add_library(adbc_driver_framework STATIC objects.cc utility.cc) adbc_configure_target(adbc_driver_framework) set_target_properties(adbc_driver_framework PROPERTIES POSITION_INDEPENDENT_CODE ON) -target_include_directories(adbc_driver_framework - PRIVATE "${REPOSITORY_ROOT}/c/" "${REPOSITORY_ROOT}/c/include" - "${REPOSITORY_ROOT}/c/vendor") +target_include_directories(adbc_driver_framework PRIVATE "${REPOSITORY_ROOT}/c/" + "${REPOSITORY_ROOT}/c/include") target_link_libraries(adbc_driver_framework PUBLIC adbc_driver_common fmt::fmt) +# For static builds, we need to install the static library here so downstream +# applications can link to it +if(ADBC_BUILD_STATIC) + if(ADBC_WITH_VENDORED_FMT OR ADBC_WITH_VENDORED_NANOARROW) + message(WARNING "adbc_driver_framework is not installed when ADBC_WITH_VENDORED_FMT or ADBC_WITH_VENDORED_NANOARROW are ON. To use the static libraries, for now you must provide these dependencies instead of using the vendored copies" + ) + else() + install(TARGETS adbc_driver_framework ${INSTALL_IS_OPTIONAL} + EXPORT adbc_driver_framework_targets + RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + arrow_install_cmake_package(AdbcDriverFramework adbc_driver_framework_targets) + endif() +endif() + if(ADBC_BUILD_TESTS) add_test_case(driver_framework_test PREFIX diff --git a/c/driver/postgresql/AdbcDriverPostgreSQLConfig.cmake.in b/c/driver/postgresql/AdbcDriverPostgreSQLConfig.cmake.in index c879d18e6b..30a22c3a7a 100644 --- a/c/driver/postgresql/AdbcDriverPostgreSQLConfig.cmake.in +++ b/c/driver/postgresql/AdbcDriverPostgreSQLConfig.cmake.in @@ -17,8 +17,12 @@ @PACKAGE_INIT@ +include(CMakeFindDependencyMacro) + set(ADBC_VERSION "@ADBC_VERSION@") include("${CMAKE_CURRENT_LIST_DIR}/AdbcDriverPostgreSQLTargets.cmake") +find_dependency(PostgreSQL) + check_required_components(AdbcDriverPostgreSQL) diff --git a/c/driver/postgresql/CMakeLists.txt b/c/driver/postgresql/CMakeLists.txt index 92c4c9f92d..e044a20d14 100644 --- a/c/driver/postgresql/CMakeLists.txt +++ b/c/driver/postgresql/CMakeLists.txt @@ -58,6 +58,10 @@ foreach(LIB_TARGET ${ADBC_LIBRARIES}) target_include_directories(${LIB_TARGET} SYSTEM PRIVATE ${REPOSITORY_ROOT}/c/ ${REPOSITORY_ROOT}/c/include/ ${LIBPQ_INCLUDE_DIRS} ${REPOSITORY_ROOT}/c/driver) + + if(NOT ADBC_DEFINE_COMMON_ENTRYPOINTS) + target_compile_definitions(${LIB_TARGET} PRIVATE ${ADBC_TARGET_COMPILE_DEFINITIONS}) + endif() endforeach() if(ADBC_TEST_LINKAGE STREQUAL "shared") diff --git a/c/driver/postgresql/connection.cc b/c/driver/postgresql/connection.cc index d3b6911387..8fa367e18b 100644 --- a/c/driver/postgresql/connection.cc +++ b/c/driver/postgresql/connection.cc @@ -463,7 +463,7 @@ AdbcStatusCode PostgresConnection::Cancel(struct AdbcError* error) { // > The return value is 1 if the cancel request was successfully dispatched // > and 0 if not. if (PQcancel(cancel_, errbuf, sizeof(errbuf)) != 1) { - SetError(error, "[libpq] Failed to cancel operation: %s", errbuf); + InternalAdbcSetError(error, "[libpq] Failed to cancel operation: %s", errbuf); return ADBC_STATUS_UNKNOWN; } return ADBC_STATUS_OK; @@ -471,7 +471,7 @@ AdbcStatusCode PostgresConnection::Cancel(struct AdbcError* error) { AdbcStatusCode PostgresConnection::Commit(struct AdbcError* error) { if (autocommit_) { - SetError(error, "%s", "[libpq] Cannot commit when autocommit is enabled"); + InternalAdbcSetError(error, "%s", "[libpq] Cannot commit when autocommit is enabled"); return ADBC_STATUS_INVALID_STATE; } @@ -526,7 +526,8 @@ AdbcStatusCode PostgresConnection::GetInfo(struct AdbcConnection* connection, RAISE_STATUS(error, result_helper.Execute()); auto it = result_helper.begin(); if (it == result_helper.end()) { - SetError(error, "[libpq] PostgreSQL returned no rows for '%s'", stmt); + InternalAdbcSetError(error, "[libpq] PostgreSQL returned no rows for '%s'", + stmt); return ADBC_STATUS_INTERNAL; } const char* server_version_num = (*it)[0].data; @@ -620,8 +621,8 @@ AdbcStatusCode PostgresConnection::GetOption(const char* option, char* value, RAISE_STATUS(error, result_helper.Execute()); auto it = result_helper.begin(); if (it == result_helper.end()) { - SetError(error, - "[libpq] PostgreSQL returned no rows for 'SELECT CURRENT_SCHEMA()'"); + InternalAdbcSetError( + error, "[libpq] PostgreSQL returned no rows for 'SELECT CURRENT_SCHEMA()'"); return ADBC_STATUS_INTERNAL; } output = (*it)[0].data; @@ -813,7 +814,8 @@ AdbcStatusCode PostgresConnectionGetStatisticsImpl(PGconn* conn, const char* db_ for (PqResultRow row : result_helper) { auto reltuples = row[5].ParseDouble(); if (!reltuples) { - SetError(error, "[libpq] Invalid double value in reltuples: '%s'", row[5].data); + InternalAdbcSetError(error, "[libpq] Invalid double value in reltuples: '%s'", + row[5].data); return ADBC_STATUS_INTERNAL; } @@ -837,7 +839,8 @@ AdbcStatusCode PostgresConnectionGetStatisticsImpl(PGconn* conn, const char* db_ auto null_frac = row[2].ParseDouble(); if (!null_frac) { - SetError(error, "[libpq] Invalid double value in null_frac: '%s'", row[2].data); + InternalAdbcSetError(error, "[libpq] Invalid double value in null_frac: '%s'", + row[2].data); return ADBC_STATUS_INTERNAL; } @@ -862,7 +865,8 @@ AdbcStatusCode PostgresConnectionGetStatisticsImpl(PGconn* conn, const char* db_ auto average_byte_width = row[3].ParseDouble(); if (!average_byte_width) { - SetError(error, "[libpq] Invalid double value in avg_width: '%s'", row[3].data); + InternalAdbcSetError(error, "[libpq] Invalid double value in avg_width: '%s'", + row[3].data); return ADBC_STATUS_INTERNAL; } @@ -888,7 +892,8 @@ AdbcStatusCode PostgresConnectionGetStatisticsImpl(PGconn* conn, const char* db_ auto n_distinct = row[4].ParseDouble(); if (!n_distinct) { - SetError(error, "[libpq] Invalid double value in avg_width: '%s'", row[4].data); + InternalAdbcSetError(error, "[libpq] Invalid double value in avg_width: '%s'", + row[4].data); return ADBC_STATUS_INTERNAL; } @@ -938,13 +943,14 @@ AdbcStatusCode PostgresConnection::GetStatistics(const char* catalog, struct AdbcError* error) { // Simplify our jobs here if (!approximate) { - SetError(error, "[libpq] Exact statistics are not implemented"); + InternalAdbcSetError(error, "[libpq] Exact statistics are not implemented"); return ADBC_STATUS_NOT_IMPLEMENTED; } else if (!db_schema) { - SetError(error, "[libpq] Must request statistics for a single schema"); + InternalAdbcSetError(error, "[libpq] Must request statistics for a single schema"); return ADBC_STATUS_NOT_IMPLEMENTED; } else if (catalog && std::strcmp(catalog, PQdb(conn_)) != 0) { - SetError(error, "[libpq] Can only request statistics for current catalog"); + InternalAdbcSetError(error, + "[libpq] Can only request statistics for current catalog"); return ADBC_STATUS_NOT_IMPLEMENTED; } @@ -1060,8 +1066,9 @@ AdbcStatusCode PostgresConnection::GetTableSchema(const char* catalog, PostgresType pg_type; if (type_resolver_->FindWithDefault(pg_oid, &pg_type) != NANOARROW_OK) { - SetError(error, "%s%d%s%s%s%" PRIu32, "Error resolving type code for column #", - row_counter + 1, " (\"", colname, "\") with oid ", pg_oid); + InternalAdbcSetError(error, "%s%d%s%s%s%" PRIu32, + "Error resolving type code for column #", row_counter + 1, + " (\"", colname, "\") with oid ", pg_oid); final_status = ADBC_STATUS_NOT_IMPLEMENTED; break; } @@ -1092,7 +1099,7 @@ AdbcStatusCode PostgresConnection::GetTableTypes(struct AdbcConnection* connecti AdbcStatusCode PostgresConnection::Init(struct AdbcDatabase* database, struct AdbcError* error) { if (!database || !database->private_data) { - SetError(error, "[libpq] Must provide an initialized AdbcDatabase"); + InternalAdbcSetError(error, "[libpq] Must provide an initialized AdbcDatabase"); return ADBC_STATUS_INVALID_ARGUMENT; } database_ = @@ -1103,7 +1110,7 @@ AdbcStatusCode PostgresConnection::Init(struct AdbcDatabase* database, cancel_ = PQgetCancel(conn_); if (!cancel_) { - SetError(error, "[libpq] Could not initialize PGcancel"); + InternalAdbcSetError(error, "[libpq] Could not initialize PGcancel"); return ADBC_STATUS_UNKNOWN; } @@ -1130,7 +1137,8 @@ AdbcStatusCode PostgresConnection::Release(struct AdbcError* error) { AdbcStatusCode PostgresConnection::Rollback(struct AdbcError* error) { if (autocommit_) { - SetError(error, "%s", "[libpq] Cannot rollback when autocommit is enabled"); + InternalAdbcSetError(error, "%s", + "[libpq] Cannot rollback when autocommit is enabled"); return ADBC_STATUS_INVALID_STATE; } @@ -1144,7 +1152,8 @@ AdbcStatusCode PostgresConnection::Rollback(struct AdbcError* error) { PGresult* result = PQexec(conn_, "ROLLBACK AND CHAIN"); if (PQresultStatus(result) != PGRES_COMMAND_OK) { - SetError(error, "%s%s", "[libpq] Failed to rollback: ", PQerrorMessage(conn_)); + InternalAdbcSetError(error, "%s%s", + "[libpq] Failed to rollback: ", PQerrorMessage(conn_)); PQclear(result); return ADBC_STATUS_IO; } @@ -1161,7 +1170,8 @@ AdbcStatusCode PostgresConnection::SetOption(const char* key, const char* value, } else if (std::strcmp(value, ADBC_OPTION_VALUE_DISABLED) == 0) { autocommit = false; } else { - SetError(error, "%s%s%s%s", "[libpq] Invalid value for option ", key, ": ", value); + InternalAdbcSetError(error, "%s%s%s%s", "[libpq] Invalid value for option ", key, + ": ", value); return ADBC_STATUS_INVALID_ARGUMENT; } @@ -1175,8 +1185,8 @@ AdbcStatusCode PostgresConnection::SetOption(const char* key, const char* value, PGresult* result = PQexec(conn_, query); if (PQresultStatus(result) != PGRES_COMMAND_OK) { - SetError(error, "%s%s", - "[libpq] Failed to update autocommit: ", PQerrorMessage(conn_)); + InternalAdbcSetError(error, "%s%s", "[libpq] Failed to update autocommit: ", + PQerrorMessage(conn_)); PQclear(result); return ADBC_STATUS_IO; } @@ -1193,7 +1203,8 @@ AdbcStatusCode PostgresConnection::SetOption(const char* key, const char* value, // PostgreSQL doesn't accept a parameter here char* value_esc = PQescapeIdentifier(conn_, value, strlen(value)); if (!value_esc) { - SetError(error, "[libpq] Could not escape identifier: %s", PQerrorMessage(conn_)); + InternalAdbcSetError(error, "[libpq] Could not escape identifier: %s", + PQerrorMessage(conn_)); return ADBC_STATUS_INTERNAL; } std::string query = fmt::format("SET search_path TO {}", value_esc); @@ -1203,26 +1214,26 @@ AdbcStatusCode PostgresConnection::SetOption(const char* key, const char* value, RAISE_STATUS(error, result_helper.Execute()); return ADBC_STATUS_OK; } - SetError(error, "%s%s", "[libpq] Unknown option ", key); + InternalAdbcSetError(error, "%s%s", "[libpq] Unknown option ", key); return ADBC_STATUS_NOT_IMPLEMENTED; } AdbcStatusCode PostgresConnection::SetOptionBytes(const char* key, const uint8_t* value, size_t length, struct AdbcError* error) { - SetError(error, "%s%s", "[libpq] Unknown option ", key); + InternalAdbcSetError(error, "%s%s", "[libpq] Unknown option ", key); return ADBC_STATUS_NOT_IMPLEMENTED; } AdbcStatusCode PostgresConnection::SetOptionDouble(const char* key, double value, struct AdbcError* error) { - SetError(error, "%s%s", "[libpq] Unknown option ", key); + InternalAdbcSetError(error, "%s%s", "[libpq] Unknown option ", key); return ADBC_STATUS_NOT_IMPLEMENTED; } AdbcStatusCode PostgresConnection::SetOptionInt(const char* key, int64_t value, struct AdbcError* error) { - SetError(error, "%s%s", "[libpq] Unknown option ", key); + InternalAdbcSetError(error, "%s%s", "[libpq] Unknown option ", key); return ADBC_STATUS_NOT_IMPLEMENTED; } diff --git a/c/driver/postgresql/copy/writer.h b/c/driver/postgresql/copy/writer.h index e88ed691cd..1c3176ab34 100644 --- a/c/driver/postgresql/copy/writer.h +++ b/c/driver/postgresql/copy/writer.h @@ -498,9 +498,9 @@ class PostgresCopyListFieldWriter : public PostgresCopyFieldWriter { NANOARROW_RETURN_NOT_OK(WriteChecked(buffer, lb, error)); } - ArrowBufferAppend(buffer, tmp->data, tmp->size_bytes); + NANOARROW_RETURN_NOT_OK(ArrowBufferAppend(buffer, tmp->data, tmp->size_bytes)); - return ADBC_STATUS_OK; + return NANOARROW_OK; } private: diff --git a/c/driver/postgresql/database.cc b/c/driver/postgresql/database.cc index f5652e8fac..cecf7a6eb0 100644 --- a/c/driver/postgresql/database.cc +++ b/c/driver/postgresql/database.cc @@ -75,8 +75,8 @@ AdbcStatusCode PostgresDatabase::Init(struct AdbcError* error) { AdbcStatusCode PostgresDatabase::Release(struct AdbcError* error) { if (open_connections_ != 0) { - SetError(error, "%s%" PRId32 "%s", "[libpq] Database released with ", - open_connections_, " open connections"); + InternalAdbcSetError(error, "%s%" PRId32 "%s", "[libpq] Database released with ", + open_connections_, " open connections"); return ADBC_STATUS_INVALID_STATE; } return ADBC_STATUS_OK; @@ -87,7 +87,7 @@ AdbcStatusCode PostgresDatabase::SetOption(const char* key, const char* value, if (strcmp(key, "uri") == 0) { uri_ = value; } else { - SetError(error, "%s%s", "[libpq] Unknown database option ", key); + InternalAdbcSetError(error, "%s%s", "[libpq] Unknown database option ", key); return ADBC_STATUS_NOT_IMPLEMENTED; } return ADBC_STATUS_OK; @@ -95,31 +95,33 @@ AdbcStatusCode PostgresDatabase::SetOption(const char* key, const char* value, AdbcStatusCode PostgresDatabase::SetOptionBytes(const char* key, const uint8_t* value, size_t length, struct AdbcError* error) { - SetError(error, "%s%s", "[libpq] Unknown option ", key); + InternalAdbcSetError(error, "%s%s", "[libpq] Unknown option ", key); return ADBC_STATUS_NOT_IMPLEMENTED; } AdbcStatusCode PostgresDatabase::SetOptionDouble(const char* key, double value, struct AdbcError* error) { - SetError(error, "%s%s", "[libpq] Unknown option ", key); + InternalAdbcSetError(error, "%s%s", "[libpq] Unknown option ", key); return ADBC_STATUS_NOT_IMPLEMENTED; } AdbcStatusCode PostgresDatabase::SetOptionInt(const char* key, int64_t value, struct AdbcError* error) { - SetError(error, "%s%s", "[libpq] Unknown option ", key); + InternalAdbcSetError(error, "%s%s", "[libpq] Unknown option ", key); return ADBC_STATUS_NOT_IMPLEMENTED; } AdbcStatusCode PostgresDatabase::Connect(PGconn** conn, struct AdbcError* error) { if (uri_.empty()) { - SetError(error, "%s", - "[libpq] Must set database option 'uri' before creating a connection"); + InternalAdbcSetError( + error, "%s", + "[libpq] Must set database option 'uri' before creating a connection"); return ADBC_STATUS_INVALID_STATE; } *conn = PQconnectdb(uri_.c_str()); if (PQstatus(*conn) != CONNECTION_OK) { - SetError(error, "%s%s", "[libpq] Failed to connect: ", PQerrorMessage(*conn)); + InternalAdbcSetError(error, "%s%s", + "[libpq] Failed to connect: ", PQerrorMessage(*conn)); PQfinish(*conn); *conn = nullptr; return ADBC_STATUS_IO; @@ -132,7 +134,7 @@ AdbcStatusCode PostgresDatabase::Disconnect(PGconn** conn, struct AdbcError* err PQfinish(*conn); *conn = nullptr; if (--open_connections_ < 0) { - SetError(error, "%s", "[libpq] Open connection count underflowed"); + InternalAdbcSetError(error, "%s", "[libpq] Open connection count underflowed"); return ADBC_STATUS_INTERNAL; } return ADBC_STATUS_OK; diff --git a/c/driver/postgresql/database.h b/c/driver/postgresql/database.h index e0a00267e3..5adf3af9a6 100644 --- a/c/driver/postgresql/database.h +++ b/c/driver/postgresql/database.h @@ -87,10 +87,3 @@ class PostgresDatabase { std::array redshift_server_version_{}; }; } // namespace adbcpq - -extern "C" { -/// For applications that want to use the driver struct directly, this gives -/// them access to the Init routine. -ADBC_EXPORT -AdbcStatusCode PostgresqlDriverInit(int, void*, struct AdbcError*); -} diff --git a/c/driver/postgresql/postgres_type.h b/c/driver/postgresql/postgres_type.h index d2a5356293..8c331b4185 100644 --- a/c/driver/postgresql/postgres_type.h +++ b/c/driver/postgresql/postgres_type.h @@ -349,7 +349,7 @@ class PostgresType { !typname_.empty() ? typname_.c_str() : PostgresTypname(type_id_); nanoarrow::UniqueBuffer buffer; - ArrowMetadataBuilderInit(buffer.get(), nullptr); + NANOARROW_RETURN_NOT_OK(ArrowMetadataBuilderInit(buffer.get(), nullptr)); // TODO(lidavidm): we have deprecated this in favor of arrow.opaque, // remove once we feel enough time has passed NANOARROW_RETURN_NOT_OK(ArrowMetadataBuilderAppend( diff --git a/c/driver/postgresql/postgresql.cc b/c/driver/postgresql/postgresql.cc index e43db98879..858c743789 100644 --- a/c/driver/postgresql/postgresql.cc +++ b/c/driver/postgresql/postgresql.cc @@ -60,8 +60,8 @@ const struct AdbcError* PostgresErrorFromArrayStream(struct ArrowArrayStream* st } int PostgresErrorGetDetailCount(const struct AdbcError* error) { - if (IsCommonError(error)) { - return CommonErrorGetDetailCount(error); + if (InternalAdbcIsCommonError(error)) { + return InternalAdbcCommonErrorGetDetailCount(error); } if (error->vendor_code != ADBC_ERROR_VENDOR_CODE_PRIVATE_DATA) { @@ -73,8 +73,8 @@ int PostgresErrorGetDetailCount(const struct AdbcError* error) { } struct AdbcErrorDetail PostgresErrorGetDetail(const struct AdbcError* error, int index) { - if (IsCommonError(error)) { - return CommonErrorGetDetail(error, index); + if (InternalAdbcIsCommonError(error)) { + return InternalAdbcCommonErrorGetDetail(error, index); } auto error_obj = reinterpret_cast(error->private_data); @@ -82,6 +82,7 @@ struct AdbcErrorDetail PostgresErrorGetDetail(const struct AdbcError* error, int } } // namespace +#if !defined(ADBC_NO_COMMON_ENTRYPOINTS) int AdbcErrorGetDetailCount(const struct AdbcError* error) { return PostgresErrorGetDetailCount(error); } @@ -94,6 +95,7 @@ const struct AdbcError* AdbcErrorFromArrayStream(struct ArrowArrayStream* stream AdbcStatusCode* status) { return PostgresErrorFromArrayStream(stream, status); } +#endif // ADBC_NO_COMMON_ENTRYPOINTS // --------------------------------------------------------------------- // AdbcDatabase @@ -109,11 +111,11 @@ AdbcStatusCode PostgresDatabaseInit(struct AdbcDatabase* database, AdbcStatusCode PostgresDatabaseNew(struct AdbcDatabase* database, struct AdbcError* error) { if (!database) { - SetError(error, "%s", "[libpq] database must not be null"); + InternalAdbcSetError(error, "%s", "[libpq] database must not be null"); return ADBC_STATUS_INVALID_STATE; } if (database->private_data) { - SetError(error, "%s", "[libpq] database is already initialized"); + InternalAdbcSetError(error, "%s", "[libpq] database is already initialized"); return ADBC_STATUS_INVALID_STATE; } auto impl = std::make_shared(); @@ -195,6 +197,7 @@ AdbcStatusCode PostgresDatabaseSetOptionInt(struct AdbcDatabase* database, } } // namespace +#if !defined(ADBC_NO_COMMON_ENTRYPOINTS) AdbcStatusCode AdbcDatabaseGetOption(struct AdbcDatabase* database, const char* key, char* value, size_t* length, struct AdbcError* error) { @@ -250,6 +253,7 @@ AdbcStatusCode AdbcDatabaseSetOptionDouble(struct AdbcDatabase* database, const double value, struct AdbcError* error) { return PostgresDatabaseSetOptionDouble(database, key, value, error); } +#endif // ADBC_NO_COMMON_ENTRYPOINTS // --------------------------------------------------------------------- // AdbcConnection @@ -450,6 +454,7 @@ AdbcStatusCode PostgresConnectionSetOptionInt(struct AdbcConnection* connection, } // namespace +#if !defined(ADBC_NO_COMMON_ENTRYPOINTS) AdbcStatusCode AdbcConnectionCancel(struct AdbcConnection* connection, struct AdbcError* error) { return PostgresConnectionCancel(connection, error); @@ -584,6 +589,7 @@ AdbcStatusCode AdbcConnectionSetOptionDouble(struct AdbcConnection* connection, struct AdbcError* error) { return PostgresConnectionSetOptionDouble(connection, key, value, error); } +#endif // ADBC_NO_COMMON_ENTRYPOINTS // --------------------------------------------------------------------- // AdbcStatement @@ -761,6 +767,7 @@ AdbcStatusCode PostgresStatementSetSqlQuery(struct AdbcStatement* statement, } } // namespace +#if !defined(ADBC_NO_COMMON_ENTRYPOINTS) AdbcStatusCode AdbcStatementBind(struct AdbcStatement* statement, struct ArrowArray* values, struct ArrowSchema* schema, struct AdbcError* error) { @@ -870,11 +877,12 @@ AdbcStatusCode AdbcStatementSetSqlQuery(struct AdbcStatement* statement, const char* query, struct AdbcError* error) { return PostgresStatementSetSqlQuery(statement, query, error); } +#endif // ADBC_NO_COMMON_ENTRYPOINTS extern "C" { ADBC_EXPORT -AdbcStatusCode PostgresqlDriverInit(int version, void* raw_driver, - struct AdbcError* error) { +AdbcStatusCode AdbcDriverPostgresqlInit(int version, void* raw_driver, + struct AdbcError* error) { if (version != ADBC_VERSION_1_0_0 && version != ADBC_VERSION_1_1_0) { return ADBC_STATUS_NOT_IMPLEMENTED; } @@ -951,8 +959,10 @@ AdbcStatusCode PostgresqlDriverInit(int version, void* raw_driver, return ADBC_STATUS_OK; } +#if !defined(ADBC_NO_COMMON_ENTRYPOINTS) ADBC_EXPORT AdbcStatusCode AdbcDriverInit(int version, void* raw_driver, struct AdbcError* error) { - return PostgresqlDriverInit(version, raw_driver, error); + return AdbcDriverPostgresqlInit(version, raw_driver, error); } +#endif // ADBC_NO_COMMON_ENTRYPOINTS } diff --git a/c/driver/postgresql/postgresql_test.cc b/c/driver/postgresql/postgresql_test.cc index 5167dbef71..fec2302c1e 100644 --- a/c/driver/postgresql/postgresql_test.cc +++ b/c/driver/postgresql/postgresql_test.cc @@ -28,13 +28,14 @@ #include #include +#include #include #include #include +#include #include "common/options.h" #include "common/utils.h" -#include "database.h" #include "validation/adbc_validation.h" #include "validation/adbc_validation_util.h" @@ -233,12 +234,12 @@ TEST_F(PostgresDatabaseTest, AdbcDriverBackwardsCompatibility) { std::memset(&driver, 0, ADBC_DRIVER_1_1_0_SIZE); driver.ErrorGetDetailCount = Canary; - ASSERT_THAT(::PostgresqlDriverInit(ADBC_VERSION_1_0_0, &driver, &error), + ASSERT_THAT(::AdbcDriverPostgresqlInit(ADBC_VERSION_1_0_0, &driver, &error), IsOkStatus(&error)); ASSERT_EQ(Canary, driver.ErrorGetDetailCount); - ASSERT_THAT(::PostgresqlDriverInit(424242, &driver, &error), + ASSERT_THAT(::AdbcDriverPostgresqlInit(424242, &driver, &error), IsStatus(ADBC_STATUS_NOT_IMPLEMENTED, &error)); } @@ -343,7 +344,7 @@ TEST_F(PostgresConnectionTest, GetObjectsGetCatalogs) { auto catalogs = {"postgres", "template0", "template1"}; for (auto catalog : catalogs) { struct AdbcGetObjectsCatalog* cat = - AdbcGetObjectsDataGetCatalogByName(*get_objects_data, catalog); + InternalAdbcGetObjectsDataGetCatalogByName(*get_objects_data, catalog); ASSERT_NE(cat, nullptr) << "catalog " << catalog << " not found"; } } @@ -367,7 +368,7 @@ TEST_F(PostgresConnectionTest, GetObjectsGetDbSchemas) { << "could not initialize the AdbcGetObjectsData object"; struct AdbcGetObjectsSchema* schema = - AdbcGetObjectsDataGetSchemaByName(*get_objects_data, "postgres", "public"); + InternalAdbcGetObjectsDataGetSchemaByName(*get_objects_data, "postgres", "public"); ASSERT_NE(schema, nullptr) << "schema public not found"; } @@ -411,12 +412,12 @@ TEST_F(PostgresConnectionTest, GetObjectsGetAllFindsPrimaryKey) { ASSERT_NE(*get_objects_data, nullptr) << "could not initialize the AdbcGetObjectsData object"; - struct AdbcGetObjectsTable* table = AdbcGetObjectsDataGetTableByName( + struct AdbcGetObjectsTable* table = InternalAdbcGetObjectsDataGetTableByName( *get_objects_data, "postgres", "public", "adbc_pkey_test"); ASSERT_NE(table, nullptr) << "could not find adbc_pkey_test table"; ASSERT_EQ(table->n_table_columns, 2); - struct AdbcGetObjectsColumn* column = AdbcGetObjectsDataGetColumnByName( + struct AdbcGetObjectsColumn* column = InternalAdbcGetObjectsDataGetColumnByName( *get_objects_data, "postgres", "public", "adbc_pkey_test", "id"); ASSERT_NE(column, nullptr) << "could not find id column on adbc_pkey_test table"; @@ -424,8 +425,10 @@ TEST_F(PostgresConnectionTest, GetObjectsGetAllFindsPrimaryKey) { << "expected 1 constraint on adbc_pkey_test table, found: " << table->n_table_constraints; - struct AdbcGetObjectsConstraint* constraint = AdbcGetObjectsDataGetConstraintByName( - *get_objects_data, "postgres", "public", "adbc_pkey_test", "adbc_pkey_test_pkey"); + struct AdbcGetObjectsConstraint* constraint = + InternalAdbcGetObjectsDataGetConstraintByName(*get_objects_data, "postgres", + "public", "adbc_pkey_test", + "adbc_pkey_test_pkey"); ASSERT_NE(constraint, nullptr) << "could not find adbc_pkey_test_pkey constraint"; auto constraint_type = std::string(constraint->constraint_type.data, @@ -503,7 +506,7 @@ TEST_F(PostgresConnectionTest, GetObjectsGetAllFindsForeignKey) { ASSERT_NE(*get_objects_data, nullptr) << "could not initialize the AdbcGetInfoData object"; - struct AdbcGetObjectsTable* table = AdbcGetObjectsDataGetTableByName( + struct AdbcGetObjectsTable* table = InternalAdbcGetObjectsDataGetTableByName( *get_objects_data, "postgres", "public", "adbc_fkey_test"); ASSERT_NE(table, nullptr) << "could not find adbc_fkey_test table"; ASSERT_EQ(table->n_table_constraints, 1) @@ -513,8 +516,9 @@ TEST_F(PostgresConnectionTest, GetObjectsGetAllFindsForeignKey) { const std::string version = adbc_validation::GetDriverVendorVersion(&connection); const std::string search_name = version < "120000" ? "adbc_fkey_test_fid1_fkey" : "adbc_fkey_test_fid1_fid2_fkey"; - struct AdbcGetObjectsConstraint* constraint = AdbcGetObjectsDataGetConstraintByName( - *get_objects_data, "postgres", "public", "adbc_fkey_test", search_name.c_str()); + struct AdbcGetObjectsConstraint* constraint = + InternalAdbcGetObjectsDataGetConstraintByName( + *get_objects_data, "postgres", "public", "adbc_fkey_test", search_name.c_str()); ASSERT_NE(constraint, nullptr) << "could not find " << search_name << " constraint"; auto constraint_type = std::string(constraint->constraint_type.data, @@ -615,11 +619,11 @@ TEST_F(PostgresConnectionTest, GetObjectsTableTypesFilter) { ASSERT_NE(*get_objects_data, nullptr) << "could not initialize the AdbcGetInfoData object"; - struct AdbcGetObjectsTable* table = AdbcGetObjectsDataGetTableByName( + struct AdbcGetObjectsTable* table = InternalAdbcGetObjectsDataGetTableByName( *get_objects_data, "postgres", "public", "adbc_table_types_table_test"); ASSERT_EQ(table, nullptr) << "unexpected table adbc_table_types_table_test found"; - struct AdbcGetObjectsTable* view = AdbcGetObjectsDataGetTableByName( + struct AdbcGetObjectsTable* view = InternalAdbcGetObjectsDataGetTableByName( *get_objects_data, "postgres", "public", "adbc_table_types_view_test"); ASSERT_NE(view, nullptr) << "did not find view adbc_table_types_view_test"; } diff --git a/c/driver/postgresql/statement.cc b/c/driver/postgresql/statement.cc index a83bca13f5..677236ef09 100644 --- a/c/driver/postgresql/statement.cc +++ b/c/driver/postgresql/statement.cc @@ -57,12 +57,12 @@ int TupleReader::GetSchema(struct ArrowSchema* out) { int na_res = copy_reader_->GetSchema(out); if (out->release == nullptr) { - SetError(&error_, "[libpq] Result set was already consumed or freed"); + InternalAdbcSetError(&error_, "[libpq] Result set was already consumed or freed"); status_ = ADBC_STATUS_INVALID_STATE; - return AdbcStatusCodeToErrno(status_); + return InternalAdbcStatusCodeToErrno(status_); } else if (na_res != NANOARROW_OK) { // e.g., Can't allocate memory - SetError(&error_, "[libpq] Error copying schema"); + InternalAdbcSetError(&error_, "[libpq] Error copying schema"); status_ = ADBC_STATUS_INTERNAL; } @@ -80,9 +80,10 @@ int TupleReader::GetCopyData() { int get_copy_res = PQgetCopyData(conn_, &pgbuf_, /*async=*/0); if (get_copy_res == -2) { - SetError(&error_, "[libpq] PQgetCopyData() failed: %s", PQerrorMessage(conn_)); + InternalAdbcSetError(&error_, "[libpq] PQgetCopyData() failed: %s", + PQerrorMessage(conn_)); status_ = ADBC_STATUS_IO; - return AdbcStatusCodeToErrno(status_); + return InternalAdbcStatusCodeToErrno(status_); } if (get_copy_res == -1) { @@ -93,7 +94,7 @@ int TupleReader::GetCopyData() { if (pq_status != PGRES_COMMAND_OK) { status_ = SetError(&error_, result_, "[libpq] Execution error [%s]: %s", PQresStatus(pq_status), PQresultErrorMessage(result_)); - return AdbcStatusCodeToErrno(status_); + return InternalAdbcStatusCodeToErrno(status_); } else { return ENODATA; } @@ -109,8 +110,8 @@ int TupleReader::AppendRowAndFetchNext() { // call to PQgetCopyData()) int na_res = copy_reader_->ReadRecord(&data_, &na_error_); if (na_res != NANOARROW_OK && na_res != ENODATA) { - SetError(&error_, "[libpq] ReadRecord failed at row %" PRId64 ": %s", row_id_, - na_error_.message); + InternalAdbcSetError(&error_, "[libpq] ReadRecord failed at row %" PRId64 ": %s", + row_id_, na_error_.message); status_ = ADBC_STATUS_IO; return na_res; } @@ -136,7 +137,8 @@ int TupleReader::BuildOutput(struct ArrowArray* out) { int na_res = copy_reader_->GetArray(out, &na_error_); if (na_res != NANOARROW_OK) { - SetError(&error_, "[libpq] Failed to build result array: %s", na_error_.message); + InternalAdbcSetError(&error_, "[libpq] Failed to build result array: %s", + na_error_.message); status_ = ADBC_STATUS_INTERNAL; return na_res; } @@ -165,7 +167,7 @@ int TupleReader::GetNext(struct ArrowArray* out) { na_res = copy_reader_->ReadHeader(&data_, &na_error_); if (na_res != NANOARROW_OK) { - SetError(&error_, "[libpq] ReadHeader() failed: %s", na_error_.message); + InternalAdbcSetError(&error_, "[libpq] ReadHeader() failed: %s", na_error_.message); return na_res; } @@ -310,7 +312,8 @@ void TupleReader::ReleaseTrampoline(struct ArrowArrayStream* self) { AdbcStatusCode PostgresStatement::New(struct AdbcConnection* connection, struct AdbcError* error) { if (!connection || !connection->private_data) { - SetError(error, "%s", "[libpq] Must provide an initialized AdbcConnection"); + InternalAdbcSetError(error, "%s", + "[libpq] Must provide an initialized AdbcConnection"); return ADBC_STATUS_INVALID_ARGUMENT; } connection_ = @@ -324,10 +327,10 @@ AdbcStatusCode PostgresStatement::Bind(struct ArrowArray* values, struct ArrowSchema* schema, struct AdbcError* error) { if (!values || !values->release) { - SetError(error, "%s", "[libpq] Must provide non-NULL array"); + InternalAdbcSetError(error, "%s", "[libpq] Must provide non-NULL array"); return ADBC_STATUS_INVALID_ARGUMENT; } else if (!schema || !schema->release) { - SetError(error, "%s", "[libpq] Must provide non-NULL schema"); + InternalAdbcSetError(error, "%s", "[libpq] Must provide non-NULL schema"); return ADBC_STATUS_INVALID_ARGUMENT; } @@ -340,7 +343,7 @@ AdbcStatusCode PostgresStatement::Bind(struct ArrowArray* values, AdbcStatusCode PostgresStatement::Bind(struct ArrowArrayStream* stream, struct AdbcError* error) { if (!stream || !stream->release) { - SetError(error, "%s", "[libpq] Must provide non-NULL stream"); + InternalAdbcSetError(error, "%s", "[libpq] Must provide non-NULL stream"); return ADBC_STATUS_INVALID_ARGUMENT; } // Move stream @@ -363,8 +366,9 @@ AdbcStatusCode PostgresStatement::CreateBulkTable(const std::string& current_sch PGconn* conn = connection_->conn(); if (!ingest_.db_schema.empty() && ingest_.temporary) { - SetError(error, "[libpq] Cannot set both %s and %s", - ADBC_INGEST_OPTION_TARGET_DB_SCHEMA, ADBC_INGEST_OPTION_TEMPORARY); + InternalAdbcSetError(error, "[libpq] Cannot set both %s and %s", + ADBC_INGEST_OPTION_TARGET_DB_SCHEMA, + ADBC_INGEST_OPTION_TEMPORARY); return ADBC_STATUS_INVALID_STATE; } @@ -373,8 +377,9 @@ AdbcStatusCode PostgresStatement::CreateBulkTable(const std::string& current_sch char* escaped = PQescapeIdentifier(conn, ingest_.db_schema.c_str(), ingest_.db_schema.size()); if (escaped == nullptr) { - SetError(error, "[libpq] Failed to escape target schema %s for ingestion: %s", - ingest_.db_schema.c_str(), PQerrorMessage(conn)); + InternalAdbcSetError( + error, "[libpq] Failed to escape target schema %s for ingestion: %s", + ingest_.db_schema.c_str(), PQerrorMessage(conn)); return ADBC_STATUS_INTERNAL; } *escaped_table += escaped; @@ -397,8 +402,9 @@ AdbcStatusCode PostgresStatement::CreateBulkTable(const std::string& current_sch char* escaped = PQescapeIdentifier(conn, ingest_.target.c_str(), ingest_.target.size()); if (escaped == nullptr) { - SetError(error, "[libpq] Failed to escape target table %s for ingestion: %s", - ingest_.target.c_str(), PQerrorMessage(conn)); + InternalAdbcSetError(error, + "[libpq] Failed to escape target table %s for ingestion: %s", + ingest_.target.c_str(), PQerrorMessage(conn)); return ADBC_STATUS_INTERNAL; } *escaped_table += escaped; @@ -451,8 +457,8 @@ AdbcStatusCode PostgresStatement::CreateBulkTable(const std::string& current_sch const char* unescaped = source_schema.children[i]->name; char* escaped = PQescapeIdentifier(conn, unescaped, std::strlen(unescaped)); if (escaped == nullptr) { - SetError(error, "[libpq] Failed to escape column %s for ingestion: %s", unescaped, - PQerrorMessage(conn)); + InternalAdbcSetError(error, "[libpq] Failed to escape column %s for ingestion: %s", + unescaped, PQerrorMessage(conn)); return ADBC_STATUS_INTERNAL; } create += escaped; @@ -473,7 +479,7 @@ AdbcStatusCode PostgresStatement::CreateBulkTable(const std::string& current_sch } create += ")"; - SetError(error, "%s%s", "[libpq] ", create.c_str()); + InternalAdbcSetError(error, "%s%s", "[libpq] ", create.c_str()); PGresult* result = PQexecParams(conn, create.c_str(), /*nParams=*/0, /*paramTypes=*/nullptr, /*paramValues=*/nullptr, /*paramLengths=*/nullptr, /*paramFormats=*/nullptr, @@ -511,7 +517,7 @@ AdbcStatusCode PostgresStatement::ExecuteQuery(struct ArrowArrayStream* stream, } if (query_.empty()) { - SetError(error, "%s", "[libpq] Must SetSqlQuery before ExecuteQuery"); + InternalAdbcSetError(error, "%s", "[libpq] Must SetSqlQuery before ExecuteQuery"); return ADBC_STATUS_INVALID_STATE; } @@ -575,7 +581,7 @@ AdbcStatusCode PostgresStatement::ExecuteSchema(struct ArrowSchema* schema, struct AdbcError* error) { ClearResult(); if (query_.empty()) { - SetError(error, "%s", "[libpq] Must SetSqlQuery before ExecuteQuery"); + InternalAdbcSetError(error, "%s", "[libpq] Must SetSqlQuery before ExecuteQuery"); return ADBC_STATUS_INVALID_STATE; } @@ -590,7 +596,7 @@ AdbcStatusCode PostgresStatement::ExecuteSchema(struct ArrowSchema* schema, &na_error, error); if (std::string(param_schema->format) != "+s") { - SetError(error, "%s", "[libpq] Bind parameters must have type STRUCT"); + InternalAdbcSetError(error, "%s", "[libpq] Bind parameters must have type STRUCT"); return ADBC_STATUS_INVALID_STATE; } @@ -628,12 +634,14 @@ AdbcStatusCode PostgresStatement::ExecuteIngest(struct ArrowArrayStream* stream, int64_t* rows_affected, struct AdbcError* error) { if (!bind_.release) { - SetError(error, "%s", "[libpq] Must Bind() before Execute() for bulk ingestion"); + InternalAdbcSetError(error, "%s", + "[libpq] Must Bind() before Execute() for bulk ingestion"); return ADBC_STATUS_INVALID_STATE; } if (stream != nullptr) { - SetError(error, "%s", "[libpq] Bulk ingest with result set is not supported"); + InternalAdbcSetError(error, "%s", + "[libpq] Bulk ingest with result set is not supported"); return ADBC_STATUS_NOT_IMPLEMENTED; } @@ -645,8 +653,8 @@ AdbcStatusCode PostgresStatement::ExecuteIngest(struct ArrowArrayStream* stream, RAISE_STATUS(error, result_helper.Execute()); auto it = result_helper.begin(); if (it == result_helper.end()) { - SetError(error, - "[libpq] PostgreSQL returned no rows for 'SELECT CURRENT_SCHEMA()'"); + InternalAdbcSetError( + error, "[libpq] PostgreSQL returned no rows for 'SELECT CURRENT_SCHEMA()'"); return ADBC_STATUS_INTERNAL; } current_schema = (*it)[0].data; @@ -717,7 +725,7 @@ AdbcStatusCode PostgresStatement::GetOption(const char* key, char* value, size_t result = "false"; } } else { - SetError(error, "[libpq] Unknown statement option '%s'", key); + InternalAdbcSetError(error, "[libpq] Unknown statement option '%s'", key); return ADBC_STATUS_NOT_FOUND; } @@ -731,13 +739,13 @@ AdbcStatusCode PostgresStatement::GetOption(const char* key, char* value, size_t AdbcStatusCode PostgresStatement::GetOptionBytes(const char* key, uint8_t* value, size_t* length, struct AdbcError* error) { - SetError(error, "[libpq] Unknown statement option '%s'", key); + InternalAdbcSetError(error, "[libpq] Unknown statement option '%s'", key); return ADBC_STATUS_NOT_FOUND; } AdbcStatusCode PostgresStatement::GetOptionDouble(const char* key, double* value, struct AdbcError* error) { - SetError(error, "[libpq] Unknown statement option '%s'", key); + InternalAdbcSetError(error, "[libpq] Unknown statement option '%s'", key); return ADBC_STATUS_NOT_FOUND; } @@ -748,7 +756,7 @@ AdbcStatusCode PostgresStatement::GetOptionInt(const char* key, int64_t* value, *value = reader_->batch_size_hint_bytes_; return ADBC_STATUS_OK; } - SetError(error, "[libpq] Unknown statement option '%s'", key); + InternalAdbcSetError(error, "[libpq] Unknown statement option '%s'", key); return ADBC_STATUS_NOT_FOUND; } @@ -759,7 +767,7 @@ AdbcStatusCode PostgresStatement::GetParameterSchema(struct ArrowSchema* schema, AdbcStatusCode PostgresStatement::Prepare(struct AdbcError* error) { if (query_.empty()) { - SetError(error, "%s", "[libpq] Must SetSqlQuery() before Prepare()"); + InternalAdbcSetError(error, "%s", "[libpq] Must SetSqlQuery() before Prepare()"); return ADBC_STATUS_INVALID_STATE; } @@ -810,7 +818,8 @@ AdbcStatusCode PostgresStatement::SetOption(const char* key, const char* value, } else if (std::strcmp(value, ADBC_INGEST_OPTION_MODE_CREATE_APPEND) == 0) { ingest_.mode = IngestMode::kCreateAppend; } else { - SetError(error, "[libpq] Invalid value '%s' for option '%s'", value, key); + InternalAdbcSetError(error, "[libpq] Invalid value '%s' for option '%s'", value, + key); return ADBC_STATUS_INVALID_ARGUMENT; } prepared_ = false; @@ -823,14 +832,16 @@ AdbcStatusCode PostgresStatement::SetOption(const char* key, const char* value, } else if (std::strcmp(value, ADBC_OPTION_VALUE_DISABLED) == 0) { ingest_.temporary = false; } else { - SetError(error, "[libpq] Invalid value '%s' for option '%s'", value, key); + InternalAdbcSetError(error, "[libpq] Invalid value '%s' for option '%s'", value, + key); return ADBC_STATUS_INVALID_ARGUMENT; } prepared_ = false; } else if (std::strcmp(key, ADBC_POSTGRESQL_OPTION_BATCH_SIZE_HINT_BYTES) == 0) { int64_t int_value = std::atol(value); if (int_value <= 0) { - SetError(error, "[libpq] Invalid value '%s' for option '%s'", value, key); + InternalAdbcSetError(error, "[libpq] Invalid value '%s' for option '%s'", value, + key); return ADBC_STATUS_INVALID_ARGUMENT; } @@ -841,11 +852,12 @@ AdbcStatusCode PostgresStatement::SetOption(const char* key, const char* value, } else if (std::strcmp(value, ADBC_OPTION_VALUE_DISABLED) == 0) { use_copy_ = false; } else { - SetError(error, "[libpq] Invalid value '%s' for option '%s'", value, key); + InternalAdbcSetError(error, "[libpq] Invalid value '%s' for option '%s'", value, + key); return ADBC_STATUS_INVALID_ARGUMENT; } } else { - SetError(error, "[libpq] Unknown statement option '%s'", key); + InternalAdbcSetError(error, "[libpq] Unknown statement option '%s'", key); return ADBC_STATUS_NOT_IMPLEMENTED; } return ADBC_STATUS_OK; @@ -853,13 +865,13 @@ AdbcStatusCode PostgresStatement::SetOption(const char* key, const char* value, AdbcStatusCode PostgresStatement::SetOptionBytes(const char* key, const uint8_t* value, size_t length, struct AdbcError* error) { - SetError(error, "%s%s", "[libpq] Unknown statement option ", key); + InternalAdbcSetError(error, "%s%s", "[libpq] Unknown statement option ", key); return ADBC_STATUS_NOT_IMPLEMENTED; } AdbcStatusCode PostgresStatement::SetOptionDouble(const char* key, double value, struct AdbcError* error) { - SetError(error, "%s%s", "[libpq] Unknown statement option ", key); + InternalAdbcSetError(error, "%s%s", "[libpq] Unknown statement option ", key); return ADBC_STATUS_NOT_IMPLEMENTED; } @@ -867,14 +879,15 @@ AdbcStatusCode PostgresStatement::SetOptionInt(const char* key, int64_t value, struct AdbcError* error) { if (std::strcmp(key, ADBC_POSTGRESQL_OPTION_BATCH_SIZE_HINT_BYTES) == 0) { if (value <= 0) { - SetError(error, "[libpq] Invalid value '%" PRIi64 "' for option '%s'", value, key); + InternalAdbcSetError(error, "[libpq] Invalid value '%" PRIi64 "' for option '%s'", + value, key); return ADBC_STATUS_INVALID_ARGUMENT; } this->batch_size_hint_bytes_ = this->reader_->batch_size_hint_bytes_ = value; return ADBC_STATUS_OK; } - SetError(error, "[libpq] Unknown statement option '%s'", key); + InternalAdbcSetError(error, "[libpq] Unknown statement option '%s'", key); return ADBC_STATUS_NOT_IMPLEMENTED; } diff --git a/c/driver/snowflake/AdbcDriverSnowflakeConfig.cmake.in b/c/driver/snowflake/AdbcDriverSnowflakeConfig.cmake.in index 7bb51d15b8..04d5397adc 100644 --- a/c/driver/snowflake/AdbcDriverSnowflakeConfig.cmake.in +++ b/c/driver/snowflake/AdbcDriverSnowflakeConfig.cmake.in @@ -33,7 +33,7 @@ if(ADBC_BUILD_SHARED) endif() if(ADBC_BUILD_STATIC) - adbc_add_shared_library( + adbc_add_static_library( AdbcDriverSnowflake::adbc_driver_snowflake_static adbc_driver_snowflake) endif() diff --git a/c/driver/snowflake/CMakeLists.txt b/c/driver/snowflake/CMakeLists.txt index f70d507355..2a81eb2c49 100644 --- a/c/driver/snowflake/CMakeLists.txt +++ b/c/driver/snowflake/CMakeLists.txt @@ -32,6 +32,8 @@ add_go_lib("${REPOSITORY_ROOT}/go/adbc/pkg/snowflake/" adbc-driver-snowflake SHARED_LINK_FLAGS ${LDFLAGS} + DEFINES + ${ADBC_TARGET_COMPILE_DEFINITIONS} OUTPUTS ADBC_LIBRARIES) diff --git a/c/driver/sqlite/AdbcDriverSQLiteConfig.cmake.in b/c/driver/sqlite/AdbcDriverSQLiteConfig.cmake.in index cea8cf27f4..6310ff1861 100644 --- a/c/driver/sqlite/AdbcDriverSQLiteConfig.cmake.in +++ b/c/driver/sqlite/AdbcDriverSQLiteConfig.cmake.in @@ -17,8 +17,12 @@ @PACKAGE_INIT@ +include(CMakeFindDependencyMacro) + set(ADBC_VERSION "@ADBC_VERSION@") include("${CMAKE_CURRENT_LIST_DIR}/AdbcDriverSQLiteTargets.cmake") +find_dependency(SQLite3) + check_required_components(AdbcDriverSQLite) diff --git a/c/driver/sqlite/CMakeLists.txt b/c/driver/sqlite/CMakeLists.txt index 1b097546cd..4c6bb1f1a7 100644 --- a/c/driver/sqlite/CMakeLists.txt +++ b/c/driver/sqlite/CMakeLists.txt @@ -64,6 +64,10 @@ foreach(LIB_TARGET ${ADBC_LIBRARIES}) target_include_directories(${LIB_TARGET} SYSTEM PRIVATE ${REPOSITORY_ROOT}/c/ ${REPOSITORY_ROOT}/c/include/ ${SQLite3_INCLUDE_DIRS} ${REPOSITORY_ROOT}/c/driver) + + if(NOT ADBC_DEFINE_COMMON_ENTRYPOINTS) + target_compile_definitions(${LIB_TARGET} PRIVATE ${ADBC_TARGET_COMPILE_DEFINITIONS}) + endif() endforeach() include(CheckTypeSize) diff --git a/c/driver/sqlite/sqlite.cc b/c/driver/sqlite/sqlite.cc index 2fbe80d39a..1a47a4f139 100644 --- a/c/driver/sqlite/sqlite.cc +++ b/c/driver/sqlite/sqlite.cc @@ -600,8 +600,8 @@ class SqliteConnection : public driver::Connection { nanoarrow::UniqueArrayStream stream; struct AdbcError error = ADBC_ERROR_INIT; AdbcStatusCode status = - AdbcSqliteExportReader(conn_, stmt, /*binder=*/NULL, - /*batch_size=*/64, stream.get(), &error); + InternalAdbcSqliteExportReader(conn_, stmt, /*binder=*/NULL, + /*batch_size=*/64, stream.get(), &error); if (status == ADBC_STATUS_OK) { int code = stream->get_schema(stream.get(), schema); if (code != 0) { @@ -767,7 +767,7 @@ class SqliteStatement : public driver::Statement { if (bind_parameters_.release) { struct AdbcError error = ADBC_ERROR_INIT; if (AdbcStatusCode code = - AdbcSqliteBinderSetArrayStream(&binder_, &bind_parameters_, &error); + InternalAdbcSqliteBinderSetArrayStream(&binder_, &bind_parameters_, &error); code != ADBC_STATUS_OK) { return Status::FromAdbc(code, error); } @@ -938,7 +938,8 @@ class SqliteStatement : public driver::Statement { struct AdbcError error = ADBC_ERROR_INIT; while (true) { char finished = 0; - status_code = AdbcSqliteBinderBindNext(&binder_, conn_, stmt, &finished, &error); + status_code = + InternalAdbcSqliteBinderBindNext(&binder_, conn_, stmt, &finished, &error); if (status_code != ADBC_STATUS_OK || finished) { status = Status::FromAdbc(status_code, error); break; @@ -983,9 +984,9 @@ class SqliteStatement : public driver::Statement { "parameter count mismatch: expected {} but found {}", expected, actual); } - auto status = - AdbcSqliteExportReader(conn_, stmt_, binder_.schema.release ? &binder_ : nullptr, - batch_size_, stream, &error); + auto status = InternalAdbcSqliteExportReader( + conn_, stmt_, binder_.schema.release ? &binder_ : nullptr, batch_size_, stream, + &error); if (status != ADBC_STATUS_OK) { return Status::FromAdbc(status, error); } @@ -1020,10 +1021,10 @@ class SqliteStatement : public driver::Statement { if (binder_.schema.release) { char finished = 0; struct AdbcError error = ADBC_ERROR_INIT; - if (AdbcStatusCode code = - AdbcSqliteBinderBindNext(&binder_, conn_, stmt_, &finished, &error); + if (AdbcStatusCode code = InternalAdbcSqliteBinderBindNext(&binder_, conn_, stmt_, + &finished, &error); code != ADBC_STATUS_OK) { - AdbcSqliteBinderRelease(&binder_); + InternalAdbcSqliteBinderRelease(&binder_); return Status::FromAdbc(code, error); } else if (finished != 0) { break; @@ -1040,7 +1041,7 @@ class SqliteStatement : public driver::Statement { if (!binder_.schema.release) break; } - AdbcSqliteBinderRelease(&binder_); + InternalAdbcSqliteBinderRelease(&binder_); if (sqlite3_reset(stmt_) != SQLITE_OK) { const char* msg = sqlite3_errmsg(conn_); @@ -1127,7 +1128,7 @@ class SqliteStatement : public driver::Statement { rc, sqlite3_errmsg(conn_)); } } - AdbcSqliteBinderRelease(&binder_); + InternalAdbcSqliteBinderRelease(&binder_); return Statement::ReleaseImpl(); } @@ -1159,6 +1160,8 @@ using SqliteDriver = // Public names +extern "C" { +#if !defined(ADBC_NO_COMMON_ENTRYPOINTS) AdbcStatusCode AdbcDatabaseGetOption(struct AdbcDatabase* database, const char* key, char* value, size_t* length, struct AdbcError* error) { @@ -1477,7 +1480,12 @@ AdbcStatusCode AdbcStatementExecutePartitions(struct AdbcStatement* statement, statement, schema, partitions, rows_affected, error); } -extern "C" { +[[maybe_unused]] ADBC_EXPORT AdbcStatusCode AdbcDriverInit(int version, void* raw_driver, + AdbcError* error) { + return adbc::sqlite::SqliteDriver::Init(version, raw_driver, error); +} +#endif // ADBC_NO_COMMON_ENTRYPOINTS + [[maybe_unused]] ADBC_EXPORT AdbcStatusCode AdbcDriverSqliteInit(int version, void* raw_driver, AdbcError* error) { @@ -1489,9 +1497,4 @@ extern "C" { AdbcError* error) { return adbc::sqlite::SqliteDriver::Init(version, raw_driver, error); } - -[[maybe_unused]] ADBC_EXPORT AdbcStatusCode AdbcDriverInit(int version, void* raw_driver, - AdbcError* error) { - return adbc::sqlite::SqliteDriver::Init(version, raw_driver, error); -} } diff --git a/c/driver/sqlite/sqlite_test.cc b/c/driver/sqlite/sqlite_test.cc index f6ee0c1ab2..62f15c6900 100644 --- a/c/driver/sqlite/sqlite_test.cc +++ b/c/driver/sqlite/sqlite_test.cc @@ -439,7 +439,7 @@ class SqliteReaderTest : public ::testing::Test { } void TearDown() override { if (error.release) error.release(&error); - AdbcSqliteBinderRelease(&binder); + InternalAdbcSqliteBinderRelease(&binder); sqlite3_finalize(stmt); sqlite3_close(db); } @@ -463,7 +463,7 @@ class SqliteReaderTest : public ::testing::Test { } void Bind(struct ArrowArrayStream* stream) { - ASSERT_THAT(AdbcSqliteBinderSetArrayStream(&binder, stream, &error), + ASSERT_THAT(InternalAdbcSqliteBinderSetArrayStream(&binder, stream, &error), IsOkStatus(&error)); } @@ -482,8 +482,8 @@ class SqliteReaderTest : public ::testing::Test { /*pzTail=*/nullptr)); struct AdbcSqliteBinder* binder = this->binder.schema.release ? &this->binder : nullptr; - ASSERT_THAT(AdbcSqliteExportReader(db, stmt, binder, infer_rows, - &reader->stream.value, &error), + ASSERT_THAT(InternalAdbcSqliteExportReader(db, stmt, binder, infer_rows, + &reader->stream.value, &error), IsOkStatus(&error)); ASSERT_NO_FATAL_FAILURE(reader->GetSchema()); } diff --git a/c/driver/sqlite/statement_reader.c b/c/driver/sqlite/statement_reader.c index 69f90ebd68..9eb65d48d4 100644 --- a/c/driver/sqlite/statement_reader.c +++ b/c/driver/sqlite/statement_reader.c @@ -34,27 +34,27 @@ #include "driver/common/utils.h" -AdbcStatusCode AdbcSqliteBinderSet(struct AdbcSqliteBinder* binder, - struct AdbcError* error) { +AdbcStatusCode InternalAdbcSqliteBinderSet(struct AdbcSqliteBinder* binder, + struct AdbcError* error) { int status = binder->params.get_schema(&binder->params, &binder->schema); if (status != 0) { const char* message = binder->params.get_last_error(&binder->params); if (!message) message = "(unknown error)"; - SetError(error, "Failed to get parameter schema: (%d) %s: %s", status, - strerror(status), message); + InternalAdbcSetError(error, "Failed to get parameter schema: (%d) %s: %s", status, + strerror(status), message); return ADBC_STATUS_INVALID_ARGUMENT; } struct ArrowError arrow_error = {0}; status = ArrowArrayViewInitFromSchema(&binder->batch, &binder->schema, &arrow_error); if (status != 0) { - SetError(error, "Failed to initialize array view: (%d) %s: %s", status, - strerror(status), arrow_error.message); + InternalAdbcSetError(error, "Failed to initialize array view: (%d) %s: %s", status, + strerror(status), arrow_error.message); return ADBC_STATUS_INVALID_ARGUMENT; } if (binder->batch.storage_type != NANOARROW_TYPE_STRUCT) { - SetError(error, "Bind parameters do not have root type STRUCT"); + InternalAdbcSetError(error, "Bind parameters do not have root type STRUCT"); return ADBC_STATUS_INVALID_ARGUMENT; } @@ -65,13 +65,13 @@ AdbcStatusCode AdbcSqliteBinderSet(struct AdbcSqliteBinder* binder, for (int i = 0; i < binder->schema.n_children; i++) { status = ArrowSchemaViewInit(&view, binder->schema.children[i], &arrow_error); if (status != NANOARROW_OK) { - SetError(error, "Failed to parse schema for column %d: %s (%d): %s", i, - strerror(status), status, arrow_error.message); + InternalAdbcSetError(error, "Failed to parse schema for column %d: %s (%d): %s", i, + strerror(status), status, arrow_error.message); return ADBC_STATUS_INVALID_ARGUMENT; } if (view.type == NANOARROW_TYPE_UNINITIALIZED) { - SetError(error, "Column %d has UNINITIALIZED type", i); + InternalAdbcSetError(error, "Column %d has UNINITIALIZED type", i); return ADBC_STATUS_INTERNAL; } @@ -80,8 +80,9 @@ AdbcStatusCode AdbcSqliteBinderSet(struct AdbcSqliteBinder* binder, status = ArrowSchemaViewInit(&value_view, binder->schema.children[i]->dictionary, &arrow_error); if (status != NANOARROW_OK) { - SetError(error, "Failed to parse schema for column %d->dictionary: %s (%d): %s", - i, strerror(status), status, arrow_error.message); + InternalAdbcSetError( + error, "Failed to parse schema for column %d->dictionary: %s (%d): %s", i, + strerror(status), status, arrow_error.message); return ADBC_STATUS_INVALID_ARGUMENT; } @@ -96,8 +97,8 @@ AdbcStatusCode AdbcSqliteBinderSet(struct AdbcSqliteBinder* binder, case NANOARROW_TYPE_BINARY_VIEW: break; default: - SetError(error, "Column %d dictionary has unsupported type %s", i, - ArrowTypeString(value_view.type)); + InternalAdbcSetError(error, "Column %d dictionary has unsupported type %s", i, + ArrowTypeString(value_view.type)); return ADBC_STATUS_NOT_IMPLEMENTED; } } @@ -108,13 +109,13 @@ AdbcStatusCode AdbcSqliteBinderSet(struct AdbcSqliteBinder* binder, return ADBC_STATUS_OK; } -AdbcStatusCode AdbcSqliteBinderSetArrayStream(struct AdbcSqliteBinder* binder, - struct ArrowArrayStream* values, - struct AdbcError* error) { - AdbcSqliteBinderRelease(binder); +AdbcStatusCode InternalAdbcSqliteBinderSetArrayStream(struct AdbcSqliteBinder* binder, + struct ArrowArrayStream* values, + struct AdbcError* error) { + InternalAdbcSqliteBinderRelease(binder); binder->params = *values; memset(values, 0, sizeof(*values)); - return AdbcSqliteBinderSet(binder, error); + return InternalAdbcSqliteBinderSet(binder, error); } #define SECONDS_PER_DAY 86400 @@ -129,7 +130,7 @@ static AdbcStatusCode ArrowDate32ToIsoString(int32_t value, char** buf, #if SIZEOF_TIME_T < 8 if ((value > INT32_MAX / SECONDS_PER_DAY) || (value < INT32_MIN / SECONDS_PER_DAY)) { - SetError(error, "Date %" PRId32 " exceeds platform time_t bounds", value); + InternalAdbcSetError(error, "Date %" PRId32 " exceeds platform time_t bounds", value); return ADBC_STATUS_INVALID_ARGUMENT; } @@ -142,13 +143,15 @@ static AdbcStatusCode ArrowDate32ToIsoString(int32_t value, char** buf, #if defined(_WIN32) if (gmtime_s(&broken_down_time, &time) != 0) { - SetError(error, "Could not convert date %" PRId32 " to broken down time", value); + InternalAdbcSetError(error, "Could not convert date %" PRId32 " to broken down time", + value); return ADBC_STATUS_INVALID_ARGUMENT; } #else if (gmtime_r(&time, &broken_down_time) != &broken_down_time) { - SetError(error, "Could not convert date %" PRId32 " to broken down time", value); + InternalAdbcSetError(error, "Could not convert date %" PRId32 " to broken down time", + value); return ADBC_STATUS_INVALID_ARGUMENT; } @@ -160,7 +163,8 @@ static AdbcStatusCode ArrowDate32ToIsoString(int32_t value, char** buf, } if (strftime(tsstr, strlen + 1, "%Y-%m-%d", &broken_down_time) == 0) { - SetError(error, "Call to strftime for date %" PRId32 " with failed", value); + InternalAdbcSetError(error, "Call to strftime for date %" PRId32 " with failed", + value); free(tsstr); return ADBC_STATUS_INVALID_ARGUMENT; } @@ -206,8 +210,9 @@ static AdbcStatusCode ArrowTimestampToIsoString(int64_t value, enum ArrowTimeUni #if SIZEOF_TIME_T < 8 if ((seconds > INT32_MAX) || (seconds < INT32_MIN)) { - SetError(error, "Timestamp %" PRId64 " with unit %d exceeds platform time_t bounds", - value, unit); + InternalAdbcSetError( + error, "Timestamp %" PRId64 " with unit %d exceeds platform time_t bounds", value, + unit); return ADBC_STATUS_INVALID_ARGUMENT; } @@ -220,17 +225,17 @@ static AdbcStatusCode ArrowTimestampToIsoString(int64_t value, enum ArrowTimeUni #if defined(_WIN32) if (gmtime_s(&broken_down_time, &time) != 0) { - SetError(error, - "Could not convert timestamp %" PRId64 " with unit %d to broken down time", - value, unit); + InternalAdbcSetError( + error, "Could not convert timestamp %" PRId64 " with unit %d to broken down time", + value, unit); return ADBC_STATUS_INVALID_ARGUMENT; } #else if (gmtime_r(&time, &broken_down_time) != &broken_down_time) { - SetError(error, - "Could not convert timestamp %" PRId64 " with unit %d to broken down time", - value, unit); + InternalAdbcSetError( + error, "Could not convert timestamp %" PRId64 " with unit %d to broken down time", + value, unit); return ADBC_STATUS_INVALID_ARGUMENT; } @@ -242,8 +247,9 @@ static AdbcStatusCode ArrowTimestampToIsoString(int64_t value, enum ArrowTimeUni } if (strftime(tsstr, strlen, "%Y-%m-%dT%H:%M:%S", &broken_down_time) == 0) { - SetError(error, "Call to strftime for timestamp %" PRId64 " with unit %d failed", - value, unit); + InternalAdbcSetError(error, + "Call to strftime for timestamp %" PRId64 " with unit %d failed", + value, unit); free(tsstr); return ADBC_STATUS_INVALID_ARGUMENT; } @@ -270,9 +276,9 @@ static AdbcStatusCode ArrowTimestampToIsoString(int64_t value, enum ArrowTimeUni return ADBC_STATUS_OK; } -AdbcStatusCode AdbcSqliteBinderBindNext(struct AdbcSqliteBinder* binder, sqlite3* conn, - sqlite3_stmt* stmt, char* finished, - struct AdbcError* error) { +AdbcStatusCode InternalAdbcSqliteBinderBindNext(struct AdbcSqliteBinder* binder, + sqlite3* conn, sqlite3_stmt* stmt, + char* finished, struct AdbcError* error) { struct ArrowError arrow_error = {0}; int status = 0; while (!binder->array.release || binder->next_row >= binder->array.length) { @@ -283,8 +289,8 @@ AdbcStatusCode AdbcSqliteBinderBindNext(struct AdbcSqliteBinder* binder, sqlite3 status = ArrowArrayViewInitFromSchema(&binder->batch, &binder->schema, &arrow_error); if (status != 0) { - SetError(error, "Failed to initialize array view: (%d) %s: %s", status, - strerror(status), arrow_error.message); + InternalAdbcSetError(error, "Failed to initialize array view: (%d) %s: %s", + status, strerror(status), arrow_error.message); return ADBC_STATUS_INTERNAL; } } @@ -293,21 +299,21 @@ AdbcStatusCode AdbcSqliteBinderBindNext(struct AdbcSqliteBinder* binder, sqlite3 if (status != 0) { const char* message = binder->params.get_last_error(&binder->params); if (!message) message = "(unknown error)"; - SetError(error, "Failed to get next parameter batch: (%d) %s: %s", status, - strerror(status), message); + InternalAdbcSetError(error, "Failed to get next parameter batch: (%d) %s: %s", + status, strerror(status), message); return ADBC_STATUS_IO; } if (!binder->array.release) { *finished = 1; - AdbcSqliteBinderRelease(binder); + InternalAdbcSqliteBinderRelease(binder); return ADBC_STATUS_OK; } status = ArrowArrayViewSetArray(&binder->batch, &binder->array, &arrow_error); if (status != 0) { - SetError(error, "Failed to initialize array view: (%d) %s: %s", status, - strerror(status), arrow_error.message); + InternalAdbcSetError(error, "Failed to initialize array view: (%d) %s: %s", status, + strerror(status), arrow_error.message); return ADBC_STATUS_INTERNAL; } @@ -315,11 +321,12 @@ AdbcStatusCode AdbcSqliteBinderBindNext(struct AdbcSqliteBinder* binder, sqlite3 } if (sqlite3_reset(stmt) != SQLITE_OK) { - SetError(error, "Failed to reset statement: %s", sqlite3_errmsg(conn)); + InternalAdbcSetError(error, "Failed to reset statement: %s", sqlite3_errmsg(conn)); return ADBC_STATUS_INTERNAL; } if (sqlite3_clear_bindings(stmt) != SQLITE_OK) { - SetError(error, "Failed to clear statement bindings: %s", sqlite3_errmsg(conn)); + InternalAdbcSetError(error, "Failed to clear statement bindings: %s", + sqlite3_errmsg(conn)); return ADBC_STATUS_INTERNAL; } @@ -346,10 +353,10 @@ AdbcStatusCode AdbcSqliteBinderBindNext(struct AdbcSqliteBinder* binder, sqlite3 uint64_t value = ArrowArrayViewGetUIntUnsafe(binder->batch.children[col], binder->next_row); if (value > INT64_MAX) { - SetError(error, - "Column %d has unsigned integer value %" PRIu64 - "out of range of int64_t", - col, value); + InternalAdbcSetError(error, + "Column %d has unsigned integer value %" PRIu64 + "out of range of int64_t", + col, value); return ADBC_STATUS_INVALID_ARGUMENT; } status = sqlite3_bind_int64(stmt, col + 1, (int64_t)value); @@ -401,11 +408,11 @@ AdbcStatusCode AdbcSqliteBinderBindNext(struct AdbcSqliteBinder* binder, sqlite3 char* tsstr; if ((value > INT32_MAX) || (value < INT32_MIN)) { - SetError(error, - "Column %d has value %" PRId64 - " which exceeds the expected range " - "for an Arrow DATE32 type", - col, value); + InternalAdbcSetError(error, + "Column %d has value %" PRId64 + " which exceeds the expected range " + "for an Arrow DATE32 type", + col, value); return ADBC_STATUS_INVALID_DATA; } @@ -435,14 +442,15 @@ AdbcStatusCode AdbcSqliteBinderBindNext(struct AdbcSqliteBinder* binder, sqlite3 break; } default: - SetError(error, "Column %d has unsupported type %s", col, - ArrowTypeString(binder->types[col])); + InternalAdbcSetError(error, "Column %d has unsupported type %s", col, + ArrowTypeString(binder->types[col])); return ADBC_STATUS_NOT_IMPLEMENTED; } } if (status != SQLITE_OK) { - SetError(error, "Failed to clear statement bindings: %s", sqlite3_errmsg(conn)); + InternalAdbcSetError(error, "Failed to clear statement bindings: %s", + sqlite3_errmsg(conn)); return ADBC_STATUS_INTERNAL; } } @@ -452,7 +460,7 @@ AdbcStatusCode AdbcSqliteBinderBindNext(struct AdbcSqliteBinder* binder, sqlite3 return ADBC_STATUS_OK; } -void AdbcSqliteBinderRelease(struct AdbcSqliteBinder* binder) { +void InternalAdbcSqliteBinderRelease(struct AdbcSqliteBinder* binder) { if (binder->schema.release) { binder->schema.release(&binder->schema); } @@ -469,7 +477,7 @@ void AdbcSqliteBinderRelease(struct AdbcSqliteBinder* binder) { memset(binder, 0, sizeof(*binder)); } -struct StatementReader { +struct InternalSqliteStatementReader { sqlite3* db; sqlite3_stmt* stmt; enum ArrowType* types; @@ -481,16 +489,18 @@ struct StatementReader { int batch_size; }; -const char* StatementReaderGetLastError(struct ArrowArrayStream* self) { +const char* InternalSqliteStatementReaderGetLastError(struct ArrowArrayStream* self) { if (!self->release || !self->private_data) { return NULL; } - struct StatementReader* reader = (struct StatementReader*)self->private_data; + struct InternalSqliteStatementReader* reader = + (struct InternalSqliteStatementReader*)self->private_data; return reader->error.message; } -void StatementReaderSetError(struct StatementReader* reader) { +void InternalSqliteStatementReaderInternalAdbcSetError( + struct InternalSqliteStatementReader* reader) { const char* msg = sqlite3_errmsg(reader->db); // Reset here so that we don't get an error again in StatementRelease (void)sqlite3_reset(reader->stmt); @@ -498,8 +508,8 @@ void StatementReaderSetError(struct StatementReader* reader) { reader->error.message[sizeof(reader->error.message) - 1] = '\0'; } -int StatementReaderGetOneValue(struct StatementReader* reader, int col, - struct ArrowArray* out) { +int InternalSqliteStatementReaderGetOneValue(struct InternalSqliteStatementReader* reader, + int col, struct ArrowArray* out) { int sqlite_type = sqlite3_column_type(reader->stmt, col); if (sqlite_type == SQLITE_NULL) { @@ -621,12 +631,14 @@ int StatementReaderGetOneValue(struct StatementReader* reader, int col, return ENOTSUP; } -int StatementReaderGetNext(struct ArrowArrayStream* self, struct ArrowArray* out) { +int InternalSqliteStatementReaderGetNext(struct ArrowArrayStream* self, + struct ArrowArray* out) { if (!self->release || !self->private_data) { return EINVAL; } - struct StatementReader* reader = (struct StatementReader*)self->private_data; + struct InternalSqliteStatementReader* reader = + (struct InternalSqliteStatementReader*)self->private_data; if (reader->initial_batch.release != NULL) { // Canonically return zero-row results as a stream with zero batches if (reader->initial_batch.length == 0) { @@ -660,8 +672,8 @@ int StatementReaderGetNext(struct ArrowArrayStream* self, struct ArrowArray* out } else { char finished = 0; struct AdbcError error = {0}; - status = AdbcSqliteBinderBindNext(reader->binder, reader->db, reader->stmt, - &finished, &error); + status = InternalAdbcSqliteBinderBindNext(reader->binder, reader->db, + reader->stmt, &finished, &error); if (status != ADBC_STATUS_OK) { reader->done = 1; status = EIO; @@ -681,17 +693,17 @@ int StatementReaderGetNext(struct ArrowArrayStream* self, struct ArrowArray* out } else if (rc == SQLITE_ERROR) { reader->done = 1; status = EIO; - StatementReaderSetError(reader); + InternalSqliteStatementReaderInternalAdbcSetError(reader); break; } else if (rc != SQLITE_ROW) { reader->done = 1; status = ADBC_STATUS_INTERNAL; - StatementReaderSetError(reader); + InternalSqliteStatementReaderInternalAdbcSetError(reader); break; } for (int col = 0; col < reader->schema.n_children; col++) { - status = StatementReaderGetOneValue(reader, col, out->children[col]); + status = InternalSqliteStatementReaderGetOneValue(reader, col, out->children[col]); if (status != 0) break; } @@ -714,18 +726,21 @@ int StatementReaderGetNext(struct ArrowArrayStream* self, struct ArrowArray* out return status; } -int StatementReaderGetSchema(struct ArrowArrayStream* self, struct ArrowSchema* out) { +int InternalSqliteStatementReaderGetSchema(struct ArrowArrayStream* self, + struct ArrowSchema* out) { if (!self->release || !self->private_data) { return EINVAL; } - struct StatementReader* reader = (struct StatementReader*)self->private_data; + struct InternalSqliteStatementReader* reader = + (struct InternalSqliteStatementReader*)self->private_data; return ArrowSchemaDeepCopy(&reader->schema, out); } -void StatementReaderRelease(struct ArrowArrayStream* self) { +void InternalSqliteStatementReaderRelease(struct ArrowArrayStream* self) { if (self->private_data) { - struct StatementReader* reader = (struct StatementReader*)self->private_data; + struct InternalSqliteStatementReader* reader = + (struct InternalSqliteStatementReader*)self->private_data; if (reader->schema.release) { reader->schema.release(&reader->schema); } @@ -736,7 +751,7 @@ void StatementReaderRelease(struct ArrowArrayStream* self) { free(reader->types); } if (reader->binder) { - AdbcSqliteBinderRelease(reader->binder); + InternalAdbcSqliteBinderRelease(reader->binder); } free(self->private_data); @@ -772,12 +787,10 @@ void StatementReaderRelease(struct ArrowArrayStream* self) { /// Initialize buffers for the first (type-inferred) batch of data. /// Use raw buffers since the types may change. -AdbcStatusCode StatementReaderInitializeInfer(int num_columns, size_t infer_rows, - struct ArrowBitmap* validity, - struct ArrowBuffer* data, - struct ArrowBuffer* binary, - enum ArrowType* current_type, - struct AdbcError* error) { +AdbcStatusCode InternalSqliteStatementReaderInitializeInfer( + int num_columns, size_t infer_rows, struct ArrowBitmap* validity, + struct ArrowBuffer* data, struct ArrowBuffer* binary, enum ArrowType* current_type, + struct AdbcError* error) { for (int i = 0; i < num_columns; i++) { ArrowBitmapInit(&validity[i]); CHECK_NA(INTERNAL, ArrowBitmapReserve(&validity[i], infer_rows), error); @@ -790,10 +803,11 @@ AdbcStatusCode StatementReaderInitializeInfer(int num_columns, size_t infer_rows } // NOLINT(whitespace/indent) /// Finalize the first (type-inferred) batch of data. -AdbcStatusCode StatementReaderInferFinalize( - sqlite3_stmt* stmt, int num_columns, int64_t num_rows, struct StatementReader* reader, - struct ArrowBitmap* validity, struct ArrowBuffer* data, struct ArrowBuffer* binary, - enum ArrowType* current_type, struct AdbcError* error) { +AdbcStatusCode InternalSqliteStatementReaderInferFinalize( + sqlite3_stmt* stmt, int num_columns, int64_t num_rows, + struct InternalSqliteStatementReader* reader, struct ArrowBitmap* validity, + struct ArrowBuffer* data, struct ArrowBuffer* binary, enum ArrowType* current_type, + struct AdbcError* error) { ArrowSchemaInit(&reader->schema); CHECK_NA(INTERNAL, ArrowSchemaSetTypeStruct(&reader->schema, num_columns), error); for (int col = 0; col < num_columns; col++) { @@ -811,7 +825,8 @@ AdbcStatusCode StatementReaderInferFinalize( if (current_type[col] == NANOARROW_TYPE_STRING || current_type[col] == NANOARROW_TYPE_BINARY) { if (binary[col].data == NULL) { - SetError(error, "INTERNAL: column has binary-like type but no backing buffer"); + InternalAdbcSetError( + error, "INTERNAL: column has binary-like type but no backing buffer"); return ADBC_STATUS_INTERNAL; } } @@ -835,8 +850,8 @@ AdbcStatusCode StatementReaderInferFinalize( } // Convert an int64 typed column to double. -AdbcStatusCode StatementReaderUpcastInt64ToDouble(struct ArrowBuffer* data, - struct AdbcError* error) { +AdbcStatusCode InternalSqliteStatementReaderUpcastInt64ToDouble(struct ArrowBuffer* data, + struct AdbcError* error) { struct ArrowBuffer doubles; ArrowBufferInit(&doubles); CHECK_NA(INTERNAL, ArrowBufferReserve(&doubles, data->capacity_bytes), error); @@ -852,10 +867,9 @@ AdbcStatusCode StatementReaderUpcastInt64ToDouble(struct ArrowBuffer* data, return ADBC_STATUS_OK; } -AdbcStatusCode StatementReaderAppendInt64ToBinary(struct ArrowBuffer* offsets, - struct ArrowBuffer* binary, - int64_t value, int32_t* offset, - struct AdbcError* error) { +AdbcStatusCode InternalSqliteStatementReaderAppendInt64ToBinary( + struct ArrowBuffer* offsets, struct ArrowBuffer* binary, int64_t value, + int32_t* offset, struct AdbcError* error) { // Make sure we have at least 21 bytes available (19 digits + sign + null) // Presumably this is enough, but manpage for snprintf makes no guarantees // about whether locale may affect this, so check for truncation regardless @@ -867,13 +881,13 @@ AdbcStatusCode StatementReaderAppendInt64ToBinary(struct ArrowBuffer* offsets, while (1) { written = snprintf(output, buffer_size, "%" PRId64, value); if (written < 0) { - SetError(error, "Encoding error when upcasting double to string"); + InternalAdbcSetError(error, "Encoding error when upcasting double to string"); return ADBC_STATUS_INTERNAL; } else if (((size_t)written) >= buffer_size) { // Truncated, resize and try again // Check for overflow - presumably this can never happen...? if (UINT_MAX - buffer_size < buffer_size) { - SetError(error, "Overflow when upcasting double to string"); + InternalAdbcSetError(error, "Overflow when upcasting double to string"); return ADBC_STATUS_INTERNAL; } CHECK_NA(INTERNAL, ArrowBufferReserve(binary, buffer_size), error); @@ -888,10 +902,9 @@ AdbcStatusCode StatementReaderAppendInt64ToBinary(struct ArrowBuffer* offsets, return ADBC_STATUS_OK; } -AdbcStatusCode StatementReaderAppendDoubleToBinary(struct ArrowBuffer* offsets, - struct ArrowBuffer* binary, - double value, int32_t* offset, - struct AdbcError* error) { +AdbcStatusCode InternalSqliteStatementReaderAppendDoubleToBinary( + struct ArrowBuffer* offsets, struct ArrowBuffer* binary, double value, + int32_t* offset, struct AdbcError* error) { static const size_t kReserve = 64; size_t buffer_size = kReserve; CHECK_NA(INTERNAL, ArrowBufferReserve(binary, buffer_size), error); @@ -900,13 +913,13 @@ AdbcStatusCode StatementReaderAppendDoubleToBinary(struct ArrowBuffer* offsets, while (1) { written = snprintf(output, buffer_size, "%e", value); if (written < 0) { - SetError(error, "Encoding error when upcasting double to string"); + InternalAdbcSetError(error, "Encoding error when upcasting double to string"); return ADBC_STATUS_INTERNAL; } else if (((size_t)written) >= buffer_size) { // Truncated, resize and try again // Check for overflow - presumably this can never happen...? if (UINT_MAX - buffer_size < buffer_size) { - SetError(error, "Overflow when upcasting double to string"); + InternalAdbcSetError(error, "Overflow when upcasting double to string"); return ADBC_STATUS_INTERNAL; } CHECK_NA(INTERNAL, ArrowBufferReserve(binary, buffer_size), error); @@ -921,9 +934,8 @@ AdbcStatusCode StatementReaderAppendDoubleToBinary(struct ArrowBuffer* offsets, return ADBC_STATUS_OK; } -AdbcStatusCode StatementReaderUpcastInt64ToBinary(struct ArrowBuffer* data, - struct ArrowBuffer* binary, - struct AdbcError* error) { +AdbcStatusCode InternalSqliteStatementReaderUpcastInt64ToBinary( + struct ArrowBuffer* data, struct ArrowBuffer* binary, struct AdbcError* error) { struct ArrowBuffer offsets; ArrowBufferInit(&offsets); ArrowBufferInit(binary); @@ -936,8 +948,8 @@ AdbcStatusCode StatementReaderUpcastInt64ToBinary(struct ArrowBuffer* data, int32_t offset = 0; ArrowBufferAppendUnsafe(&offsets, &offset, sizeof(int32_t)); for (size_t i = 0; i < num_elements; i++) { - AdbcStatusCode status = - StatementReaderAppendInt64ToBinary(&offsets, binary, elements[i], &offset, error); + AdbcStatusCode status = InternalSqliteStatementReaderAppendInt64ToBinary( + &offsets, binary, elements[i], &offset, error); if (status != ADBC_STATUS_OK) return status; } ArrowBufferReset(data); @@ -945,9 +957,8 @@ AdbcStatusCode StatementReaderUpcastInt64ToBinary(struct ArrowBuffer* data, return ADBC_STATUS_OK; } -AdbcStatusCode StatementReaderUpcastDoubleToBinary(struct ArrowBuffer* data, - struct ArrowBuffer* binary, - struct AdbcError* error) { +AdbcStatusCode InternalSqliteStatementReaderUpcastDoubleToBinary( + struct ArrowBuffer* data, struct ArrowBuffer* binary, struct AdbcError* error) { struct ArrowBuffer offsets; ArrowBufferInit(&offsets); ArrowBufferInit(binary); @@ -960,7 +971,7 @@ AdbcStatusCode StatementReaderUpcastDoubleToBinary(struct ArrowBuffer* data, int32_t offset = 0; ArrowBufferAppendUnsafe(&offsets, &offset, sizeof(int32_t)); for (size_t i = 0; i < num_elements; i++) { - AdbcStatusCode status = StatementReaderAppendDoubleToBinary( + AdbcStatusCode status = InternalSqliteStatementReaderAppendDoubleToBinary( &offsets, binary, elements[i], &offset, error); if (status != ADBC_STATUS_OK) return status; } @@ -970,7 +981,7 @@ AdbcStatusCode StatementReaderUpcastDoubleToBinary(struct ArrowBuffer* data, } /// Append a single value to a single column. -AdbcStatusCode StatementReaderInferOneValue( +AdbcStatusCode InternalSqliteStatementReaderInferOneValue( sqlite3_stmt* stmt, int col, struct ArrowBitmap* validity, struct ArrowBuffer* data, struct ArrowBuffer* binary, enum ArrowType* current_type, struct AdbcError* error) { // TODO: static_assert sizeof(int64) == sizeof(double) @@ -1018,7 +1029,7 @@ AdbcStatusCode StatementReaderInferOneValue( case NANOARROW_TYPE_STRING: case NANOARROW_TYPE_BINARY: { int32_t offset = ((int32_t*)data->data)[data->size_bytes / 4 - 1]; - return StatementReaderAppendInt64ToBinary( + return InternalSqliteStatementReaderAppendInt64ToBinary( data, binary, sqlite3_column_int64(stmt, col), &offset, error); } default: @@ -1031,7 +1042,8 @@ AdbcStatusCode StatementReaderInferOneValue( switch (*current_type) { case NANOARROW_TYPE_INT64: { - AdbcStatusCode status = StatementReaderUpcastInt64ToDouble(data, error); + AdbcStatusCode status = + InternalSqliteStatementReaderUpcastInt64ToDouble(data, error); if (status != ADBC_STATUS_OK) return status; *current_type = NANOARROW_TYPE_DOUBLE; double value = sqlite3_column_double(stmt, col); @@ -1046,7 +1058,7 @@ AdbcStatusCode StatementReaderInferOneValue( case NANOARROW_TYPE_STRING: case NANOARROW_TYPE_BINARY: { int32_t offset = ((int32_t*)data->data)[data->size_bytes / 4 - 1]; - return StatementReaderAppendDoubleToBinary( + return InternalSqliteStatementReaderAppendDoubleToBinary( data, binary, sqlite3_column_double(stmt, col), &offset, error); } default: @@ -1059,14 +1071,15 @@ AdbcStatusCode StatementReaderInferOneValue( switch (*current_type) { case NANOARROW_TYPE_INT64: { - AdbcStatusCode status = StatementReaderUpcastInt64ToBinary(data, binary, error); + AdbcStatusCode status = + InternalSqliteStatementReaderUpcastInt64ToBinary(data, binary, error); if (status != ADBC_STATUS_OK) return status; *current_type = NANOARROW_TYPE_STRING; break; } case NANOARROW_TYPE_DOUBLE: { AdbcStatusCode status = - StatementReaderUpcastDoubleToBinary(data, binary, error); + InternalSqliteStatementReaderUpcastDoubleToBinary(data, binary, error); if (status != ADBC_STATUS_OK) return status; *current_type = NANOARROW_TYPE_STRING; break; @@ -1090,14 +1103,15 @@ AdbcStatusCode StatementReaderInferOneValue( switch (*current_type) { case NANOARROW_TYPE_INT64: { - AdbcStatusCode status = StatementReaderUpcastInt64ToBinary(data, binary, error); + AdbcStatusCode status = + InternalSqliteStatementReaderUpcastInt64ToBinary(data, binary, error); if (status != ADBC_STATUS_OK) return status; *current_type = NANOARROW_TYPE_BINARY; break; } case NANOARROW_TYPE_DOUBLE: { AdbcStatusCode status = - StatementReaderUpcastDoubleToBinary(data, binary, error); + InternalSqliteStatementReaderUpcastDoubleToBinary(data, binary, error); if (status != ADBC_STATUS_OK) return status; *current_type = NANOARROW_TYPE_BINARY; break; @@ -1125,21 +1139,23 @@ AdbcStatusCode StatementReaderInferOneValue( return ADBC_STATUS_OK; } // NOLINT(whitespace/indent) -AdbcStatusCode AdbcSqliteExportReader(sqlite3* db, sqlite3_stmt* stmt, - struct AdbcSqliteBinder* binder, size_t batch_size, - struct ArrowArrayStream* stream, - struct AdbcError* error) { - struct StatementReader* reader = malloc(sizeof(struct StatementReader)); - memset(reader, 0, sizeof(struct StatementReader)); +AdbcStatusCode InternalAdbcSqliteExportReader(sqlite3* db, sqlite3_stmt* stmt, + struct AdbcSqliteBinder* binder, + size_t batch_size, + struct ArrowArrayStream* stream, + struct AdbcError* error) { + struct InternalSqliteStatementReader* reader = + malloc(sizeof(struct InternalSqliteStatementReader)); + memset(reader, 0, sizeof(struct InternalSqliteStatementReader)); reader->db = db; reader->stmt = stmt; reader->batch_size = (int)batch_size; stream->private_data = reader; - stream->release = StatementReaderRelease; - stream->get_last_error = StatementReaderGetLastError; - stream->get_next = StatementReaderGetNext; - stream->get_schema = StatementReaderGetSchema; + stream->release = InternalSqliteStatementReaderRelease; + stream->get_last_error = InternalSqliteStatementReaderGetLastError; + stream->get_next = InternalSqliteStatementReaderGetNext; + stream->get_schema = InternalSqliteStatementReaderGetSchema; sqlite3_mutex_enter(sqlite3_db_mutex(db)); @@ -1149,12 +1165,12 @@ AdbcStatusCode AdbcSqliteExportReader(sqlite3* db, sqlite3_stmt* stmt, struct ArrowBuffer* binary = malloc(num_columns * sizeof(struct ArrowBuffer)); enum ArrowType* current_type = malloc(num_columns * sizeof(enum ArrowType)); - AdbcStatusCode status = StatementReaderInitializeInfer( + AdbcStatusCode status = InternalSqliteStatementReaderInitializeInfer( num_columns, batch_size, validity, data, binary, current_type, error); if (binder) { char finished = 0; - status = AdbcSqliteBinderBindNext(binder, db, stmt, &finished, error); + status = InternalAdbcSqliteBinderBindNext(binder, db, stmt, &finished, error); if (finished) { reader->done = 1; } @@ -1170,7 +1186,7 @@ AdbcStatusCode AdbcSqliteExportReader(sqlite3* db, sqlite3_stmt* stmt, break; } else { char finished = 0; - status = AdbcSqliteBinderBindNext(binder, db, stmt, &finished, error); + status = InternalAdbcSqliteBinderBindNext(binder, db, stmt, &finished, error); if (status != ADBC_STATUS_OK) break; if (finished) { reader->done = 1; @@ -1179,7 +1195,7 @@ AdbcStatusCode AdbcSqliteExportReader(sqlite3* db, sqlite3_stmt* stmt, } continue; } else if (rc == SQLITE_ERROR) { - SetError(error, "Failed to step query: %s", sqlite3_errmsg(db)); + InternalAdbcSetError(error, "Failed to step query: %s", sqlite3_errmsg(db)); status = ADBC_STATUS_IO; // Reset here so that we don't get an error again in StatementRelease (void)sqlite3_reset(stmt); @@ -1190,8 +1206,9 @@ AdbcStatusCode AdbcSqliteExportReader(sqlite3* db, sqlite3_stmt* stmt, } for (int col = 0; col < num_columns; col++) { - status = StatementReaderInferOneValue(stmt, col, &validity[col], &data[col], - &binary[col], ¤t_type[col], error); + status = InternalSqliteStatementReaderInferOneValue(stmt, col, &validity[col], + &data[col], &binary[col], + ¤t_type[col], error); if (status != ADBC_STATUS_OK) break; } if (status != ADBC_STATUS_OK) break; @@ -1199,8 +1216,9 @@ AdbcStatusCode AdbcSqliteExportReader(sqlite3* db, sqlite3_stmt* stmt, } if (status == ADBC_STATUS_OK) { - status = StatementReaderInferFinalize(stmt, num_columns, num_rows, reader, validity, - data, binary, current_type, error); + status = InternalSqliteStatementReaderInferFinalize(stmt, num_columns, num_rows, + reader, validity, data, binary, + current_type, error); } } diff --git a/c/driver/sqlite/statement_reader.h b/c/driver/sqlite/statement_reader.h index 2e6b19086c..7563cd5523 100644 --- a/c/driver/sqlite/statement_reader.h +++ b/c/driver/sqlite/statement_reader.h @@ -41,15 +41,15 @@ struct ADBC_EXPORT AdbcSqliteBinder { }; ADBC_EXPORT -AdbcStatusCode AdbcSqliteBinderSetArrayStream(struct AdbcSqliteBinder* binder, - struct ArrowArrayStream* values, - struct AdbcError* error); +AdbcStatusCode InternalAdbcSqliteBinderSetArrayStream(struct AdbcSqliteBinder* binder, + struct ArrowArrayStream* values, + struct AdbcError* error); ADBC_EXPORT -AdbcStatusCode AdbcSqliteBinderBindNext(struct AdbcSqliteBinder* binder, sqlite3* conn, - sqlite3_stmt* stmt, char* finished, - struct AdbcError* error); +AdbcStatusCode InternalAdbcSqliteBinderBindNext(struct AdbcSqliteBinder* binder, + sqlite3* conn, sqlite3_stmt* stmt, + char* finished, struct AdbcError* error); ADBC_EXPORT -void AdbcSqliteBinderRelease(struct AdbcSqliteBinder* binder); +void InternalAdbcSqliteBinderRelease(struct AdbcSqliteBinder* binder); /// \brief Initialize an ArrowArrayStream from a sqlite3_stmt. /// \param[in] db The SQLite connection. @@ -59,10 +59,11 @@ void AdbcSqliteBinderRelease(struct AdbcSqliteBinder* binder); /// \param[out] stream The stream to export to. /// \param[out] error Error details, if needed. ADBC_EXPORT -AdbcStatusCode AdbcSqliteExportReader(sqlite3* db, sqlite3_stmt* stmt, - struct AdbcSqliteBinder* binder, size_t batch_size, - struct ArrowArrayStream* stream, - struct AdbcError* error); +AdbcStatusCode InternalAdbcSqliteExportReader(sqlite3* db, sqlite3_stmt* stmt, + struct AdbcSqliteBinder* binder, + size_t batch_size, + struct ArrowArrayStream* stream, + struct AdbcError* error); #ifdef __cplusplus } diff --git a/c/include/arrow-adbc/adbc_driver_manager.h b/c/include/arrow-adbc/adbc_driver_manager.h index c32368ab69..e5e9bf67c4 100644 --- a/c/include/arrow-adbc/adbc_driver_manager.h +++ b/c/include/arrow-adbc/adbc_driver_manager.h @@ -40,8 +40,9 @@ extern "C" { /// /// \param[in] driver_name An identifier for the driver (e.g. a path to a /// shared library on Linux). -/// \param[in] entrypoint An identifier for the entrypoint (e.g. the -/// symbol to call for AdbcDriverInitFunc on Linux). +/// \param[in] entrypoint An identifier for the entrypoint (e.g. the symbol to +/// call for AdbcDriverInitFunc on Linux). If not provided, search for an +/// entrypoint based on the driver name. /// \param[in] version The ADBC revision to attempt to initialize. /// \param[out] driver The table of function pointers to initialize. /// \param[out] error An optional location to return an error message diff --git a/c/include/arrow-adbc/driver/bigquery.h b/c/include/arrow-adbc/driver/bigquery.h new file mode 100644 index 0000000000..985a021400 --- /dev/null +++ b/c/include/arrow-adbc/driver/bigquery.h @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +/// \file arrow-adbc/driver/bigquery.h ADBC BigQuery Driver +/// +/// A driver for BigQuery. + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +ADBC_EXPORT +AdbcStatusCode AdbcDriverBigqueryInit(int version, void* raw_driver, + struct AdbcError* error); + +#ifdef __cplusplus +} +#endif diff --git a/c/include/arrow-adbc/driver/flightsql.h b/c/include/arrow-adbc/driver/flightsql.h new file mode 100644 index 0000000000..1d2ad8e2d1 --- /dev/null +++ b/c/include/arrow-adbc/driver/flightsql.h @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +/// \file arrow-adbc/driver/flightsql.h ADBC Flight SQL Driver +/// +/// A driver for Arrow Flight SQL. + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +ADBC_EXPORT +AdbcStatusCode AdbcDriverFlightsqlInit(int version, void* raw_driver, + struct AdbcError* error); + +#ifdef __cplusplus +} +#endif diff --git a/c/include/arrow-adbc/driver/postgresql.h b/c/include/arrow-adbc/driver/postgresql.h new file mode 100644 index 0000000000..49ea63e16f --- /dev/null +++ b/c/include/arrow-adbc/driver/postgresql.h @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +/// \file arrow-adbc/driver/postgresql.h ADBC PostgreSQL Driver +/// +/// A driver for PostgreSQL. + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +ADBC_EXPORT +AdbcStatusCode AdbcDriverPostgresqlInit(int version, void* raw_driver, + struct AdbcError* error); + +#ifdef __cplusplus +} +#endif diff --git a/c/include/arrow-adbc/driver/snowflake.h b/c/include/arrow-adbc/driver/snowflake.h new file mode 100644 index 0000000000..3dc734bd41 --- /dev/null +++ b/c/include/arrow-adbc/driver/snowflake.h @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +/// \file arrow-adbc/driver/snowflake.h ADBC Snowflake Driver +/// +/// A driver for Snowflake. + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +ADBC_EXPORT +AdbcStatusCode AdbcDriverSnowflakeInit(int version, void* raw_driver, + struct AdbcError* error); + +#ifdef __cplusplus +} +#endif diff --git a/c/include/arrow-adbc/driver/sqlite.h b/c/include/arrow-adbc/driver/sqlite.h new file mode 100644 index 0000000000..e11c8418b9 --- /dev/null +++ b/c/include/arrow-adbc/driver/sqlite.h @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +/// \file arrow-adbc/driver/sqlite.h ADBC SQLite Driver +/// +/// A driver for SQLite. + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +ADBC_EXPORT +AdbcStatusCode AdbcDriverSqliteInit(int version, void* raw_driver, + struct AdbcError* error); + +#ifdef __cplusplus +} +#endif diff --git a/c/integration/shared_test/CMakeLists.txt b/c/integration/shared_test/CMakeLists.txt new file mode 100644 index 0000000000..dabe629c71 --- /dev/null +++ b/c/integration/shared_test/CMakeLists.txt @@ -0,0 +1,27 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +cmake_minimum_required(VERSION 3.18) + +project(adbc-static-test LANGUAGES C) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + +find_package(AdbcDriverManager REQUIRED) + +add_executable(shared_test main.c) +target_link_libraries(shared_test PRIVATE AdbcDriverManager::adbc_driver_manager_shared) diff --git a/c/integration/shared_test/main.c b/c/integration/shared_test/main.c new file mode 100644 index 0000000000..351d2a5d06 --- /dev/null +++ b/c/integration/shared_test/main.c @@ -0,0 +1,95 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include +#include +#include + +#include +#include + +int TryDriver(const char* driver_name) { + struct AdbcError error; + struct AdbcDriver driver; + + memset(&error, 0, sizeof(error)); + memset(&driver, 0, sizeof(driver)); + + AdbcStatusCode status = + AdbcLoadDriver(driver_name, NULL, ADBC_VERSION_1_1_0, &driver, &error); + if (status != ADBC_STATUS_OK) { + if (error.release) { + fprintf(stderr, "AdbcLoadDriver failed: %s\n", error.message); + error.release(&error); + } else { + fprintf(stderr, "AdbcLoadDriver failed\n"); + } + return EXIT_FAILURE; + } + + if (driver.release) { + status = driver.release(&driver, &error); + + if (status != ADBC_STATUS_OK) { + if (error.release) { + fprintf(stderr, "AdbcDriver.release failed: %s\n", error.message); + error.release(&error); + } else { + fprintf(stderr, "AdbcDriver.release failed\n"); + } + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} + +int main(int argc, char** argv) { + int rc = 0; + + rc = TryDriver("adbc_driver_bigquery"); + if (rc != EXIT_SUCCESS) { + return rc; + } + printf("Loaded BigQuery driver\n"); + + rc = TryDriver("adbc_driver_flightsql"); + if (rc != EXIT_SUCCESS) { + return rc; + } + printf("Loaded FlightSQL driver\n"); + + rc = TryDriver("adbc_driver_postgresql"); + if (rc != EXIT_SUCCESS) { + return rc; + } + printf("Loaded PostgreSQL driver\n"); + + rc = TryDriver("adbc_driver_snowflake"); + if (rc != EXIT_SUCCESS) { + return rc; + } + printf("Loaded Snowflake driver\n"); + + rc = TryDriver("adbc_driver_sqlite"); + if (rc != EXIT_SUCCESS) { + return rc; + } + printf("Loaded SQLite driver\n"); + + return EXIT_SUCCESS; +} diff --git a/c/integration/static_test/CMakeLists.txt b/c/integration/static_test/CMakeLists.txt new file mode 100644 index 0000000000..e0ada2fe70 --- /dev/null +++ b/c/integration/static_test/CMakeLists.txt @@ -0,0 +1,49 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +cmake_minimum_required(VERSION 3.18) + +project(adbc-static-test LANGUAGES C CXX) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + +find_package(AdbcDriverCommon REQUIRED) +find_package(AdbcDriverFramework REQUIRED) + +find_package(AdbcDriverBigQuery REQUIRED) +find_package(AdbcDriverFlightSQL REQUIRED) +find_package(AdbcDriverPostgreSQL REQUIRED) +find_package(AdbcDriverSQLite REQUIRED) +find_package(AdbcDriverSnowflake REQUIRED) + +find_package(fmt REQUIRED) +find_package(nanoarrow REQUIRED) + +add_executable(static_test main.c) +# We need to link the C++ standard library since some of the drivers are +# written in C++. +set_target_properties(static_test PROPERTIES LINKER_LANGUAGE CXX) +target_link_libraries(static_test + PRIVATE AdbcDriverFlightSQL::adbc_driver_flightsql_static + AdbcDriverPostgreSQL::adbc_driver_postgresql_static + AdbcDriverSQLite::adbc_driver_sqlite_static + PostgreSQL::PostgreSQL + SQLite::SQLite3 + fmt::fmt + nanoarrow::nanoarrow + AdbcDriverCommon::adbc_driver_common + AdbcDriverFramework::adbc_driver_framework) diff --git a/c/integration/static_test/README.md b/c/integration/static_test/README.md new file mode 100644 index 0000000000..1da0f562d2 --- /dev/null +++ b/c/integration/static_test/README.md @@ -0,0 +1,23 @@ + + +# Static Linking Test + +This is only used to test that static linking with multiple drivers behaves as +expected. See the docker-compose job `cpp-static-test`. diff --git a/c/integration/static_test/main.c b/c/integration/static_test/main.c new file mode 100644 index 0000000000..101e00f508 --- /dev/null +++ b/c/integration/static_test/main.c @@ -0,0 +1,77 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +int main(int argc, char** argv) { + struct AdbcError error; + + struct AdbcDriver flightsql; + struct AdbcDriver postgresql; + struct AdbcDriver sqlite; + + memset(&error, 0, sizeof(error)); + memset(&flightsql, 0, sizeof(flightsql)); + memset(&postgresql, 0, sizeof(postgresql)); + memset(&sqlite, 0, sizeof(sqlite)); + + AdbcStatusCode status; + + status = AdbcDriverFlightsqlInit(ADBC_VERSION_1_1_0, &flightsql, &error); + if (status != ADBC_STATUS_OK) { + if (error.release) { + fprintf(stderr, "AdbcDriverFlightsqlInit failed: %s\n", error.message); + error.release(&error); + } else { + fprintf(stderr, "AdbcDriverFlightsqlInit failed\n"); + } + return EXIT_FAILURE; + } + + status = AdbcDriverPostgresqlInit(ADBC_VERSION_1_1_0, &postgresql, &error); + if (status != ADBC_STATUS_OK) { + if (error.release) { + fprintf(stderr, "AdbcDriverPostgresqlInit failed: %s\n", error.message); + error.release(&error); + } else { + fprintf(stderr, "AdbcDriverPostgresqlInit failed\n"); + } + return EXIT_FAILURE; + } + + status = AdbcDriverSqliteInit(ADBC_VERSION_1_1_0, &sqlite, &error); + if (status != ADBC_STATUS_OK) { + if (error.release) { + fprintf(stderr, "AdbcDriverSqliteInit failed: %s\n", error.message); + error.release(&error); + } else { + fprintf(stderr, "AdbcDriverSqliteInit failed\n"); + } + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/c/symbols.map b/c/symbols.map index c9464b2da4..9adf7bcb99 100644 --- a/c/symbols.map +++ b/c/symbols.map @@ -19,12 +19,8 @@ global: # Only expose symbols from the ADBC API Adbc*; - - # Expose driver-specific initialization routines - FlightSQLDriverInit; - PostgresqlDriverInit; - SnowflakeDriverInit; - SqliteDriverInit; + # Needed for tests, but namespaced so they are clearly not for public use + InternalAdbc*; extern "C++" { Adbc*; diff --git a/c/validation/adbc_validation_connection.cc b/c/validation/adbc_validation_connection.cc index 0f3c135545..9c9bdeff21 100644 --- a/c/validation/adbc_validation_connection.cc +++ b/c/validation/adbc_validation_connection.cc @@ -981,13 +981,13 @@ void ConnectionTest::TestMetadataGetObjectsPrimaryKey() { << "could not initialize the AdbcGetObjectsData object"; // Test primary key - struct AdbcGetObjectsTable* table = - AdbcGetObjectsDataGetTableByName(*get_objects_data, quirks()->catalog().c_str(), - quirks()->db_schema().c_str(), "adbc_pkey_test"); + struct AdbcGetObjectsTable* table = InternalAdbcGetObjectsDataGetTableByName( + *get_objects_data, quirks()->catalog().c_str(), quirks()->db_schema().c_str(), + "adbc_pkey_test"); ASSERT_NE(table, nullptr) << "could not find adbc_pkey_test table"; ASSERT_EQ(table->n_table_columns, 1); - struct AdbcGetObjectsColumn* column = AdbcGetObjectsDataGetColumnByName( + struct AdbcGetObjectsColumn* column = InternalAdbcGetObjectsDataGetColumnByName( *get_objects_data, quirks()->catalog().c_str(), quirks()->db_schema().c_str(), "adbc_pkey_test", "id"); ASSERT_NE(column, nullptr) << "could not find id column on adbc_pkey_test table"; @@ -1000,7 +1000,7 @@ void ConnectionTest::TestMetadataGetObjectsPrimaryKey() { ConstraintTest(constraint, "PRIMARY KEY", {"id"}); // Test composite primary key - struct AdbcGetObjectsTable* composite_table = AdbcGetObjectsDataGetTableByName( + struct AdbcGetObjectsTable* composite_table = InternalAdbcGetObjectsDataGetTableByName( *get_objects_data, quirks()->catalog().c_str(), quirks()->db_schema().c_str(), "adbc_composite_pkey_test"); ASSERT_NE(composite_table, nullptr) << "could not find adbc_composite_pkey_test table"; @@ -1013,7 +1013,7 @@ void ConnectionTest::TestMetadataGetObjectsPrimaryKey() { const char* parent_2_column_names[2] = {"id_primary_col1", "id_primary_col2"}; struct AdbcGetObjectsColumn* parent_2_column; for (int column_name_index = 0; column_name_index < 2; column_name_index++) { - parent_2_column = AdbcGetObjectsDataGetColumnByName( + parent_2_column = InternalAdbcGetObjectsDataGetColumnByName( *get_objects_data, quirks()->catalog().c_str(), quirks()->db_schema().c_str(), "adbc_composite_pkey_test", parent_2_column_names[column_name_index]); ASSERT_NE(parent_2_column, nullptr) @@ -1104,7 +1104,7 @@ void ConnectionTest::TestMetadataGetObjectsForeignKey() { << "could not initialize the AdbcGetObjectsData object"; // Test child table - struct AdbcGetObjectsTable* child_table = AdbcGetObjectsDataGetTableByName( + struct AdbcGetObjectsTable* child_table = InternalAdbcGetObjectsDataGetTableByName( *get_objects_data, quirks()->catalog().c_str(), quirks()->db_schema().c_str(), "adbc_fkey_child_test"); ASSERT_NE(child_table, nullptr) << "could not find adbc_fkey_child_test table"; @@ -1115,7 +1115,7 @@ void ConnectionTest::TestMetadataGetObjectsForeignKey() { const char* child_column_names[3] = {"id_child_col1", "id_child_col2", "id_child_col3"}; struct AdbcGetObjectsColumn* child_column; for (int column_index = 0; column_index < 2; column_index++) { - child_column = AdbcGetObjectsDataGetColumnByName( + child_column = InternalAdbcGetObjectsDataGetColumnByName( *get_objects_data, quirks()->catalog().c_str(), quirks()->db_schema().c_str(), "adbc_fkey_child_test", child_column_names[column_index]); ASSERT_NE(child_column, nullptr) diff --git a/c/validation/adbc_validation_util.h b/c/validation/adbc_validation_util.h index b4f5d6f81a..d3eab643d1 100644 --- a/c/validation/adbc_validation_util.h +++ b/c/validation/adbc_validation_util.h @@ -242,9 +242,9 @@ struct StreamReader { struct GetObjectsReader { explicit GetObjectsReader(struct ArrowArrayView* array_view) { // TODO: this swallows any construction errors - get_objects_data_ = AdbcGetObjectsDataInit(array_view); + get_objects_data_ = InternalAdbcGetObjectsDataInit(array_view); } - ~GetObjectsReader() { AdbcGetObjectsDataDelete(get_objects_data_); } + ~GetObjectsReader() { InternalAdbcGetObjectsDataDelete(get_objects_data_); } struct AdbcGetObjectsData* operator*() { return get_objects_data_; } struct AdbcGetObjectsData* operator->() { return get_objects_data_; } diff --git a/ci/docker/python-debug.dockerfile b/ci/docker/python-debug.dockerfile index c17ca103dd..d687e5368f 100644 --- a/ci/docker/python-debug.dockerfile +++ b/ci/docker/python-debug.dockerfile @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -FROM ghcr.io/mamba-org/micromamba:bookworm +FROM ghcr.io/mamba-org/micromamba:debian-slim ARG ARCH ARG GO diff --git a/ci/docker/python-debug.sh b/ci/docker/python-debug.sh index cf03c988d9..6012093dd7 100755 --- a/ci/docker/python-debug.sh +++ b/ci/docker/python-debug.sh @@ -31,7 +31,7 @@ cat /adbc/ci/conda_env_cpp.txt /adbc/ci/conda_env_python.txt |\ micromamba install -c conda-forge -y \ -f /tmp/spec.txt \ - "conda-forge/label/python_debug::python=${PYTHON}[build=*_cpython]" + "conda-forge/label/python_debug::python=${PYTHON}.*" micromamba clean --all -y export ADBC_USE_ASAN=ON diff --git a/ci/scripts/cpp_shared_no_common_entrypoints_test.sh b/ci/scripts/cpp_shared_no_common_entrypoints_test.sh new file mode 100755 index 0000000000..55e900172d --- /dev/null +++ b/ci/scripts/cpp_shared_no_common_entrypoints_test.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Test building a simple application using the static drivers, ensuring that +# symbols do not clash and all dependencies are present. +# https://github.com/apache/arrow-adbc/issues/2562 + +set -euo pipefail + +main() { + local -r source_dir="${1}" + local -r build_dir="${2}" + local -r install_dir="${3}" + + mkdir -p "${build_dir}" + + echo "Install ADBC" + mkdir -p "${build_dir}/install" + pushd "${build_dir}/install" + env \ + ADBC_BUILD_SHARED=ON \ + ADBC_BUILD_STATIC=OFF \ + ADBC_BUILD_TESTS=OFF \ + ADBC_USE_ASAN=OFF \ + ADBC_USE_UBSAN=OFF \ + ADBC_CMAKE_ARGS="-DADBC_DEFINE_COMMON_ENTRYPOINTS=OFF" \ + "${source_dir}/ci/scripts/cpp_build.sh" \ + "${source_dir}" \ + "${build_dir}/install" \ + "${install_dir}" + popd + + # No static libraries should exist + if find "${install_dir}" | grep -E "libadbc.*\.a"; then + echo "Found ADBC static libraries, which should not exist for this test" + return 1 + fi + + # Make sure Adbc symbols aren't exported + failed=0 + for lib in "${install_dir}/lib"/libadbc_driver_*.so; do + echo "Checking symbols in $lib" + if [[ $(basename "$lib") == *"adbc_driver_manager"* ]]; then + continue + fi + + nm \ + --defined-only \ + --demangle \ + --extern-only \ + --no-weak \ + "${lib}" | \ + grep ' T ' | \ + awk '{print $3}' | \ + { grep --extended-regexp '^Adbc' || true; } | \ + { grep --extended-regexp --invert-match '^AdbcDriver[a-zA-Z]+Init' || true; } \ + > /tmp/symbols.txt + if [[ -s /tmp/symbols.txt ]]; then + echo "Found unexpected exported Adbc* symbols in $lib" + cat /tmp/symbols.txt + failed=$(($failed + 1)) + fi + done + if [[ $failed -ne 0 ]]; then + return $failed + fi + + echo "Build test application" + mkdir -p "${build_dir}/test" + pushd "${build_dir}/test" + cmake "${source_dir}/c/integration/shared_test" \ + -DCMAKE_PREFIX_PATH="${install_dir}" \ + -DCMAKE_VERBOSE_MAKEFILE=ON + cmake --build "${build_dir}/test" --target shared_test + + env LD_LIBRARY_PATH="${install_dir}/lib" "${build_dir}/test/shared_test" + popd +} + +main "$@" diff --git a/ci/scripts/cpp_static_test.sh b/ci/scripts/cpp_static_test.sh new file mode 100755 index 0000000000..4114d4fcfd --- /dev/null +++ b/ci/scripts/cpp_static_test.sh @@ -0,0 +1,123 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Test building a simple application using the static drivers, ensuring that +# symbols do not clash and all dependencies are present. +# https://github.com/apache/arrow-adbc/issues/2562 + +set -euo pipefail + +main() { + local -r source_dir="${1}" + local -r build_dir="${2}" + local -r install_dir="${3}" + + mkdir -p "${build_dir}" + + echo "Install fmt" + if [ ! -d "${build_dir}/fmt" ]; then + git clone https://github.com/fmtlib/fmt.git --branch 11.1.4 --depth 1 "${build_dir}/fmt" + fi + mkdir -p "${build_dir}/fmt/build" + pushd "${build_dir}/fmt/build" + cmake "${build_dir}/fmt" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="${install_dir}" \ + -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE \ + -DFMT_DOC=OFF \ + -DFMT_TEST=OFF + cmake --build "${build_dir}/fmt/build" --target install -j + popd + + echo "Install nanoarrow" + if [ ! -d "${build_dir}/nanoarrow" ]; then + git clone https://github.com/apache/arrow-nanoarrow.git --depth 1 "${build_dir}/nanoarrow" + fi + mkdir -p "${build_dir}/nanoarrow/build" + pushd "${build_dir}/nanoarrow/build" + cmake "${build_dir}/nanoarrow" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="${install_dir}" \ + -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE + cmake --build "${build_dir}/nanoarrow/build" --target install -j + popd + + echo "Install ADBC" + mkdir -p "${build_dir}/install" + pushd "${build_dir}/install" + env \ + ADBC_BUILD_SHARED=OFF \ + ADBC_BUILD_STATIC=ON \ + ADBC_BUILD_TESTS=OFF \ + ADBC_USE_ASAN=OFF \ + ADBC_USE_UBSAN=OFF \ + ADBC_CMAKE_ARGS="-DADBC_WITH_VENDORED_FMT=OFF -DADBC_WITH_VENDORED_NANOARROW=OFF -DADBC_DEFINE_COMMON_ENTRYPOINTS=OFF" \ + "${source_dir}/ci/scripts/cpp_build.sh" \ + "${source_dir}" \ + "${build_dir}/install" \ + "${install_dir}" + popd + + # No shared libraries should exist + if find "${install_dir}" | grep -E "libadbc.*\.so"; then + echo "Found ADBC shared libraries, which should not exist for this test" + return 1 + fi + + # Make sure Adbc symbols aren't exported + failed=0 + for lib in "${install_dir}/lib"/libadbc_driver_*.a; do + echo "Checking symbols in $lib" + if [[ $(basename "$lib") == *"adbc_driver_manager"* ]]; then + continue + fi + + nm \ + --defined-only \ + --demangle \ + --extern-only \ + --no-weak \ + "${lib}" | \ + grep ' T ' | \ + awk '{print $3}' | \ + { grep --extended-regexp '^Adbc' || true; } | \ + { grep --extended-regexp --invert-match '^AdbcDriver[a-zA-Z]+Init' || true; } \ + > /tmp/symbols.txt + if [[ -s /tmp/symbols.txt ]]; then + echo "Found unexpected exported Adbc* symbols in $lib" + cat /tmp/symbols.txt + failed=$(($failed + 1)) + fi + done + if [[ $failed -ne 0 ]]; then + return $failed + fi + + echo "Build test application" + mkdir -p "${build_dir}/test" + pushd "${build_dir}/test" + cmake "${source_dir}/c/integration/static_test" \ + -DCMAKE_PREFIX_PATH="${install_dir}" \ + -DCMAKE_VERBOSE_MAKEFILE=ON + cmake --build "${build_dir}/test" --target static_test + + "${build_dir}/test/static_test" + popd +} + +main "$@" diff --git a/compose.yaml b/compose.yaml index 742669cc80..bcf85726ff 100644 --- a/compose.yaml +++ b/compose.yaml @@ -34,6 +34,7 @@ services: # Build/test with latest Clang cpp-clang-latest: + image: ${REPO}:${ARCH}-cpp-clang-latest-adbc build: context: . dockerfile: ci/docker/cpp-clang-latest.dockerfile @@ -44,6 +45,7 @@ services: command: "bash -c 'git config --global --add safe.directory /adbc && /adbc/ci/scripts/cpp_build.sh /adbc /adbc/build/clang-latest && env BUILD_ALL=0 BUILD_DRIVER_MANAGER=1 BUILD_DRIVER_SQLITE=1 /adbc/ci/scripts/cpp_test.sh /adbc/build/clang-latest'" cpp-gcc-latest: + image: ${REPO}:${ARCH}-cpp-gcc-latest-adbc build: context: . dockerfile: ci/docker/cpp-gcc-latest.dockerfile @@ -54,6 +56,21 @@ services: - .:/adbc:delegated command: "bash -c 'git config --global --add safe.directory /adbc && /adbc/ci/scripts/cpp_build.sh /adbc /adbc/build/gcc-latest && env BUILD_ALL=0 BUILD_DRIVER_MANAGER=1 BUILD_DRIVER_SQLITE=1 /adbc/ci/scripts/cpp_test.sh /adbc/build/gcc-latest'" + # Build and dynamically load shared drivers missing the common entrypoints + cpp-shared-no-common-entrypoints-test: + image: ${REPO}:${ARCH}-cpp-clang-latest-adbc + volumes: + - .:/adbc:delegated + command: "bash -c 'git config --global --add safe.directory /adbc && /adbc/ci/scripts/cpp_shared_no_common_entrypoints_test.sh /adbc /adbc/build/shared-test/build /adbc/build/shared-test/local'" + + # Test building and installing the static libraries, then try linking to them. + cpp-static-test: + image: ${REPO}:${ARCH}-cpp-clang-latest-adbc + volumes: + - .:/adbc:delegated + command: "bash -c 'git config --global --add safe.directory /adbc && /adbc/ci/scripts/cpp_static_test.sh /adbc /adbc/build/static-test/build /adbc/build/static-test/local'" + + ############################ Documentation ################################### docs: @@ -98,11 +115,11 @@ services: command: "/bin/bash -c '/adbc/ci/scripts/python_conda_test.sh /adbc /adbc/build'" python-debug: - image: ${REPO}:${ARCH}-python-${PYTHON}-debug-adbc + image: ${REPO}:${ARCH}-python-debug-adbc build: context: . cache_from: - - ${REPO}:${ARCH}-python-${PYTHON}-debug-adbc + - ${REPO}:${ARCH}-python-debug-adbc dockerfile: ci/docker/python-debug.dockerfile args: ARCH: ${ARCH} diff --git a/csharp/src/Drivers/Interop/FlightSql/FlightSqlDriverLoader.cs b/csharp/src/Drivers/Interop/FlightSql/FlightSqlDriverLoader.cs index 12ea491d92..ef090d4fd2 100644 --- a/csharp/src/Drivers/Interop/FlightSql/FlightSqlDriverLoader.cs +++ b/csharp/src/Drivers/Interop/FlightSql/FlightSqlDriverLoader.cs @@ -22,7 +22,7 @@ namespace Apache.Arrow.Adbc.Drivers.Interop.FlightSql /// public class FlightSqlDriverLoader : AdbcDriverLoader { - public FlightSqlDriverLoader() : base("libadbc_driver_flightsql", "FlightSqlDriverInit") + public FlightSqlDriverLoader() : base("libadbc_driver_flightsql", "AdbcDriverFlightsqlInit") { } diff --git a/csharp/src/Drivers/Interop/Snowflake/SnowflakeDriverLoader.cs b/csharp/src/Drivers/Interop/Snowflake/SnowflakeDriverLoader.cs index 14d85b6de0..27dfe3452f 100644 --- a/csharp/src/Drivers/Interop/Snowflake/SnowflakeDriverLoader.cs +++ b/csharp/src/Drivers/Interop/Snowflake/SnowflakeDriverLoader.cs @@ -24,7 +24,7 @@ namespace Apache.Arrow.Adbc.Drivers.Interop.Snowflake /// public class SnowflakeDriverLoader : AdbcDriverLoader { - public SnowflakeDriverLoader() : base("libadbc_driver_snowflake", "SnowflakeDriverInit") + public SnowflakeDriverLoader() : base("libadbc_driver_snowflake", "AdbcDriverSnowflakeInit") { } diff --git a/csharp/test/Drivers/Interop/Snowflake/readme.md b/csharp/test/Drivers/Interop/Snowflake/readme.md index 8e7a8877c1..a0df8aff21 100644 --- a/csharp/test/Drivers/Interop/Snowflake/readme.md +++ b/csharp/test/Drivers/Interop/Snowflake/readme.md @@ -30,7 +30,7 @@ The environment variable `SNOWFLAKE_TEST_CONFIG_FILE` must be set to a configura The following values can be setup in the configuration: - **driverPath** - The path for the Go library. Can be a relative path if using .NET 5.0 or greater, otherwise, it is an absolute path. -- **driverEntryPoint** - The driver entry point. For Snowflake, this is `SnowflakeDriverInit`. +- **driverEntryPoint** - The driver entry point. For Snowflake, this is `AdbcDriverSnowflakeInit`. - **account** - The `adbc.snowflake.sql.account` value from the [Snowflake Client Options](https://arrow.apache.org/adbc/0.5.1/driver/snowflake.html#client-options). - **user** - The Snowflake user name. - **password** - The Snowflake password, if using `auth_snowflake` for the auth type. diff --git a/docs/source/cpp/index.rst b/docs/source/cpp/index.rst index 29bbfc9202..6f68c9e53a 100644 --- a/docs/source/cpp/index.rst +++ b/docs/source/cpp/index.rst @@ -26,4 +26,5 @@ C and C++ driver_manager concurrency driver_example + static_linking api/index diff --git a/docs/source/cpp/static_linking.rst b/docs/source/cpp/static_linking.rst new file mode 100644 index 0000000000..19470ad066 --- /dev/null +++ b/docs/source/cpp/static_linking.rst @@ -0,0 +1,64 @@ +.. Licensed to the Apache Software Foundation (ASF) under one +.. or more contributor license agreements. See the NOTICE file +.. distributed with this work for additional information +.. regarding copyright ownership. The ASF licenses this file +.. to you under the Apache License, Version 2.0 (the +.. "License"); you may not use this file except in compliance +.. with the License. You may obtain a copy of the License at +.. +.. http://www.apache.org/licenses/LICENSE-2.0 +.. +.. Unless required by applicable law or agreed to in writing, +.. software distributed under the License is distributed on an +.. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +.. KIND, either express or implied. See the License for the +.. specific language governing permissions and limitations +.. under the License. + +============== +Static Linking +============== + +To statically link and use *multiple* drivers, the following limitations hold: + +#. You must build with these CMake options [#meson]_: + + - ``-DADBC_BUILD_STATIC=ON`` + - ``-DADBC_DEFINE_COMMON_ENTRYPOINTS=OFF`` + - ``-DADBC_WITH_VENDORED_FMT=OFF`` + - ``-DADBC_WITH_VENDORED_NANOARROW=OFF`` + +#. You must provide ``fmt`` and ``nanoarrow`` dependencies. (This may be + relaxed in the future.) +#. You must explicitly link all the required transitive dependencies. This + is: + + - ``libpq`` for PostgreSQL + - ``sqlite3`` for SQLite + - ``adbc_driver_common``, ``adbc_driver_framework``, ``fmt``, + ``nanoarrow``, and the C++ standard library for either PostgreSQL or + SQLite. + - To link the C++ standard library, the easiest thing is to just use the + C++ linker, even if the code itself is in C, e.g. + + .. code-block:: cmake + + set_target_properties(myapp PROPERTIES LINKER_LANGUAGE CXX) + + - Go-based drivers (BigQuery, Flight SQL, Snowflake) have no transitive + dependencies. + +#. You cannot link more than a single Go-based driver. See `golang/go#20639 + `_, `StackOverflow #67243572 `_, and `StackOverflow + #34333107 `_ for a discussion of the issues involved. (This + may be relaxed in the future by providing a way to build a single driver + library with all driver implementations included.) + +An example of this can be seen with ``cpp_static_test.sh`` and +``c/integration/static_test`` in the source tree. + +.. [#meson] There is currently no documentation for Meson, but in principle + it should work similarly. +.. _go20639: https://github.com/golang/go/issues/20639 +.. _so67243572: https://stackoverflow.com/questions/67243572/go-cgo-produce-static-library-without-definitions-of-go-runtime-functions +.. _so34333107: https://stackoverflow.com/questions/34333107/is-there-a-way-to-include-multiple-c-archive-packages-in-a-single-binary diff --git a/go/adbc/drivermgr/arrow-adbc/adbc_driver_manager.h b/go/adbc/drivermgr/arrow-adbc/adbc_driver_manager.h index c32368ab69..e5e9bf67c4 100644 --- a/go/adbc/drivermgr/arrow-adbc/adbc_driver_manager.h +++ b/go/adbc/drivermgr/arrow-adbc/adbc_driver_manager.h @@ -40,8 +40,9 @@ extern "C" { /// /// \param[in] driver_name An identifier for the driver (e.g. a path to a /// shared library on Linux). -/// \param[in] entrypoint An identifier for the entrypoint (e.g. the -/// symbol to call for AdbcDriverInitFunc on Linux). +/// \param[in] entrypoint An identifier for the entrypoint (e.g. the symbol to +/// call for AdbcDriverInitFunc on Linux). If not provided, search for an +/// entrypoint based on the driver name. /// \param[in] version The ADBC revision to attempt to initialize. /// \param[out] driver The table of function pointers to initialize. /// \param[out] error An optional location to return an error message diff --git a/go/adbc/pkg/_tmpl/driver.go.tmpl b/go/adbc/pkg/_tmpl/driver.go.tmpl index bbede3b3c3..0eec1fcc10 100644 --- a/go/adbc/pkg/_tmpl/driver.go.tmpl +++ b/go/adbc/pkg/_tmpl/driver.go.tmpl @@ -1810,8 +1810,8 @@ func {{.Prefix}}StatementExecutePartitions(stmt *C.struct_AdbcStatement, schema return C.ADBC_STATUS_OK } -//export {{.Prefix}}DriverInit -func {{.Prefix}}DriverInit(version C.int, rawDriver *C.void, err *C.struct_AdbcError) C.AdbcStatusCode { +//export AdbcDriver{{.Prefix}}Init +func AdbcDriver{{.Prefix}}Init(version C.int, rawDriver *C.void, err *C.struct_AdbcError) C.AdbcStatusCode { driver := (*C.struct_AdbcDriver)(unsafe.Pointer(rawDriver)) switch version { diff --git a/go/adbc/pkg/_tmpl/utils.c.tmpl b/go/adbc/pkg/_tmpl/utils.c.tmpl index 3b7601a6c8..08a039facf 100644 --- a/go/adbc/pkg/_tmpl/utils.c.tmpl +++ b/go/adbc/pkg/_tmpl/utils.c.tmpl @@ -83,6 +83,7 @@ struct AdbcErrorDetail {{.Prefix}}ErrorGetDetail(const struct AdbcError* error, }; } +#if !defined(ADBC_NO_COMMON_ENTRYPOINTS) int AdbcErrorGetDetailCount(const struct AdbcError* error) { return {{.Prefix}}ErrorGetDetailCount(error); } @@ -428,8 +429,9 @@ AdbcStatusCode AdbcStatementSetOptionInt(struct AdbcStatement* statement, ADBC_EXPORT AdbcStatusCode AdbcDriverInit(int version, void* driver, struct AdbcError* error) { - return {{.Prefix}}DriverInit(version, driver, error); + return AdbcDriver{{.Prefix}}Init(version, driver, error); } +#endif // ADBC_NO_COMMON_ENTRYPOINTS int {{.Prefix}}ArrayStreamGetSchema(struct ArrowArrayStream*, struct ArrowSchema*); int {{.Prefix}}ArrayStreamGetNext(struct ArrowArrayStream*, struct ArrowArray*); diff --git a/go/adbc/pkg/_tmpl/utils.h.tmpl b/go/adbc/pkg/_tmpl/utils.h.tmpl index 15d862f462..b8d9a039ab 100644 --- a/go/adbc/pkg/_tmpl/utils.h.tmpl +++ b/go/adbc/pkg/_tmpl/utils.h.tmpl @@ -81,7 +81,7 @@ AdbcStatusCode {{.Prefix}}StatementSetOptionInt(struct AdbcStatement*, const cha AdbcStatusCode {{.Prefix}}StatementSetSqlQuery(struct AdbcStatement* stmt, const char* query, struct AdbcError* err); AdbcStatusCode {{.Prefix}}StatementSetSubstraitPlan(struct AdbcStatement* stmt, const uint8_t* plan, size_t length, struct AdbcError* err); -AdbcStatusCode {{.Prefix}}DriverInit(int version, void* rawDriver, struct AdbcError* err); +AdbcStatusCode AdbcDriver{{.Prefix}}Init(int version, void* rawDriver, struct AdbcError* err); static inline void {{.Prefix}}errRelease(struct AdbcError* error) { if (error->release) { diff --git a/go/adbc/pkg/bigquery/driver.go b/go/adbc/pkg/bigquery/driver.go index 4f119dded7..53bb5b5f10 100644 --- a/go/adbc/pkg/bigquery/driver.go +++ b/go/adbc/pkg/bigquery/driver.go @@ -1813,8 +1813,8 @@ func BigQueryStatementExecutePartitions(stmt *C.struct_AdbcStatement, schema *C. return C.ADBC_STATUS_OK } -//export BigQueryDriverInit -func BigQueryDriverInit(version C.int, rawDriver *C.void, err *C.struct_AdbcError) C.AdbcStatusCode { +//export AdbcDriverBigqueryInit +func AdbcDriverBigqueryInit(version C.int, rawDriver *C.void, err *C.struct_AdbcError) C.AdbcStatusCode { driver := (*C.struct_AdbcDriver)(unsafe.Pointer(rawDriver)) switch version { diff --git a/go/adbc/pkg/bigquery/utils.c b/go/adbc/pkg/bigquery/utils.c index 3fefb3f5e2..a07c22f2b1 100644 --- a/go/adbc/pkg/bigquery/utils.c +++ b/go/adbc/pkg/bigquery/utils.c @@ -85,6 +85,7 @@ struct AdbcErrorDetail BigQueryErrorGetDetail(const struct AdbcError* error, }; } +#if !defined(ADBC_NO_COMMON_ENTRYPOINTS) int AdbcErrorGetDetailCount(const struct AdbcError* error) { return BigQueryErrorGetDetailCount(error); } @@ -430,7 +431,14 @@ AdbcStatusCode AdbcStatementSetOptionInt(struct AdbcStatement* statement, ADBC_EXPORT AdbcStatusCode AdbcDriverInit(int version, void* driver, struct AdbcError* error) { - return BigQueryDriverInit(version, driver, error); + return AdbcDriverBigqueryInit(version, driver, error); +} +#endif // ADBC_NO_COMMON_ENTRYPOINTS + +ADBC_EXPORT +AdbcStatusCode BigQueryDriverInit(int version, void* driver, struct AdbcError* error) { + // For backwards compatibility + return AdbcDriverBigqueryInit(version, driver, error); } int BigQueryArrayStreamGetSchema(struct ArrowArrayStream*, struct ArrowSchema*); diff --git a/go/adbc/pkg/bigquery/utils.h b/go/adbc/pkg/bigquery/utils.h index 6e2b96d86d..3eb938b9fd 100644 --- a/go/adbc/pkg/bigquery/utils.h +++ b/go/adbc/pkg/bigquery/utils.h @@ -156,6 +156,8 @@ AdbcStatusCode BigQueryStatementSetSubstraitPlan(struct AdbcStatement* stmt, const uint8_t* plan, size_t length, struct AdbcError* err); +AdbcStatusCode AdbcDriverBigqueryInit(int version, void* rawDriver, + struct AdbcError* err); AdbcStatusCode BigQueryDriverInit(int version, void* rawDriver, struct AdbcError* err); static inline void BigQueryerrRelease(struct AdbcError* error) { diff --git a/go/adbc/pkg/flightsql/driver.go b/go/adbc/pkg/flightsql/driver.go index 57e3a55462..037130cf41 100644 --- a/go/adbc/pkg/flightsql/driver.go +++ b/go/adbc/pkg/flightsql/driver.go @@ -1813,8 +1813,8 @@ func FlightSQLStatementExecutePartitions(stmt *C.struct_AdbcStatement, schema *C return C.ADBC_STATUS_OK } -//export FlightSQLDriverInit -func FlightSQLDriverInit(version C.int, rawDriver *C.void, err *C.struct_AdbcError) C.AdbcStatusCode { +//export AdbcDriverFlightsqlInit +func AdbcDriverFlightsqlInit(version C.int, rawDriver *C.void, err *C.struct_AdbcError) C.AdbcStatusCode { driver := (*C.struct_AdbcDriver)(unsafe.Pointer(rawDriver)) switch version { diff --git a/go/adbc/pkg/flightsql/utils.c b/go/adbc/pkg/flightsql/utils.c index a3aa1dd370..f62389dcf0 100644 --- a/go/adbc/pkg/flightsql/utils.c +++ b/go/adbc/pkg/flightsql/utils.c @@ -85,6 +85,7 @@ struct AdbcErrorDetail FlightSQLErrorGetDetail(const struct AdbcError* error, }; } +#if !defined(ADBC_NO_COMMON_ENTRYPOINTS) int AdbcErrorGetDetailCount(const struct AdbcError* error) { return FlightSQLErrorGetDetailCount(error); } @@ -430,7 +431,14 @@ AdbcStatusCode AdbcStatementSetOptionInt(struct AdbcStatement* statement, ADBC_EXPORT AdbcStatusCode AdbcDriverInit(int version, void* driver, struct AdbcError* error) { - return FlightSQLDriverInit(version, driver, error); + return AdbcDriverFlightsqlInit(version, driver, error); +} +#endif // ADBC_NO_COMMON_ENTRYPOINTS + +ADBC_EXPORT +AdbcStatusCode FlightSqlDriverInit(int version, void* driver, struct AdbcError* error) { + // For backwards compatibility + return AdbcDriverFlightsqlInit(version, driver, error); } int FlightSQLArrayStreamGetSchema(struct ArrowArrayStream*, struct ArrowSchema*); diff --git a/go/adbc/pkg/flightsql/utils.h b/go/adbc/pkg/flightsql/utils.h index 8c26c8439f..0f45f3dc5b 100644 --- a/go/adbc/pkg/flightsql/utils.h +++ b/go/adbc/pkg/flightsql/utils.h @@ -154,7 +154,9 @@ AdbcStatusCode FlightSQLStatementSetSubstraitPlan(struct AdbcStatement* stmt, const uint8_t* plan, size_t length, struct AdbcError* err); -AdbcStatusCode FlightSQLDriverInit(int version, void* rawDriver, struct AdbcError* err); +AdbcStatusCode AdbcDriverFlightsqlInit(int version, void* rawDriver, + struct AdbcError* err); +AdbcStatusCode FlightSqlDriverInit(int version, void* rawDriver, struct AdbcError* err); static inline void FlightSQLerrRelease(struct AdbcError* error) { if (error->release) { diff --git a/go/adbc/pkg/snowflake/driver.go b/go/adbc/pkg/snowflake/driver.go index 47147481a0..5d4175fcc3 100644 --- a/go/adbc/pkg/snowflake/driver.go +++ b/go/adbc/pkg/snowflake/driver.go @@ -1813,8 +1813,8 @@ func SnowflakeStatementExecutePartitions(stmt *C.struct_AdbcStatement, schema *C return C.ADBC_STATUS_OK } -//export SnowflakeDriverInit -func SnowflakeDriverInit(version C.int, rawDriver *C.void, err *C.struct_AdbcError) C.AdbcStatusCode { +//export AdbcDriverSnowflakeInit +func AdbcDriverSnowflakeInit(version C.int, rawDriver *C.void, err *C.struct_AdbcError) C.AdbcStatusCode { driver := (*C.struct_AdbcDriver)(unsafe.Pointer(rawDriver)) switch version { diff --git a/go/adbc/pkg/snowflake/utils.c b/go/adbc/pkg/snowflake/utils.c index 17ef6a4ff3..46c05b6cd3 100644 --- a/go/adbc/pkg/snowflake/utils.c +++ b/go/adbc/pkg/snowflake/utils.c @@ -85,6 +85,7 @@ struct AdbcErrorDetail SnowflakeErrorGetDetail(const struct AdbcError* error, }; } +#if !defined(ADBC_NO_COMMON_ENTRYPOINTS) int AdbcErrorGetDetailCount(const struct AdbcError* error) { return SnowflakeErrorGetDetailCount(error); } @@ -430,7 +431,14 @@ AdbcStatusCode AdbcStatementSetOptionInt(struct AdbcStatement* statement, ADBC_EXPORT AdbcStatusCode AdbcDriverInit(int version, void* driver, struct AdbcError* error) { - return SnowflakeDriverInit(version, driver, error); + return AdbcDriverSnowflakeInit(version, driver, error); +} +#endif // ADBC_NO_COMMON_ENTRYPOINTS + +ADBC_EXPORT +AdbcStatusCode SnowflakeDriverInit(int version, void* driver, struct AdbcError* error) { + // For backwards compatibility + return AdbcDriverSnowflakeInit(version, driver, error); } int SnowflakeArrayStreamGetSchema(struct ArrowArrayStream*, struct ArrowSchema*); diff --git a/go/adbc/pkg/snowflake/utils.h b/go/adbc/pkg/snowflake/utils.h index 8268caabac..2942def9c8 100644 --- a/go/adbc/pkg/snowflake/utils.h +++ b/go/adbc/pkg/snowflake/utils.h @@ -154,6 +154,8 @@ AdbcStatusCode SnowflakeStatementSetSubstraitPlan(struct AdbcStatement* stmt, const uint8_t* plan, size_t length, struct AdbcError* err); +AdbcStatusCode AdbcDriverSnowflakeInit(int version, void* rawDriver, + struct AdbcError* err); AdbcStatusCode SnowflakeDriverInit(int version, void* rawDriver, struct AdbcError* err); static inline void SnowflakeerrRelease(struct AdbcError* error) { diff --git a/r/adbcsqlite/src/init.cc b/r/adbcsqlite/src/init.cc index 3c921c19c3..a7f51bfb38 100644 --- a/r/adbcsqlite/src/init.cc +++ b/r/adbcsqlite/src/init.cc @@ -22,7 +22,8 @@ #include "arrow-adbc/adbc.h" extern "C" { -AdbcStatusCode SqliteDriverInit(int version, void* raw_driver, struct AdbcError* error); +AdbcStatusCode AdbcDriverSqliteInit(int version, void* raw_driver, + struct AdbcError* error); static SEXP init_func_xptr = 0; @@ -36,7 +37,7 @@ void R_init_adbcsqlite(DllInfo* dll) { R_useDynamicSymbols(dll, FALSE); init_func_xptr = - PROTECT(R_MakeExternalPtrFn((DL_FUNC)SqliteDriverInit, R_NilValue, R_NilValue)); + PROTECT(R_MakeExternalPtrFn((DL_FUNC)AdbcDriverSqliteInit, R_NilValue, R_NilValue)); Rf_setAttrib(init_func_xptr, R_ClassSymbol, Rf_mkString("adbc_driver_init_func")); R_PreserveObject(init_func_xptr); UNPROTECT(1); diff --git a/rust/driver/snowflake/src/driver.rs b/rust/driver/snowflake/src/driver.rs index 825cd61ae1..e355d3f9cd 100644 --- a/rust/driver/snowflake/src/driver.rs +++ b/rust/driver/snowflake/src/driver.rs @@ -39,7 +39,7 @@ pub use builder::*; static DRIVER: LazyLock> = LazyLock::new(|| { ManagedDriver::load_dynamic_from_name( "adbc_driver_snowflake", - Some(b"SnowflakeDriverInit"), + Some(b"AdbcDriverSnowflakeInit"), Default::default(), ) }); @@ -65,7 +65,7 @@ impl fmt::Debug for Driver { #[cfg(any(feature = "bundled", feature = "linked"))] extern "C" { - #[link_name = "SnowflakeDriverInit"] + #[link_name = "AdbcDriverSnowflakeInit"] fn init(version: c_int, raw_driver: *mut c_void, err: *mut FFI_AdbcError) -> FFI_AdbcStatusCode; }