Skip to content

Commit

Permalink
Add Arrow Flight SQL ODBC driver
Browse files Browse the repository at this point in the history
  • Loading branch information
jbonofre committed Oct 6, 2024
1 parent 993a27c commit 9a7edb7
Show file tree
Hide file tree
Showing 132 changed files with 20,259 additions and 0 deletions.
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
# openssl@1.1 # add to the cmake line
# -DOPENSSL_ROOT_DIR=/usr/local/Cellar/openssl@1.1/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/openssl@1.1/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()

dd_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

0 comments on commit 9a7edb7

Please sign in to comment.