Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Arrow Flight SQL ODBC driver #40939

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
49 changes: 49 additions & 0 deletions cpp/src/arrow/flight/sql/odbc/Brewfile
Original file line number Diff line number Diff line change
@@ -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.

brew "aws-sdk-cpp"
brew "bash"
brew "boost"
brew "brotli"
brew "bzip2"
brew "c-ares"
brew "curl"
brew "ccache"
brew "cmake"
brew "flatbuffers"
brew "git"
brew "glog"
brew "googletest"
brew "grpc"
brew "llvm@14"
brew "lz4"
brew "mimalloc"
brew "ninja"
brew "node"
brew "openssl@3"
brew "pkg-config"
brew "protobuf"
brew "python"
brew "rapidjson"
brew "re2"
brew "snappy"
brew "thrift"
brew "utf8proc"
brew "wget"
brew "xsimd"
brew "zstd"
brew "libiodbc"
43 changes: 43 additions & 0 deletions cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# 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.16)
set(CMAKE_CXX_STANDARD 17)

project(flightsql_odbc)

if(CMAKE_BUILD_TYPE STREQUAL "Release")
add_compile_definitions(NDEBUG)
endif()

# Add Boost dependencies. Should be pre-installed (Brew on Mac).
find_package(Boost REQUIRED)
find_package(ODBC REQUIRED)

# Fetch and include GTest
# Adapted from Google's documentation: https://google.github.io/googletest/quickstart-cmake.html#set-up-a-project
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/v1.14.0.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

add_subdirectory(flight_sql)
add_subdirectory(odbcabstraction)
209 changes: 209 additions & 0 deletions cpp/src/arrow/flight/sql/odbc/flight_sql/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
# 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.16)
set(CMAKE_CXX_STANDARD 17)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

include_directories(include include/flight_sql
${CMAKE_SOURCE_DIR}/odbcabstraction/include)

if(DEFINED CMAKE_TOOLCHAIN_FILE)
include(${CMAKE_TOOLCHAIN_FILE})
endif()

# Add Zlib dependencies needed by Arrow Flight. Should be pre-installed
# unless provided by VCPKG. find_package(ZLIB REQUIRED)

# Add Protobuf dependencies needed by Arrow Flight. Should be pre-installed.
# set(Protobuf_USE_STATIC_LIBS OFF) find_package(Protobuf REQUIRED)

# Add OpenSSL dependencies needed by Arrow Flight. Should be pre-installed. #
# May need to set OPENSSL_ROOT_DIR first. On Mac if using brew: # brew install
# [email protected] # add to the cmake line
# -DOPENSSL_ROOT_DIR=/usr/local/Cellar/[email protected]/1.1.1m if (NOT DEFINED
# OPENSSL_ROOT_DIR AND DEFINED APPLE AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
# set(OPENSSL_ROOT_DIR /usr/local/Cellar/[email protected]/1.1.1m) endif() # This is
# based on Arrow's FindOpenSSL module. It's not clear if both variables # need
# to be set. if (NOT DEFINED MSVC) set(OpenSSL_USE_STATIC_LIBS ON)
# set(OPENSSL_USE_STATIC_LIBS ON) endif() find_package(OpenSSL REQUIRED)

# OpenSSL depends on krb5 on CentOS if (UNIX) list(APPEND OPENSSL_LIBRARIES krb5
# k5crypto) endif()

# Add gRPC dependencies needed by Arrow Flight. Should be pre-installed.
# find_package(gRPC 1.36 CONFIG REQUIRED)

find_package(RapidJSON CONFIG REQUIRED)

if(MSVC)
# the following definitions stop arrow from using __declspec when staticly
# linking and will break on Windows without them
add_compile_definitions(ARROW_STATIC ARROW_FLIGHT_STATIC)
endif()

enable_testing()

add_library(arrow_odbc_spi_impl
include/flight_sql/flight_sql_driver.h
accessors/binary_array_accessor.cc
accessors/binary_array_accessor.h
accessors/boolean_array_accessor.cc
accessors/boolean_array_accessor.h
accessors/common.h
accessors/date_array_accessor.cc
accessors/date_array_accessor.h
accessors/decimal_array_accessor.cc
accessors/decimal_array_accessor.h
accessors/main.h
accessors/primitive_array_accessor.cc
accessors/primitive_array_accessor.h
accessors/string_array_accessor.cc
accessors/string_array_accessor.h
accessors/time_array_accessor.cc
accessors/time_array_accessor.h
accessors/timestamp_array_accessor.cc
accessors/timestamp_array_accessor.h
address_info.cc
address_info.h
flight_sql_auth_method.cc
flight_sql_auth_method.h
flight_sql_connection.cc
flight_sql_connection.h
flight_sql_driver.cc
flight_sql_get_tables_reader.cc
flight_sql_get_tables_reader.h
flight_sql_get_type_info_reader.cc
flight_sql_get_type_info_reader.h
flight_sql_result_set.cc
flight_sql_result_set.h
flight_sql_result_set_accessors.cc
flight_sql_result_set_accessors.h
flight_sql_result_set_column.cc
flight_sql_result_set_column.h
flight_sql_result_set_metadata.cc
flight_sql_result_set_metadata.h
flight_sql_ssl_config.cc
flight_sql_ssl_config.h
flight_sql_statement.cc
flight_sql_statement.h
flight_sql_statement_get_columns.cc
flight_sql_statement_get_columns.h
flight_sql_statement_get_tables.cc
flight_sql_statement_get_tables.h
flight_sql_statement_get_type_info.cc
flight_sql_statement_get_type_info.h
flight_sql_stream_chunk_buffer.cc
flight_sql_stream_chunk_buffer.h
get_info_cache.cc
get_info_cache.h
json_converter.cc
json_converter.h
record_batch_transformer.cc
record_batch_transformer.h
scalar_function_reporter.cc
scalar_function_reporter.h
system_trust_store.cc
system_trust_store.h
utils.cc)
target_include_directories(arrow_odbc_spi_impl PUBLIC ${CMAKE_CURRENT_LIST_DIR})
if(WIN32)
target_sources(arrow_odbc_spi_impl
include/flight_sql/config/configuration.h
include/flight_sql/config/connection_string_parser.h
include/flight_sql/ui/add_property_window.h
include/flight_sql/ui/custom_window.h
include/flight_sql/ui/dsn_configuration_window.h
include/flight_sql/ui/window.h
config/configuration.cc
config/connection_string_parser.cc
ui/custom_window.cc
ui/window.cc
ui/dsn_configuration_window.cc
ui/add_property_window.cc
system_dsn.cc)
endif()

find_package(ArrowFlightSql)

target_link_libraries(arrow_odbc_spi_impl PUBLIC odbcabstraction
ArrowFlightSql::arrow_flight_sql_static)

if(MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "/MD")
set(CMAKE_CXX_FLAGS_DEBUG "/MDd")
# else
# target_link_libraries(arrow_odbc_spi_impl PUBLIC ArrowFlightSql::arrow_flight_sql_static)
endif()

# set(ARROW_ODBC_SPI_THIRDPARTY_LIBS
# ${ARROW_LIBS} gRPC::grpc++ ${ZLIB_LIBRARIES} ${Protobuf_LIBRARIES}
# ${OPENSSL_LIBRARIES} ${RapidJSON_LIBRARIES})

if(MSVC)
find_package(Boost REQUIRED COMPONENTS locale)
target_link_libraries(arrow_odbc_spi_impl PUBLIC Boost::locale)
endif()

set_target_properties(
arrow_odbc_spi_impl
PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/lib
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/lib
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/lib)

# target_include_directories(arrow_odbc_spi_impl
# PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

# CLI
add_executable(arrow_odbc_spi_impl_cli main.cc)
set_target_properties(
arrow_odbc_spi_impl_cli PROPERTIES RUNTIME_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/$<CONFIG>/bin)
target_link_libraries(arrow_odbc_spi_impl_cli arrow_odbc_spi_impl)

# Unit tests
add_executable(
arrow_odbc_spi_impl_test
accessors/boolean_array_accessor_test.cc
accessors/binary_array_accessor_test.cc
accessors/date_array_accessor_test.cc
accessors/decimal_array_accessor_test.cc
accessors/primitive_array_accessor_test.cc
accessors/string_array_accessor_test.cc
accessors/time_array_accessor_test.cc
accessors/timestamp_array_accessor_test.cc
flight_sql_connection_test.cc
parse_table_types_test.cc
json_converter_test.cc
record_batch_transformer_test.cc
utils_test.cc)

set_target_properties(
arrow_odbc_spi_impl_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/test/$<CONFIG>/bin)
target_link_libraries(arrow_odbc_spi_impl_test arrow_odbc_spi_impl gtest
gtest_main)

add_test(connection_test arrow_odbc_spi_impl_test)
add_test(transformer_test arrow_odbc_spi_impl_test)

add_custom_command(
TARGET arrow_odbc_spi_impl_test
COMMENT "Run tests"
POST_BUILD
COMMAND ${CMAKE_BINARY_DIR}/test/$<CONFIG>/bin/arrow_odbc_spi_impl_test)
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// 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 "binary_array_accessor.h"

#include <arrow/array.h>
#include <algorithm>
#include <cstdint>

namespace driver {
namespace flight_sql {

using namespace arrow;
using namespace odbcabstraction;

namespace {

inline RowStatus MoveSingleCellToBinaryBuffer(ColumnBinding *binding,
BinaryArray *array, int64_t arrow_row, int64_t i,
int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) {
RowStatus result = odbcabstraction::RowStatus_SUCCESS;

const char *value = array->Value(arrow_row).data();
size_t size_in_bytes = array->value_length(arrow_row);

size_t remaining_length = static_cast<size_t>(size_in_bytes - value_offset);
size_t value_length =
std::min(remaining_length,
binding->buffer_length);

auto *byte_buffer = static_cast<unsigned char *>(binding->buffer) +
i * binding->buffer_length;
memcpy(byte_buffer, ((char *)value) + value_offset, value_length);

if (remaining_length > binding->buffer_length) {
result = odbcabstraction::RowStatus_SUCCESS_WITH_INFO;
diagnostics.AddTruncationWarning();
if (update_value_offset) {
value_offset += value_length;
}
} else if (update_value_offset) {
value_offset = -1;
}

if (binding->strlen_buffer) {
binding->strlen_buffer[i] = static_cast<ssize_t>(remaining_length);
}

return result;
}

} // namespace

template <CDataType TARGET_TYPE>
BinaryArrayFlightSqlAccessor<TARGET_TYPE>::BinaryArrayFlightSqlAccessor(
Array *array)
: FlightSqlAccessor<BinaryArray, TARGET_TYPE,
BinaryArrayFlightSqlAccessor<TARGET_TYPE>>(array) {}

template <>
RowStatus BinaryArrayFlightSqlAccessor<CDataType_BINARY>::MoveSingleCell_impl(
ColumnBinding *binding, int64_t arrow_row, int64_t i, int64_t &value_offset,
bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) {
return MoveSingleCellToBinaryBuffer(binding, this->GetArray(), arrow_row, i, value_offset,
update_value_offset, diagnostics);
}

template <CDataType TARGET_TYPE>
size_t BinaryArrayFlightSqlAccessor<TARGET_TYPE>::GetCellLength_impl(ColumnBinding *binding) const {
return binding->buffer_length;
}

template class BinaryArrayFlightSqlAccessor<odbcabstraction::CDataType_BINARY>;

} // namespace flight_sql
} // namespace driver
Loading
Loading