Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion .github/workflows/cpp_extra.yml
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,62 @@ jobs:
cd cpp/examples/minimal_build
../minimal_build.build/arrow-example

odbc-linux:
needs: check-labels
name: ODBC Linux
runs-on: ubuntu-latest
if: >-
needs.check-labels.outputs.force == 'true' ||
contains(fromJSON(needs.check-labels.outputs.ci-extra-labels || '[]'), 'CI: Extra') ||
contains(fromJSON(needs.check-labels.outputs.ci-extra-labels || '[]'), 'CI: Extra: C++')
timeout-minutes: 75
strategy:
fail-fast: false
env:
ARCH: amd64
ARCHERY_DEBUG: 1
ARROW_ENABLE_TIMING_TESTS: OFF
DOCKER_VOLUME_PREFIX: ".docker/"
UBUNTU: 24.04
steps:
- name: Checkout Arrow
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Cache Docker Volumes
uses: actions/cache@v5
with:
path: .docker
key: ubuntu-cpp-odbc-${{ hashFiles('cpp/**') }}
restore-keys: ubuntu-cpp-odbc-
- name: Setup Python on hosted runner
uses: actions/setup-python@v6
with:
python-version: 3
- name: Setup Archery
run: python3 -m pip install -e dev/archery[docker]
- name: Execute Docker Build
env:
ARCHERY_DOCKER_USER: ${{ secrets.DOCKERHUB_USER }}
ARCHERY_DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }}
run: |
# GH-40558: reduce ASLR to avoid ASAN/LSAN crashes
sudo sysctl -w vm.mmap_rnd_bits=28
source ci/scripts/util_enable_core_dumps.sh
archery docker run ubuntu-cpp-odbc
- name: Docker Push
if: >-
success() &&
github.event_name == 'push' &&
github.repository == 'apache/arrow' &&
github.ref_name == 'main'
env:
ARCHERY_DOCKER_USER: ${{ secrets.DOCKERHUB_USER }}
ARCHERY_DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }}
continue-on-error: true
run: archery docker push ubuntu-cpp-odbc
Comment on lines +383 to +393
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this image because we can reuse ubuntu-cpp image.

Suggested change
- name: Docker Push
if: >-
success() &&
github.event_name == 'push' &&
github.repository == 'apache/arrow' &&
github.ref_name == 'main'
env:
ARCHERY_DOCKER_USER: ${{ secrets.DOCKERHUB_USER }}
ARCHERY_DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }}
continue-on-error: true
run: archery docker push ubuntu-cpp-odbc

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi kou, I used ubuntu-cpp-odbc for running a custom commands section, since for ODBC we need to run the ODBC registration script before executing tests.
In order to use ubuntu-cpp, I tried code like archery docker run ubuntu-cpp bash -c "<custom_commands>" to replace the commands section and that didn't work, so I created a new image instead. Is there a workaround for this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your approach is correct. I also think that I want to create a new service (ubuntu-cpp-odbc) from an existing service (ubuntu-cpp) with different command: but we can't do it with Docker Compose. So we can create ubuntu-cpp-odbc for this. But the built image by ubuntu-cpp-odbc has the same name (${REPO}:${ARCH}-ubuntu-${UBUNTU}-cpp) and build options. So we don't need to overwrite existing ${REPO}:${ARCH}-ubuntu-${UBUNTU}-cpp image by this.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kou Sounds good. I have changed ubuntu-cpp-odbc to re-use ubuntu-cpp as a service to reduce duplicate code. I also disabled non-ODBC related libraries in ubuntu-cpp-odbc. Please have another look.


odbc-macos:
needs: check-labels
name: ODBC ${{ matrix.build-type }} ${{ matrix.architecture }} macOS ${{ matrix.macos-version }}
Expand Down Expand Up @@ -435,7 +491,7 @@ jobs:
"$(pwd)/build/cpp/${{ matrix.build-type }}/libarrow_flight_sql_odbc.dylib"
- name: Register Flight SQL ODBC Driver
run: |
sudo cpp/src/arrow/flight/sql/odbc/install/mac/install_odbc.sh $(pwd)/build/cpp/${{ matrix.build-type }}/libarrow_flight_sql_odbc.dylib
sudo cpp/src/arrow/flight/sql/odbc/install/unix/install_odbc.sh $(pwd)/build/cpp/${{ matrix.build-type }}/libarrow_flight_sql_odbc.dylib
- name: Test
shell: bash
run: |
Expand Down Expand Up @@ -698,6 +754,7 @@ jobs:
- jni-linux
- jni-macos
- msvc-arm64
- odbc-linux
- odbc-macos
- odbc-msvc
- odbc-nightly
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ repos:
?^cpp/build-support/update-thrift\.sh$|
?^cpp/examples/minimal_build/run\.sh$|
?^cpp/examples/tutorial_examples/run\.sh$|
?^cpp/src/arrow/flight/sql/odbc/install/mac/install_odbc\.sh$|
?^cpp/src/arrow/flight/sql/odbc/install/unix/install_odbc\.sh$|
?^dev/release/05-binary-upload\.sh$|
?^dev/release/08-binary-verify\.sh$|
?^dev/release/binary-recover\.sh$|
Expand Down
1 change: 1 addition & 0 deletions ci/docker/ubuntu-24.04-cpp.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ RUN apt-get update -y -q && \
rsync \
tzdata \
tzdata-legacy \
unixodbc-dev \
uuid-runtime \
unzip \
wget && \
Expand Down
30 changes: 29 additions & 1 deletion compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ x-hierarchy:
- ubuntu-r-only-r
- ubuntu-cpp-bundled
- ubuntu-cpp-bundled-offline
- ubuntu-cpp-odbc
- ubuntu-cpp-minimal
- ubuntu-cuda-cpp:
- ubuntu-cuda-python
Expand Down Expand Up @@ -371,7 +372,7 @@ services:
/arrow/ci/scripts/cpp_build.sh /arrow /build &&
/arrow/ci/scripts/cpp_test.sh /arrow /build"

ubuntu-cpp:
ubuntu-cpp: &ubuntu-cpp-base
# Usage:
# docker compose build ubuntu-cpp
# docker compose run --rm ubuntu-cpp
Expand Down Expand Up @@ -496,6 +497,33 @@ services:
volumes: *ubuntu-volumes
command: *cpp-command

ubuntu-cpp-odbc:
# Arrow Flight SQL ODBC build with BUNDLED dependencies with downloaded dependencies.
<<: *ubuntu-cpp-base
environment:
<<: [*common, *ccache, *sccache, *cpp]
ARROW_ACERO: "OFF"
ARROW_AZURE: "OFF"
ARROW_BUILD_TYPE: RELEASE
ARROW_CSV: "OFF"
ARROW_DATASET: "OFF"
ARROW_DEPENDENCY_SOURCE: BUNDLED
ARROW_DEPENDENCY_USE_SHARED: "OFF"
ARROW_FLIGHT_SQL_ODBC: "ON"
ARROW_GANDIVA: "OFF"
ARROW_GCS: "OFF"
ARROW_HDFS: "OFF"
ARROW_ORC: "OFF"
ARROW_PARQUET: "OFF"
ARROW_S3: "OFF"
ARROW_SUBSTRAIT: "OFF"
# Register ODBC before running tests
command: >
/bin/bash -c "
/arrow/ci/scripts/cpp_build.sh /arrow /build &&
sudo /arrow/cpp/src/arrow/flight/sql/odbc/install/unix/install_odbc.sh /usr/local/lib/libarrow_flight_sql_odbc.so &&
/arrow/ci/scripts/cpp_test.sh /arrow /build"

ubuntu-cpp-minimal:
# Arrow build with minimal components/dependencies
image: ${REPO}:${ARCH}-ubuntu-${UBUNTU}-cpp-minimal
Expand Down
4 changes: 0 additions & 4 deletions cpp/cmake_modules/DefineOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,6 @@ macro(tsort_bool_option_dependencies)
endmacro()

macro(resolve_option_dependencies)
# Arrow Flight SQL ODBC is available only for Windows and macOS for now.
if(NOT WIN32 AND NOT APPLE)
set(ARROW_FLIGHT_SQL_ODBC OFF)
endif()
if(MSVC_TOOLCHAIN)
set(ARROW_USE_GLOG OFF)
endif()
Expand Down
2 changes: 1 addition & 1 deletion cpp/cmake_modules/ThirdpartyToolchain.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ function(build_boost)
set(ARROW_BOOST_NEED_MULTIPRECISION FALSE)
endif()
if(ARROW_ENABLE_THREADING)
if(ARROW_WITH_THRIFT OR (ARROW_FLIGHT_SQL_ODBC AND MSVC))
if(ARROW_WITH_THRIFT OR ARROW_FLIGHT_SQL_ODBC)
list(APPEND BOOST_INCLUDE_LIBRARIES locale)
endif()
if(ARROW_BOOST_NEED_MULTIPRECISION)
Expand Down
7 changes: 6 additions & 1 deletion cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ else()
endif()

add_subdirectory(odbc_impl)
add_subdirectory(tests)
if(ARROW_BUILD_TESTS)
if(WIN32 OR APPLE)
# GH-49552 TODO: Enable Linux test build
add_subdirectory(tests)
endif()
endif()

arrow_install_all_headers("arrow/flight/sql/odbc")

Expand Down
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also update .pre-commit-config.yaml?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes good catch, updated

Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,18 @@ if [ ! -f "$ODBC_64BIT" ]; then
exit 1
fi

USER_ODBCINST_FILE="$HOME/Library/ODBC/odbcinst.ini"
DRIVER_NAME="Apache Arrow Flight SQL ODBC Driver"
case "$(uname)" in
Linux)
USER_ODBCINST_FILE="/etc/odbcinst.ini"
;;
*)
# macOS
USER_ODBCINST_FILE="$HOME/Library/ODBC/odbcinst.ini"
mkdir -p "$HOME"/Library/ODBC
;;
esac

mkdir -p "$HOME"/Library/ODBC
DRIVER_NAME="Apache Arrow Flight SQL ODBC Driver"

touch "$USER_ODBCINST_FILE"

Expand Down
2 changes: 2 additions & 0 deletions cpp/src/arrow/flight/sql/odbc/odbc_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#endif // defined(_WIN32)

namespace arrow::flight::sql::odbc {
void LoadPropertiesFromDSN(const std::string& dsn, Connection::ConnPropertyMap& props);

SQLRETURN SQLAllocHandle(SQLSMALLINT type, SQLHANDLE parent, SQLHANDLE* result) {
ARROW_LOG(DEBUG) << "SQLAllocHandle called with type: " << type
<< ", parent: " << parent
Expand Down
3 changes: 1 addition & 2 deletions cpp/src/arrow/flight/sql/odbc/odbc_api_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
#include "arrow/flight/sql/odbc/odbc_impl/platform.h"

#include <sql.h>
#include <sqltypes.h>
#include <sqlucode.h>
#include <sqlext.h>

// \file odbc_api_internal.h
//
Expand Down
20 changes: 13 additions & 7 deletions cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,20 +130,26 @@ if(WIN32)
win_system_dsn.cc)
endif()

if(APPLE)
if(WIN32)
find_package(ODBC REQUIRED)
target_include_directories(arrow_odbc_spi_impl PUBLIC ${ODBC_INCLUDE_DIR})
target_link_libraries(arrow_odbc_spi_impl
PUBLIC arrow_flight_sql_shared arrow_compute_shared Boost::locale
${ODBCINST})
else()
# Unix
target_include_directories(arrow_odbc_spi_impl SYSTEM BEFORE PUBLIC ${ODBC_INCLUDE_DIR})
target_link_libraries(arrow_odbc_spi_impl
PUBLIC arrow_flight_sql_static
arrow_compute_static
Boost::locale
Boost::headers
RapidJSON)
else()
find_package(ODBC REQUIRED)
target_include_directories(arrow_odbc_spi_impl PUBLIC ${ODBC_INCLUDE_DIR})
target_link_libraries(arrow_odbc_spi_impl
PUBLIC arrow_flight_sql_shared arrow_compute_shared Boost::locale
${ODBCINST})

if(NOT APPLE)
# Explicitly link to unix-odbc on Linux
target_link_libraries(arrow_odbc_spi_impl PUBLIC ${ODBCINST})
endif()
endif()

# CLI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Basic) {
accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false,
diagnostics, nullptr));

for (int i = 0; i < values.size(); ++i) {
for (size_t i = 0; i < values.size(); ++i) {
ASSERT_EQ(values[i].length(), str_len_buffer[i]);
// Beware that CDataType_BINARY values are not null terminated.
// It's safe to create a std::string from this data because we know it's
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ TEST(BooleanArrayFlightSqlAccessor, Test_BooleanArray_CDataType_BIT) {
accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false,
diagnostics, nullptr));

for (int i = 0; i < values.size(); ++i) {
for (size_t i = 0; i < values.size(); ++i) {
ASSERT_EQ(sizeof(unsigned char), str_len_buffer[i]);
ASSERT_EQ(values[i] ? 1 : 0, buffer[i]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ void AssertNumericOutput(int input_precision, int input_scale,
accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false,
diagnostics, nullptr));

for (int i = 0; i < values.size(); ++i) {
for (size_t i = 0; i < values.size(); ++i) {
ASSERT_EQ(sizeof(NUMERIC_STRUCT), str_len_buffer[i]);

ASSERT_EQ(output_precision, buffer[i].precision);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void TestPrimitiveArraySqlAccessor() {
accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false,
diagnostics, nullptr));

for (int i = 0; i < values.size(); ++i) {
for (size_t i = 0; i < values.size(); ++i) {
ASSERT_EQ(sizeof(c_type), str_len_buffer[i]);
ASSERT_EQ(values[i], buffer[i]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Basic) {
accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false,
diagnostics, nullptr));

for (int i = 0; i < values.size(); ++i) {
for (size_t i = 0; i < values.size(); ++i) {
ASSERT_EQ(values[i].length(), str_len_buffer[i]);
ASSERT_EQ(values[i], std::string(buffer.data() + i * max_str_len));
}
Expand Down Expand Up @@ -102,7 +102,7 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Basic) {
accessor->GetColumnarData(&binding, 0, values.size(), value_offset, false,
diagnostics, nullptr));

for (int i = 0; i < values.size(); ++i) {
for (size_t i = 0; i < values.size(); ++i) {
ASSERT_EQ(values[i].length() * GetSqlWCharSize(), str_len_buffer[i]);
std::vector<uint8_t> expected;
Utf8ToWcs(values[i].c_str(), &expected);
Expand Down
10 changes: 5 additions & 5 deletions cpp/src/arrow/flight/sql/odbc/odbc_impl/accessors/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ struct ColumnBinding {

ColumnBinding(CDataType target_type, int precision, int scale, void* buffer,
size_t buffer_length, ssize_t* str_len_buffer)
: target_type(target_type),
precision(precision),
scale(scale),
buffer(buffer),
: buffer(buffer),
str_len_buffer(str_len_buffer),
buffer_length(buffer_length),
str_len_buffer(str_len_buffer) {}
target_type(target_type),
precision(precision),
scale(scale) {}
};

/// \brief Accessor interface meant to provide a way of populating data of a
Expand Down
10 changes: 10 additions & 0 deletions cpp/src/arrow/flight/sql/odbc/odbc_impl/attribute_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,21 @@ inline void SetAttributeSQLWCHAR(SQLPOINTER new_value, SQLINTEGER input_length_i
thread_local std::vector<uint8_t> utf8_str;
if (input_length_in_bytes == SQL_NTS) {
arrow::flight::sql::odbc::WcsToUtf8(new_value, &utf8_str);
} else if (input_length_in_bytes <= 0) {
// empty string
attribute_to_write.clear();
return;
} else {
arrow::flight::sql::odbc::WcsToUtf8(
new_value, input_length_in_bytes / arrow::flight::sql::odbc::GetSqlWCharSize(),
&utf8_str);
}

// add null-terminator
if (utf8_str.back() != '\0') {
utf8_str.push_back('\0');
}

attribute_to_write.assign((char*)utf8_str.data());
}

Expand Down
2 changes: 1 addition & 1 deletion cpp/src/arrow/flight/sql/odbc/odbc_impl/blocking_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class BlockingQueue {

void AddProducer(Supplier supplier) {
active_threads_++;
threads_.emplace_back([=] {
threads_.emplace_back([this, supplier] {
while (!closed_) {
// Block while queue is full
std::unique_lock<std::mutex> unique_lock(mtx_);
Expand Down
Loading
Loading