From b1a7a68badeb7aa1129a02153c4c1b02ebbce105 Mon Sep 17 00:00:00 2001 From: Ryan Tse Date: Wed, 10 Nov 2021 23:31:12 +0000 Subject: [PATCH 001/183] Initial empty repository From de151d9a670a75b8d2d8c982cb6b1e09e28e31e7 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Thu, 11 Nov 2021 14:16:37 -0300 Subject: [PATCH 002/183] First draft Change-Id: If5a754b5af95075f3788692b8c16d0dcd08b76b7 --- .../flightsql-odbc/.gitignore | 26 +++++++++ .../flightsql-odbc/CMakeLists.txt | 9 +++ .../flightsql-odbc/connection.h | 57 +++++++++++++++++++ .../flightsql-odbc/driver.h | 13 +++++ .../flightsql-odbc/main.cpp | 3 + .../flightsql-odbc/statement.h | 8 +++ 6 files changed, 116 insertions(+) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/statement.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore new file mode 100644 index 0000000000000..826ae2d376038 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore @@ -0,0 +1,26 @@ +thirdparty/*.tar* +CMakeFiles/ +CMakeCache.txt +CTestTestfile.cmake +Makefile +cmake_install.cmake +build/ +*-build/ +Testing/ +build-support/boost_* + +# Build directories created by Clion +cmake-build-*/ + +######################################### +# Editor temporary/working/backup files # +.#* +*\#*\# +[#]*# +*~ +*$ +*.bak +*flymake* +*.kdev4 +*.log +*.swp diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt new file mode 100644 index 0000000000000..ff02008fca988 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.11) +project(flight_odbc_driver) +include(FindODBC) +find_package(Boost) + +set(CMAKE_CXX_STANDARD 11) + +add_executable(flight_odbc_driver main.cpp connection.h driver.h statement.h) +target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES}) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h new file mode 100644 index 0000000000000..8c1e5ca5acc24 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h @@ -0,0 +1,57 @@ +#include +#include +#include +#include "statement.h" + +#pragma once + +class Connection { +public: + enum AttributeId { + // TODO: Add attributes ids + }; + typedef boost::variant Attribute; + typedef boost::variant Property; + + // TODO: Constants for known properties (username, auth) + + /** + * Unified connect method + * + * @param properties[in] + * @param missing_attr[out] + */ + virtual void Connect( + const std::map& properties, + std::vector& missing_attr) = 0; + + /** + * Close this connection + */ + virtual void Close() = 0; + + /** + * Allocates a statement + */ + virtual std::shared_ptr CreateStatement() = 0; + + /** + * Set a connection attribute (may be called at any time) + * @param attribute + * @param value + */ + virtual void SetAttribute(Attribute attribute, const AttributesType& value) = 0; + + /** + * Retrieve a connection attribute + * + * @param attribute + * @return + */ + virtual AttributesType GetAttribute(Attribute attribute) = 0; + + // I feel this method should just return a variant (that can be a string, int32, etc) + // and the wiring layer should be responsible for filling output ODBC buffers. + // Let's not use short, int, etc and use int16_t, int32_t instead. + virtual void GetInfo(uint16_t info_type, void* out, short out_capacity, short* out_length) = 0; +}; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h new file mode 100644 index 0000000000000..e1742617d6d2f --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h @@ -0,0 +1,13 @@ +#include +#include + +#include "connection.h" + +#pragma once + +// Let's make all interfaces have public no-op virtual destructors. +class Driver { +public: + // This should take an ODBC version which can be 2, 3, or 4. + virtual std::shared_ptr CreateConnection() = 0; +}; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp new file mode 100644 index 0000000000000..4cce7f667ff72 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp @@ -0,0 +1,3 @@ +int main() { + return 0; +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/statement.h new file mode 100644 index 0000000000000..46ec1c7a9fa7b --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/statement.h @@ -0,0 +1,8 @@ +#include +#include + +#pragma once + +class Statement { + +}; From a8b10ea5a7c39e960edaf45b7a33af290612c52f Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Thu, 11 Nov 2021 15:35:53 -0300 Subject: [PATCH 003/183] Test new workflow Change-Id: I650e412dd70c4411ca54e707596fdd34312855ff --- .../flightsql-odbc-clone/flightsql-odbc/connection.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h index 8c1e5ca5acc24..ec09d8988a97f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h @@ -54,4 +54,6 @@ class Connection { // and the wiring layer should be responsible for filling output ODBC buffers. // Let's not use short, int, etc and use int16_t, int32_t instead. virtual void GetInfo(uint16_t info_type, void* out, short out_capacity, short* out_length) = 0; + + // Test }; From 9adee62ff5a9f2bc603e38281e653e872ec2d540 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 16 Nov 2021 15:49:13 -0300 Subject: [PATCH 004/183] WIP: Implement connection Change-Id: Ib296b798db88c9226dd5bdd92ea9d219ede1c07c --- .../flightsql-odbc/CMakeLists.txt | 15 +++-- .../flightsql-odbc/connection.h | 48 ++++++++++---- .../flightsql-odbc/driver.h | 1 - .../flight_sql/FlightSqlConnection.cpp | 62 +++++++++++++++++++ .../flight_sql/FlightSqlConnection.h | 27 ++++++++ .../flight_sql/FlightSqlDriver.cpp | 6 ++ .../flight_sql/FlightSqlDriver.h | 8 +++ .../flightsql-odbc/main.cpp | 21 +++++++ .../flightsql-odbc/vcpkg.json | 13 ++++ 9 files changed, 183 insertions(+), 18 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cpp create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index ff02008fca988..3189837032e3f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -1,9 +1,16 @@ cmake_minimum_required(VERSION 3.11) +set(CMAKE_CXX_STANDARD 11) + project(flight_odbc_driver) include(FindODBC) -find_package(Boost) -set(CMAKE_CXX_STANDARD 11) +SET(Arrow_STATIC ON) +find_package(Arrow REQUIRED) +find_package(ArrowFlight REQUIRED PATHS /usr/local/lib/cmake/arrow/) +find_package(ArrowFlightSql REQUIRED PATHS /usr/local/lib/cmake/arrow/) + +message(STATUS "Arrow version: ${ARROW_VERSION}") +message(STATUS "Arrow SO version: ${ARROW_FULL_SO_VERSION}") -add_executable(flight_odbc_driver main.cpp connection.h driver.h statement.h) -target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES}) +add_executable(flight_odbc_driver main.cpp flight_sql/FlightSqlDriver.cpp flight_sql/FlightSqlDriver.h flight_sql/FlightSqlConnection.cpp flight_sql/FlightSqlConnection.h) +target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES} arrow_static arrow_flight arrow_flight_sql) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h index ec09d8988a97f..ac87264ff7a43 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h @@ -8,12 +8,39 @@ class Connection { public: enum AttributeId { - // TODO: Add attributes ids + ACCESS_MODE, + ASYNC_DBC_EVENT, + ASYNC_DBC_FUNCTIONS_ENABLE, + ASYNC_DBC_PCALLBACK, + ASYNC_DBC_PCONTEXT, + ASYNC_ENABLE, + AUTO_IPD, + AUTOCOMMIT, + CONNECTION_DEAD, + CONNECTION_TIMEOUT, + CURRENT_CATALOG, + DBC_INFO_TOKEN, + ENLIST_IN_DTC, + LOGIN_TIMEOUT, + METADATA_ID, + ODBC_CURSORS, + PACKET_SIZE, + QUIET_MODE, + TRACE, + TRACEFILE, + TRANSLATE_LIB, + TRANSLATE_OPTION, + TXN_ISOLATION, }; - typedef boost::variant Attribute; - typedef boost::variant Property; + typedef boost::variant Attribute; + typedef boost::variant Property; + typedef boost::variant Info; - // TODO: Constants for known properties (username, auth) + static const std::string CONNECTION_STRING; + static const std::string HOST; + static const std::string PORT; + static const std::string USERNAME; + static const std::string PASSWORD; /** * Unified connect method @@ -22,7 +49,7 @@ class Connection { * @param missing_attr[out] */ virtual void Connect( - const std::map& properties, + const std::map& properties, std::vector& missing_attr) = 0; /** @@ -40,7 +67,7 @@ class Connection { * @param attribute * @param value */ - virtual void SetAttribute(Attribute attribute, const AttributesType& value) = 0; + virtual void SetAttribute(AttributeId attribute, const Attribute& value) = 0; /** * Retrieve a connection attribute @@ -48,12 +75,7 @@ class Connection { * @param attribute * @return */ - virtual AttributesType GetAttribute(Attribute attribute) = 0; + virtual Attribute GetAttribute(AttributeId attribute) = 0; - // I feel this method should just return a variant (that can be a string, int32, etc) - // and the wiring layer should be responsible for filling output ODBC buffers. - // Let's not use short, int, etc and use int16_t, int32_t instead. - virtual void GetInfo(uint16_t info_type, void* out, short out_capacity, short* out_length) = 0; - - // Test + virtual Info GetInfo(uint16_t info_type) = 0; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h index e1742617d6d2f..99ce97cae0141 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h @@ -1,4 +1,3 @@ -#include #include #include "connection.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp new file mode 100644 index 0000000000000..d47494fc13dbb --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp @@ -0,0 +1,62 @@ +#include "FlightSqlConnection.h" + +using arrow::Status; +using arrow::Result; +using arrow::flight::Location; +using arrow::flight::FlightClient; +using arrow::flight::sql::FlightSqlClient; + +void ThrowIfNotOK(const Status& status) { + if (!status.ok()) { + throw std::runtime_error(status.ToString()); + } +} + +void FlightSqlConnection::Connect(const std::map &properties, + std::vector &missing_attr) { + const std::string &host = boost::get(properties.at("HOST")); + const int &port = boost::get(properties.at("PORT")); + + Location location; + if (properties.count("USE_SSL") && boost::get(properties.at("USE_SSL"))) { + ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); + } else { + ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); + } + + std::unique_ptr client; + ThrowIfNotOK(FlightClient::Connect(location, &client)); + + const std::string &username = boost::get(properties.at("USERNAME")); + const std::string &password = boost::get(properties.at("PASSWORD")); + + if (!username.empty() || !password.empty()) { + Result> bearer_result = + client->AuthenticateBasicToken({}, username, password); + ThrowIfNotOK(bearer_result.status()); + + call_options_.headers.push_back(bearer_result.ValueOrDie()); + } + + client_.reset(new FlightSqlClient(std::move(client))); +} + +void FlightSqlConnection::Close() { + throw std::runtime_error("Close not implemented"); +} + +std::shared_ptr FlightSqlConnection::CreateStatement() { + throw std::runtime_error("CreateStatement not implemented"); +} + +void FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, const Connection::Attribute &value) { + throw std::runtime_error("SetAttribute not implemented"); +} + +Connection::Attribute FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { + throw std::runtime_error("GetAttribute not implemented"); +} + +Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { + throw std::runtime_error("GetInfo not implemented"); +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h new file mode 100644 index 0000000000000..317949493b530 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h @@ -0,0 +1,27 @@ +#pragma once + +#include "../connection.h" +#include +#include + +using arrow::flight::FlightCallOptions; +using arrow::flight::sql::FlightSqlClient; + +class FlightSqlConnection: public Connection { +private: + std::unique_ptr client_; + FlightCallOptions call_options_; + +public: + void Connect(const std::map &properties, std::vector &missing_attr) override; + + void Close() override; + + std::shared_ptr CreateStatement() override; + + void SetAttribute(AttributeId attribute, const Attribute &value) override; + + Attribute GetAttribute(AttributeId attribute) override; + + Info GetInfo(uint16_t info_type) override; +}; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cpp new file mode 100644 index 0000000000000..4ed36500e4e44 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cpp @@ -0,0 +1,6 @@ +#include "FlightSqlDriver.h" +#include "FlightSqlConnection.h" + +std::shared_ptr FlightSqlDriver::CreateConnection() { + return std::make_shared(); +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h new file mode 100644 index 0000000000000..b24e77d8a811d --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h @@ -0,0 +1,8 @@ +#pragma once + +#include "../driver.h" + +class FlightSqlDriver: public Driver { +public: + std::shared_ptr CreateConnection() override; +}; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp index 4cce7f667ff72..dfbe61f901ac4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp @@ -1,3 +1,24 @@ +#include +#include +#include +#include "flight_sql/FlightSqlDriver.h" + +using arrow::Status; +using arrow::flight::Location; +using arrow::flight::FlightClient; +using arrow::flight::sql::FlightSqlClient; + int main() { + FlightSqlDriver driver; + + const std::shared_ptr &connection = driver.CreateConnection(); + + std::vector missing_attr; + std::map properties = { + {"HOST", std::string("0.0.0.0")}, + {"PORT", 31337} + }; + connection->Connect(properties, missing_attr); + return 0; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json new file mode 100644 index 0000000000000..cfd6b144f62c8 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json @@ -0,0 +1,13 @@ +{ + "name": "flightsql-odbc", + "version-string": "1.0.0", + "dependencies": [ + "openssl", + "protobuf", + "zlib", + "re2", + "grpc", + "utf8proc" + ], + "builtin-baseline": "b5865bfeba430cd44063fc54a45a8861195a715f" +} From 452354ea152193e0de79a2973d63c4e02037af7a Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Wed, 17 Nov 2021 14:10:43 -0300 Subject: [PATCH 005/183] Add other properties to Connect() method Change-Id: Ie69e7a923b1f7537193a87102ff08439ee03742e --- .../flightsql-odbc/CMakeLists.txt | 2 +- .../flightsql-odbc/connection.cpp | 7 +++++++ .../flightsql-odbc/connection.h | 2 +- .../flight_sql/FlightSqlConnection.cpp | 21 ++++++++++++------- .../flight_sql/FlightSqlConnection.h | 1 + .../flightsql-odbc/main.cpp | 6 +++--- 6 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cpp diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index 3189837032e3f..5ac9324a0eaa0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -12,5 +12,5 @@ find_package(ArrowFlightSql REQUIRED PATHS /usr/local/lib/cmake/arrow/) message(STATUS "Arrow version: ${ARROW_VERSION}") message(STATUS "Arrow SO version: ${ARROW_FULL_SO_VERSION}") -add_executable(flight_odbc_driver main.cpp flight_sql/FlightSqlDriver.cpp flight_sql/FlightSqlDriver.h flight_sql/FlightSqlConnection.cpp flight_sql/FlightSqlConnection.h) +add_executable(flight_odbc_driver main.cpp connection.cpp flight_sql/FlightSqlDriver.cpp flight_sql/FlightSqlDriver.h flight_sql/FlightSqlConnection.cpp flight_sql/FlightSqlConnection.h) target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES} arrow_static arrow_flight arrow_flight_sql) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cpp new file mode 100644 index 0000000000000..71e9c2e2993d3 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cpp @@ -0,0 +1,7 @@ +#include "connection.h" + +const std::string Connection::HOST = "HOST"; +const std::string Connection::PORT = "PORT"; +const std::string Connection::USERNAME = "USERNAME"; +const std::string Connection::PASSWORD = "PASSWORD"; +const std::string Connection::USE_SSL = "USE_SSL"; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h index ac87264ff7a43..abcee11ce8dcd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h @@ -36,11 +36,11 @@ class Connection { typedef boost::variant Property; typedef boost::variant Info; - static const std::string CONNECTION_STRING; static const std::string HOST; static const std::string PORT; static const std::string USERNAME; static const std::string PASSWORD; + static const std::string USE_SSL; /** * Unified connect method diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp index d47494fc13dbb..1d9044e0ff6f1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp @@ -6,7 +6,7 @@ using arrow::flight::Location; using arrow::flight::FlightClient; using arrow::flight::sql::FlightSqlClient; -void ThrowIfNotOK(const Status& status) { +inline void ThrowIfNotOK(const Status &status) { if (!status.ok()) { throw std::runtime_error(status.ToString()); } @@ -14,11 +14,11 @@ void ThrowIfNotOK(const Status& status) { void FlightSqlConnection::Connect(const std::map &properties, std::vector &missing_attr) { - const std::string &host = boost::get(properties.at("HOST")); - const int &port = boost::get(properties.at("PORT")); + const std::string &host = boost::get(properties.at(Connection::HOST)); + const int &port = boost::get(properties.at(Connection::PORT)); Location location; - if (properties.count("USE_SSL") && boost::get(properties.at("USE_SSL"))) { + if (properties.count("USE_SSL") && boost::get(properties.at(Connection::USE_SSL))) { ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); } else { ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); @@ -27,8 +27,10 @@ void FlightSqlConnection::Connect(const std::map &propert std::unique_ptr client; ThrowIfNotOK(FlightClient::Connect(location, &client)); - const std::string &username = boost::get(properties.at("USERNAME")); - const std::string &password = boost::get(properties.at("PASSWORD")); + const std::string &username = properties.count(Connection::USERNAME) ? boost::get( + properties.at(Connection::USERNAME)) : ""; + const std::string &password = properties.count(Connection::PASSWORD) ? boost::get( + properties.at(Connection::PASSWORD)) : ""; if (!username.empty() || !password.empty()) { Result> bearer_result = @@ -42,7 +44,12 @@ void FlightSqlConnection::Connect(const std::map &propert } void FlightSqlConnection::Close() { - throw std::runtime_error("Close not implemented"); + if (closed_) { + throw std::runtime_error("Connection already closed."); + } + + client_.reset(); + closed_ = true; } std::shared_ptr FlightSqlConnection::CreateStatement() { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h index 317949493b530..a7a51da3ab416 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h @@ -11,6 +11,7 @@ class FlightSqlConnection: public Connection { private: std::unique_ptr client_; FlightCallOptions call_options_; + bool closed_; public: void Connect(const std::map &properties, std::vector &missing_attr) override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp index dfbe61f901ac4..46e54d0af9c54 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp @@ -13,11 +13,11 @@ int main() { const std::shared_ptr &connection = driver.CreateConnection(); - std::vector missing_attr; std::map properties = { - {"HOST", std::string("0.0.0.0")}, - {"PORT", 31337} + {Connection::HOST, std::string("0.0.0.0")}, + {Connection::PORT, 31337}, }; + std::vector missing_attr; connection->Connect(properties, missing_attr); return 0; From a3461cc4267e8c43166a2fbfcf153218a4f1cb67 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Wed, 17 Nov 2021 14:12:20 -0300 Subject: [PATCH 006/183] Add Attribuite methods and test class Change-Id: I9f2e86b6addbf72453e6d7473c646d03ef0a8e5f --- .../flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt | 5 ++++- .../flightsql-odbc/flight_sql/FlightConnectionTest.cpp | 0 .../flightsql-odbc/flight_sql/FlightSqlConnection.cpp | 4 ++-- .../flightsql-odbc/flight_sql/FlightSqlConnection.h | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index 5ac9324a0eaa0..8c1172c70eb0e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -12,5 +12,8 @@ find_package(ArrowFlightSql REQUIRED PATHS /usr/local/lib/cmake/arrow/) message(STATUS "Arrow version: ${ARROW_VERSION}") message(STATUS "Arrow SO version: ${ARROW_FULL_SO_VERSION}") -add_executable(flight_odbc_driver main.cpp connection.cpp flight_sql/FlightSqlDriver.cpp flight_sql/FlightSqlDriver.h flight_sql/FlightSqlConnection.cpp flight_sql/FlightSqlConnection.h) +add_executable(flight_odbc_driver main.cpp + connection.cpp flight_sql/FlightSqlDriver.cpp flight_sql/FlightSqlDriver.h + flight_sql/FlightSqlConnection.cpp flight_sql/FlightSqlConnection.h + flight_sql/FlightConnectionTest.cpp) target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES} arrow_static arrow_flight arrow_flight_sql) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp index 1d9044e0ff6f1..2081aa588ad72 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp @@ -57,11 +57,11 @@ std::shared_ptr FlightSqlConnection::CreateStatement() { } void FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, const Connection::Attribute &value) { - throw std::runtime_error("SetAttribute not implemented"); + attribute_.insert({attribute, value}); } Connection::Attribute FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { - throw std::runtime_error("GetAttribute not implemented"); + return attribute_.find(attribute) -> second; } Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h index a7a51da3ab416..14b4661f6702e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h @@ -12,6 +12,7 @@ class FlightSqlConnection: public Connection { std::unique_ptr client_; FlightCallOptions call_options_; bool closed_; + std::map attribute_; public: void Connect(const std::map &properties, std::vector &missing_attr) override; From 2be757e42154aa2e14b773f7cbc74e6fb9b62bf0 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Wed, 17 Nov 2021 14:34:44 -0300 Subject: [PATCH 007/183] Add gtest to cmake and vcpkg Change-Id: Ibb0310650bfb2434b762fcf351e905920f3ffc56 --- .../flightsql-odbc/CMakeLists.txt | 14 +++++++++++--- .../flightsql-odbc-clone/flightsql-odbc/vcpkg.json | 3 ++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index 8c1172c70eb0e..81661133c78d1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -9,11 +9,19 @@ find_package(Arrow REQUIRED) find_package(ArrowFlight REQUIRED PATHS /usr/local/lib/cmake/arrow/) find_package(ArrowFlightSql REQUIRED PATHS /usr/local/lib/cmake/arrow/) +enable_testing() +find_package(GTest REQUIRED) + message(STATUS "Arrow version: ${ARROW_VERSION}") message(STATUS "Arrow SO version: ${ARROW_FULL_SO_VERSION}") add_executable(flight_odbc_driver main.cpp connection.cpp flight_sql/FlightSqlDriver.cpp flight_sql/FlightSqlDriver.h - flight_sql/FlightSqlConnection.cpp flight_sql/FlightSqlConnection.h - flight_sql/FlightConnectionTest.cpp) -target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES} arrow_static arrow_flight arrow_flight_sql) + flight_sql/FlightSqlConnection.cpp flight_sql/FlightSqlConnection.h) +target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES} arrow_static arrow_flight arrow_flight_sql ) + +add_executable(odbc_test flight_sql/FlightConnectionTest.cpp) + +target_link_libraries(odbc_test GTest::gtest GTest::gtest_main) + +add_test(connection_test odbc_test) \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json index cfd6b144f62c8..ba9d3f088cd5d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json @@ -7,7 +7,8 @@ "zlib", "re2", "grpc", - "utf8proc" + "utf8proc", + "gtest" ], "builtin-baseline": "b5865bfeba430cd44063fc54a45a8861195a715f" } From 43934d4089e01967f72829d3efa289e04e92609e Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Wed, 17 Nov 2021 14:35:05 -0300 Subject: [PATCH 008/183] Test template Change-Id: I08777349c0182bab017ae090a291081a9d8f469e --- .../flightsql-odbc/flight_sql/FlightConnectionTest.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp index e69de29bb2d1d..b4ea869902753 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp @@ -0,0 +1,7 @@ + + +#include "gtest/gtest.h" + +TEST(test1, test1) { + EXPECT_EQ(1, 1); +} \ No newline at end of file From d64c5b3a63022706d646d784884a2b1385e3bc8f Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Wed, 17 Nov 2021 14:49:13 -0300 Subject: [PATCH 009/183] Add vcpkg_installed and .idea to .gitignore Change-Id: Icf9530bac762426d636c9a5988ff882fa3cafd87 --- .../flightsql-odbc-clone/flightsql-odbc/.gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore index 826ae2d376038..c8c0f0a42c1e5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore @@ -24,3 +24,6 @@ cmake-build-*/ *.kdev4 *.log *.swp + +.idea +vcpkg_installed From 05d5430e5ec996f83f72e5e7a12b623f021765bc Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Thu, 18 Nov 2021 13:27:22 -0300 Subject: [PATCH 010/183] Fix get and setAttrubute and add a couple of test case Change-Id: Ia3435a1336f4057e4d2f90429df5a086d596c765 --- .../flightsql-odbc/CMakeLists.txt | 5 +-- .../flightsql-odbc/connection.h | 3 +- .../flight_sql/FlightConnectionTest.cpp | 36 +++++++++++++++++-- .../flight_sql/FlightSqlConnection.cpp | 8 +++-- .../flight_sql/FlightSqlConnection.h | 2 +- 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index 81661133c78d1..a99fa8d8372d2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -20,8 +20,9 @@ add_executable(flight_odbc_driver main.cpp flight_sql/FlightSqlConnection.cpp flight_sql/FlightSqlConnection.h) target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES} arrow_static arrow_flight arrow_flight_sql ) -add_executable(odbc_test flight_sql/FlightConnectionTest.cpp) +add_executable(odbc_test connection.cpp flight_sql/FlightConnectionTest.cpp flight_sql/FlightSqlDriver.cpp flight_sql/FlightSqlDriver.h + flight_sql/FlightSqlConnection.cpp) -target_link_libraries(odbc_test GTest::gtest GTest::gtest_main) +target_link_libraries(odbc_test GTest::gtest GTest::gtest_main arrow_static arrow_flight arrow_flight_sql) add_test(connection_test odbc_test) \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h index abcee11ce8dcd..5919180e0f2c3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h @@ -1,6 +1,7 @@ #include #include #include +#include #include "statement.h" #pragma once @@ -75,7 +76,7 @@ class Connection { * @param attribute * @return */ - virtual Attribute GetAttribute(AttributeId attribute) = 0; + virtual boost::optional GetAttribute(Connection::AttributeId attribute) = 0; virtual Info GetInfo(uint16_t info_type) = 0; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp index b4ea869902753..3f34a47281b85 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp @@ -1,7 +1,37 @@ +#include "gtest/gtest.h" +#include "FlightSqlDriver.h" +TEST(AttributeTests, SetAndGetAttribute) { + FlightSqlDriver driver; -#include "gtest/gtest.h" + const std::shared_ptr &connection = driver.CreateConnection(); + + connection->SetAttribute(Connection::CONNECTION_TIMEOUT, 200); + const boost::optional firstValue = connection->GetAttribute( + Connection::CONNECTION_TIMEOUT); + + EXPECT_TRUE(firstValue.has_value()); + + EXPECT_EQ(boost::get(firstValue.value()), 200); + + connection->SetAttribute(Connection::CONNECTION_TIMEOUT, 300); + + const boost::optional changeValue = connection->GetAttribute( + Connection::CONNECTION_TIMEOUT); + + EXPECT_TRUE(changeValue.has_value()); + EXPECT_EQ(boost::get(changeValue.value()), 300); +} + +TEST(AttributeTests, GetAttributeWithoutSetting) { + FlightSqlDriver driver; + + const std::shared_ptr &connection = driver.CreateConnection(); + + const boost::optional anOptional = connection->GetAttribute( + Connection::CONNECTION_TIMEOUT); + + bool b = anOptional.has_value(); -TEST(test1, test1) { - EXPECT_EQ(1, 1); + EXPECT_FALSE(b); } \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp index 2081aa588ad72..1c7e6e485d258 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp @@ -1,4 +1,5 @@ #include "FlightSqlConnection.h" +#include using arrow::Status; using arrow::Result; @@ -57,11 +58,12 @@ std::shared_ptr FlightSqlConnection::CreateStatement() { } void FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, const Connection::Attribute &value) { - attribute_.insert({attribute, value}); + attribute_[attribute] = value; } -Connection::Attribute FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { - return attribute_.find(attribute) -> second; +boost::optional +FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { + return boost::make_optional(attribute_.count(attribute), attribute_.find(attribute) -> second); } Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h index 14b4661f6702e..ca641fd89eb92 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h @@ -23,7 +23,7 @@ class FlightSqlConnection: public Connection { void SetAttribute(AttributeId attribute, const Attribute &value) override; - Attribute GetAttribute(AttributeId attribute) override; + boost::optional GetAttribute(Connection::AttributeId attribute) override; Info GetInfo(uint16_t info_type) override; }; From 6edc9de45e2bab23bb375b25455287e4551c72d1 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Thu, 18 Nov 2021 14:52:40 -0300 Subject: [PATCH 011/183] Add comments and rename files from .cpp to .cc Change-Id: I4ddba924f1e62c3e6699150593fd6f5a37e5b98a --- .../flightsql-odbc/CMakeLists.txt | 10 +-- .../{connection.cpp => connection.cc} | 0 .../flightsql-odbc/connection.h | 71 +++++++++++-------- .../flightsql-odbc/driver.h | 5 ++ ...ectionTest.cpp => FlightConnectionTest.cc} | 14 ++-- ...lConnection.cpp => FlightSqlConnection.cc} | 37 ++++++---- .../flight_sql/FlightSqlConnection.h | 8 ++- ...FlightSqlDriver.cpp => FlightSqlDriver.cc} | 0 .../flight_sql/FlightSqlDriver.h | 2 +- .../flightsql-odbc/{main.cpp => main.cc} | 10 +-- .../flightsql-odbc/statement.h | 4 +- 11 files changed, 93 insertions(+), 68 deletions(-) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{connection.cpp => connection.cc} (100%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/{FlightConnectionTest.cpp => FlightConnectionTest.cc} (66%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/{FlightSqlConnection.cpp => FlightSqlConnection.cc} (61%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/{FlightSqlDriver.cpp => FlightSqlDriver.cc} (100%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{main.cpp => main.cc} (85%) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index a99fa8d8372d2..fbfa1fd4a10ef 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -15,13 +15,13 @@ find_package(GTest REQUIRED) message(STATUS "Arrow version: ${ARROW_VERSION}") message(STATUS "Arrow SO version: ${ARROW_FULL_SO_VERSION}") -add_executable(flight_odbc_driver main.cpp - connection.cpp flight_sql/FlightSqlDriver.cpp flight_sql/FlightSqlDriver.h - flight_sql/FlightSqlConnection.cpp flight_sql/FlightSqlConnection.h) +add_executable(flight_odbc_driver main.cc + connection.cc flight_sql/FlightSqlDriver.cc flight_sql/FlightSqlDriver.h + flight_sql/FlightSqlConnection.cc flight_sql/FlightSqlConnection.h) target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES} arrow_static arrow_flight arrow_flight_sql ) -add_executable(odbc_test connection.cpp flight_sql/FlightConnectionTest.cpp flight_sql/FlightSqlDriver.cpp flight_sql/FlightSqlDriver.h - flight_sql/FlightSqlConnection.cpp) +add_executable(odbc_test connection.cc flight_sql/FlightConnectionTest.cc flight_sql/FlightSqlDriver.cc flight_sql/FlightSqlDriver.h + flight_sql/FlightSqlConnection.cc) target_link_libraries(odbc_test GTest::gtest GTest::gtest_main arrow_static arrow_flight arrow_flight_sql) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cc similarity index 100% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cpp rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h index 5919180e0f2c3..260e2fe9802c5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h @@ -1,38 +1,43 @@ +#include "statement.h" +#include +#include #include #include -#include -#include -#include "statement.h" #pragma once class Connection { public: enum AttributeId { - ACCESS_MODE, - ASYNC_DBC_EVENT, - ASYNC_DBC_FUNCTIONS_ENABLE, - ASYNC_DBC_PCALLBACK, - ASYNC_DBC_PCONTEXT, - ASYNC_ENABLE, - AUTO_IPD, - AUTOCOMMIT, - CONNECTION_DEAD, - CONNECTION_TIMEOUT, - CURRENT_CATALOG, - DBC_INFO_TOKEN, - ENLIST_IN_DTC, - LOGIN_TIMEOUT, - METADATA_ID, - ODBC_CURSORS, - PACKET_SIZE, - QUIET_MODE, - TRACE, - TRACEFILE, - TRANSLATE_LIB, - TRANSLATE_OPTION, - TXN_ISOLATION, + ACCESS_MODE, // Writable attribute, tells if it should support write + // operations + ASYNC_DBC_EVENT, // Do not support async yet + ASYNC_DBC_FUNCTIONS_ENABLE, // Do not support async yet + ASYNC_DBC_PCALLBACK, // Do not support async yet + ASYNC_DBC_PCONTEXT, // Do not support async yet + ASYNC_ENABLE, // Do not support async yet + AUTO_IPD, // Relevant to parameter binding on statements + AUTOCOMMIT, // Do not support transactions yet + CONNECTION_DEAD, // Tells if connection is still alive + CONNECTION_TIMEOUT, // Matters to Connect() + CURRENT_CATALOG, // DO not support at first - Instead of passing catalog as + // argument, rely on this attribute + DBC_INFO_TOKEN, // lookup + ENLIST_IN_DTC, // Do not support + LOGIN_TIMEOUT, // Matters to Connect() + METADATA_ID, // Pass to statement + // ODBC_CURSORS, // Internal + PACKET_SIZE, // Lookup if there is a packet size on Flight + QUIET_MODE, // lookup + // TRACE, + // TRACEFILE, + // TRANSLATE_LIB, + // TRANSLATE_OPTION, + TXN_ISOLATION, // Do not support transactions yet }; + + enum OdbcVersion { V_2, V_3, V_4 }; + typedef boost::variant Attribute; typedef boost::variant Property; typedef boost::variant Info; @@ -42,6 +47,10 @@ class Connection { static const std::string USERNAME; static const std::string PASSWORD; static const std::string USE_SSL; + // Add properties for getting the certificates + // Check if gRPC can use the system truststore, if not copy from Drill + + Connection(OdbcVersion odbc_version) {} /** * Unified connect method @@ -49,9 +58,8 @@ class Connection { * @param properties[in] * @param missing_attr[out] */ - virtual void Connect( - const std::map& properties, - std::vector& missing_attr) = 0; + virtual void Connect(const std::map &properties, + std::vector &missing_attr) = 0; /** * Close this connection @@ -68,7 +76,7 @@ class Connection { * @param attribute * @param value */ - virtual void SetAttribute(AttributeId attribute, const Attribute& value) = 0; + virtual void SetAttribute(AttributeId attribute, const Attribute &value) = 0; /** * Retrieve a connection attribute @@ -76,7 +84,8 @@ class Connection { * @param attribute * @return */ - virtual boost::optional GetAttribute(Connection::AttributeId attribute) = 0; + virtual boost::optional + GetAttribute(Connection::AttributeId attribute) = 0; virtual Info GetInfo(uint16_t info_type) = 0; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h index 99ce97cae0141..f54dba1431fcb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h @@ -7,6 +7,11 @@ // Let's make all interfaces have public no-op virtual destructors. class Driver { public: + virtual ~Driver() = default; + // This should take an ODBC version which can be 2, 3, or 4. virtual std::shared_ptr CreateConnection() = 0; + +protected: + Driver() = default; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cc similarity index 66% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cc index 3f34a47281b85..e9edd5a9fb152 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cpp +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cc @@ -1,5 +1,5 @@ -#include "gtest/gtest.h" #include "FlightSqlDriver.h" +#include "gtest/gtest.h" TEST(AttributeTests, SetAndGetAttribute) { FlightSqlDriver driver; @@ -7,8 +7,8 @@ TEST(AttributeTests, SetAndGetAttribute) { const std::shared_ptr &connection = driver.CreateConnection(); connection->SetAttribute(Connection::CONNECTION_TIMEOUT, 200); - const boost::optional firstValue = connection->GetAttribute( - Connection::CONNECTION_TIMEOUT); + const boost::optional firstValue = + connection->GetAttribute(Connection::CONNECTION_TIMEOUT); EXPECT_TRUE(firstValue.has_value()); @@ -16,8 +16,8 @@ TEST(AttributeTests, SetAndGetAttribute) { connection->SetAttribute(Connection::CONNECTION_TIMEOUT, 300); - const boost::optional changeValue = connection->GetAttribute( - Connection::CONNECTION_TIMEOUT); + const boost::optional changeValue = + connection->GetAttribute(Connection::CONNECTION_TIMEOUT); EXPECT_TRUE(changeValue.has_value()); EXPECT_EQ(boost::get(changeValue.value()), 300); @@ -28,8 +28,8 @@ TEST(AttributeTests, GetAttributeWithoutSetting) { const std::shared_ptr &connection = driver.CreateConnection(); - const boost::optional anOptional = connection->GetAttribute( - Connection::CONNECTION_TIMEOUT); + const boost::optional anOptional = + connection->GetAttribute(Connection::CONNECTION_TIMEOUT); bool b = anOptional.has_value(); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cc similarity index 61% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cc index 1c7e6e485d258..2ae5bc4b7699a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cpp +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cc @@ -1,10 +1,10 @@ #include "FlightSqlConnection.h" #include -using arrow::Status; using arrow::Result; -using arrow::flight::Location; +using arrow::Status; using arrow::flight::FlightClient; +using arrow::flight::Location; using arrow::flight::sql::FlightSqlClient; inline void ThrowIfNotOK(const Status &status) { @@ -13,29 +13,38 @@ inline void ThrowIfNotOK(const Status &status) { } } -void FlightSqlConnection::Connect(const std::map &properties, - std::vector &missing_attr) { - const std::string &host = boost::get(properties.at(Connection::HOST)); +void FlightSqlConnection::Connect( + const std::map &properties, + std::vector &missing_attr) { + const std::string &host = + boost::get(properties.at(Connection::HOST)); const int &port = boost::get(properties.at(Connection::PORT)); Location location; - if (properties.count("USE_SSL") && boost::get(properties.at(Connection::USE_SSL))) { + if (properties.count("USE_SSL") && + boost::get(properties.at(Connection::USE_SSL))) { ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); } else { ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); } std::unique_ptr client; + + // TODO: Use timeout from attributes ThrowIfNotOK(FlightClient::Connect(location, &client)); - const std::string &username = properties.count(Connection::USERNAME) ? boost::get( - properties.at(Connection::USERNAME)) : ""; - const std::string &password = properties.count(Connection::PASSWORD) ? boost::get( - properties.at(Connection::PASSWORD)) : ""; + const std::string &username = + properties.count(Connection::USERNAME) + ? boost::get(properties.at(Connection::USERNAME)) + : ""; + const std::string &password = + properties.count(Connection::PASSWORD) + ? boost::get(properties.at(Connection::PASSWORD)) + : ""; if (!username.empty() || !password.empty()) { Result> bearer_result = - client->AuthenticateBasicToken({}, username, password); + client->AuthenticateBasicToken({}, username, password); ThrowIfNotOK(bearer_result.status()); call_options_.headers.push_back(bearer_result.ValueOrDie()); @@ -57,13 +66,15 @@ std::shared_ptr FlightSqlConnection::CreateStatement() { throw std::runtime_error("CreateStatement not implemented"); } -void FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, const Connection::Attribute &value) { +void FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, + const Connection::Attribute &value) { attribute_[attribute] = value; } boost::optional FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { - return boost::make_optional(attribute_.count(attribute), attribute_.find(attribute) -> second); + return boost::make_optional(attribute_.count(attribute), + attribute_.find(attribute)->second); } Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h index ca641fd89eb92..b90e0e0405ba5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h @@ -7,7 +7,7 @@ using arrow::flight::FlightCallOptions; using arrow::flight::sql::FlightSqlClient; -class FlightSqlConnection: public Connection { +class FlightSqlConnection : public Connection { private: std::unique_ptr client_; FlightCallOptions call_options_; @@ -15,7 +15,8 @@ class FlightSqlConnection: public Connection { std::map attribute_; public: - void Connect(const std::map &properties, std::vector &missing_attr) override; + void Connect(const std::map &properties, + std::vector &missing_attr) override; void Close() override; @@ -23,7 +24,8 @@ class FlightSqlConnection: public Connection { void SetAttribute(AttributeId attribute, const Attribute &value) override; - boost::optional GetAttribute(Connection::AttributeId attribute) override; + boost::optional + GetAttribute(Connection::AttributeId attribute) override; Info GetInfo(uint16_t info_type) override; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cc similarity index 100% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cpp rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h index b24e77d8a811d..1954aae89c880 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h @@ -2,7 +2,7 @@ #include "../driver.h" -class FlightSqlDriver: public Driver { +class FlightSqlDriver : public Driver { public: std::shared_ptr CreateConnection() override; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cc similarity index 85% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cc index 46e54d0af9c54..36a454be4b355 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cpp +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cc @@ -1,11 +1,11 @@ -#include +#include "flight_sql/FlightSqlDriver.h" #include #include -#include "flight_sql/FlightSqlDriver.h" +#include using arrow::Status; -using arrow::flight::Location; using arrow::flight::FlightClient; +using arrow::flight::Location; using arrow::flight::sql::FlightSqlClient; int main() { @@ -14,8 +14,8 @@ int main() { const std::shared_ptr &connection = driver.CreateConnection(); std::map properties = { - {Connection::HOST, std::string("0.0.0.0")}, - {Connection::PORT, 31337}, + {Connection::HOST, std::string("0.0.0.0")}, + {Connection::PORT, 31337}, }; std::vector missing_attr; connection->Connect(properties, missing_attr); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/statement.h index 46ec1c7a9fa7b..1a94dd053d919 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/statement.h @@ -3,6 +3,4 @@ #pragma once -class Statement { - -}; +class Statement {}; From 415c12b057029511d61f6651ea57ffcb8b5f17de Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Thu, 18 Nov 2021 16:26:49 -0300 Subject: [PATCH 012/183] Create new cmakelist for subdirectory flight-sql Change-Id: I0e7e0cc66bc49c95e51d5bd1b868b8a928f87cab --- .../flightsql-odbc/CMakeLists.txt | 15 ++++----------- .../flightsql-odbc/connection.h | 2 -- .../flightsql-odbc/flight_sql/CMakeLists.txt | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 13 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index fbfa1fd4a10ef..f50967cd553fd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -9,20 +9,13 @@ find_package(Arrow REQUIRED) find_package(ArrowFlight REQUIRED PATHS /usr/local/lib/cmake/arrow/) find_package(ArrowFlightSql REQUIRED PATHS /usr/local/lib/cmake/arrow/) -enable_testing() find_package(GTest REQUIRED) message(STATUS "Arrow version: ${ARROW_VERSION}") message(STATUS "Arrow SO version: ${ARROW_FULL_SO_VERSION}") -add_executable(flight_odbc_driver main.cc - connection.cc flight_sql/FlightSqlDriver.cc flight_sql/FlightSqlDriver.h - flight_sql/FlightSqlConnection.cc flight_sql/FlightSqlConnection.h) -target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES} arrow_static arrow_flight arrow_flight_sql ) - -add_executable(odbc_test connection.cc flight_sql/FlightConnectionTest.cc flight_sql/FlightSqlDriver.cc flight_sql/FlightSqlDriver.h - flight_sql/FlightSqlConnection.cc) +add_subdirectory(flight_sql) -target_link_libraries(odbc_test GTest::gtest GTest::gtest_main arrow_static arrow_flight arrow_flight_sql) - -add_test(connection_test odbc_test) \ No newline at end of file +add_executable(flight_odbc_driver main.cc + connection.cc ) +target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES} arrow_static arrow_flight arrow_flight_sql ) \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h index 260e2fe9802c5..e47cb847dd2a9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h @@ -50,8 +50,6 @@ class Connection { // Add properties for getting the certificates // Check if gRPC can use the system truststore, if not copy from Drill - Connection(OdbcVersion odbc_version) {} - /** * Unified connect method * diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt new file mode 100644 index 0000000000000..d07a54a60725e --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.11) +set(CMAKE_CXX_STANDARD 11) + +enable_testing() +add_executable(odbc_flight_sql FlightSqlDriver.cc FlightSqlDriver.h + FlightSqlConnection.cc FlightSqlConnection.h) + +target_include_directories(odbc_flight_sql PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +add_executable(odbc_test ../connection.cc FlightConnectionTest.cc FlightSqlDriver.cc FlightSqlDriver.h + FlightSqlConnection.cc) + +target_link_libraries(odbc_test GTest::gtest GTest::gtest_main arrow_static arrow_flight arrow_flight_sql) + +add_test(connection_test odbc_test) \ No newline at end of file From 6d3b3776568a1c6ea076ed77284a24ff3209d67c Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Fri, 19 Nov 2021 11:12:24 -0300 Subject: [PATCH 013/183] Create new cmakelist for subdirectory flight-sql Change-Id: I8ef552895ead2c90c7bae1dd31537f8b7fef415c --- .../flightsql-odbc/CMakeLists.txt | 12 ++---------- .../flightsql-odbc/flight_sql/CMakeLists.txt | 16 ++++++++++++---- .../flightsql-odbc/{ => flight_sql}/main.cc | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{ => flight_sql}/main.cc (93%) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index f50967cd553fd..584b5ccf909b0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -4,18 +4,10 @@ set(CMAKE_CXX_STANDARD 11) project(flight_odbc_driver) include(FindODBC) -SET(Arrow_STATIC ON) -find_package(Arrow REQUIRED) -find_package(ArrowFlight REQUIRED PATHS /usr/local/lib/cmake/arrow/) -find_package(ArrowFlightSql REQUIRED PATHS /usr/local/lib/cmake/arrow/) - -find_package(GTest REQUIRED) - message(STATUS "Arrow version: ${ARROW_VERSION}") message(STATUS "Arrow SO version: ${ARROW_FULL_SO_VERSION}") add_subdirectory(flight_sql) -add_executable(flight_odbc_driver main.cc - connection.cc ) -target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES} arrow_static arrow_flight arrow_flight_sql ) \ No newline at end of file +add_library(flight_odbc_driver connection.cc) +target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES}) \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index d07a54a60725e..5929e03965492 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -1,15 +1,23 @@ cmake_minimum_required(VERSION 3.11) set(CMAKE_CXX_STANDARD 11) +SET(Arrow_STATIC ON) +find_package(Arrow REQUIRED) +find_package(ArrowFlight REQUIRED PATHS /usr/local/lib/cmake/arrow/) +find_package(ArrowFlightSql REQUIRED PATHS /usr/local/lib/cmake/arrow/) +find_package(GTest REQUIRED) + enable_testing() -add_executable(odbc_flight_sql FlightSqlDriver.cc FlightSqlDriver.h +add_executable(sql_moduler main.cc FlightSqlDriver.cc FlightSqlDriver.h FlightSqlConnection.cc FlightSqlConnection.h) -target_include_directories(odbc_flight_sql PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(sql_moduler flight_odbc_driver arrow_static arrow_flight arrow_flight_sql) + +target_include_directories(sql_moduler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -add_executable(odbc_test ../connection.cc FlightConnectionTest.cc FlightSqlDriver.cc FlightSqlDriver.h +add_executable(odbc_test FlightConnectionTest.cc FlightSqlDriver.cc FlightSqlDriver.h FlightSqlConnection.cc) -target_link_libraries(odbc_test GTest::gtest GTest::gtest_main arrow_static arrow_flight arrow_flight_sql) +target_link_libraries(odbc_test flight_odbc_driver GTest::gtest GTest::gtest_main arrow_static arrow_flight arrow_flight_sql) add_test(connection_test odbc_test) \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc similarity index 93% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cc rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 36a454be4b355..092e2b3c7df7e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -1,4 +1,4 @@ -#include "flight_sql/FlightSqlDriver.h" +#include "FlightSqlDriver.h" #include #include #include From 4c40d3e847c8705c07150f02c2d3bcc36cddb8f1 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Fri, 19 Nov 2021 13:26:45 -0300 Subject: [PATCH 014/183] WIP: Implement Connect Change-Id: Ic9859ec87c330ff7995ee5deba1f874b77082de1 --- .../flightsql-odbc/CMakeLists.txt | 9 +-- .../flightsql-odbc/connection.cc | 5 +- .../flightsql-odbc/connection.h | 13 ++-- .../flightsql-odbc/driver.h | 6 +- .../flight_sql/FlightSqlConnection.cc | 67 +++++++++++-------- .../flight_sql/FlightSqlConnection.h | 8 +++ .../flight_sql/FlightSqlDriver.cc | 5 +- .../flight_sql/FlightSqlDriver.h | 3 +- .../flight_sql/flight_sql_auth_method.cc | 63 +++++++++++++++++ .../flight_sql/flight_sql_auth_method.h | 21 ++++++ .../flightsql-odbc/main.cc | 6 +- .../flightsql-odbc/types.h | 3 + 12 files changed, 162 insertions(+), 47 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/types.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index fbfa1fd4a10ef..8bd08277297db 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -16,12 +16,13 @@ message(STATUS "Arrow version: ${ARROW_VERSION}") message(STATUS "Arrow SO version: ${ARROW_FULL_SO_VERSION}") add_executable(flight_odbc_driver main.cc - connection.cc flight_sql/FlightSqlDriver.cc flight_sql/FlightSqlDriver.h - flight_sql/FlightSqlConnection.cc flight_sql/FlightSqlConnection.h) + connection.cc flight_sql/FlightSqlDriver.cc + flight_sql/FlightSqlConnection.cc + flight_sql/flight_sql_auth_method.cc) target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES} arrow_static arrow_flight arrow_flight_sql ) -add_executable(odbc_test connection.cc flight_sql/FlightConnectionTest.cc flight_sql/FlightSqlDriver.cc flight_sql/FlightSqlDriver.h - flight_sql/FlightSqlConnection.cc) +add_executable(odbc_test connection.cc flight_sql/FlightConnectionTest.cc flight_sql/FlightSqlDriver.cc + flight_sql/FlightSqlConnection.cc flight_sql/flight_sql_auth_method.cc) target_link_libraries(odbc_test GTest::gtest GTest::gtest_main arrow_static arrow_flight arrow_flight_sql) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cc index 71e9c2e2993d3..d87fec1add8c0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cc @@ -2,6 +2,9 @@ const std::string Connection::HOST = "HOST"; const std::string Connection::PORT = "PORT"; -const std::string Connection::USERNAME = "USERNAME"; +const std::string Connection::USER = "USER"; const std::string Connection::PASSWORD = "PASSWORD"; const std::string Connection::USE_SSL = "USE_SSL"; + +Connection::Connection(OdbcVersion odbc_version) + : odbc_version_(odbc_version) {} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h index 260e2fe9802c5..6dd24fff4aea8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h @@ -4,6 +4,8 @@ #include #include +#include "types.h" + #pragma once class Connection { @@ -36,21 +38,19 @@ class Connection { TXN_ISOLATION, // Do not support transactions yet }; - enum OdbcVersion { V_2, V_3, V_4 }; - - typedef boost::variant Attribute; + typedef boost::variant Attribute; typedef boost::variant Property; typedef boost::variant Info; static const std::string HOST; static const std::string PORT; - static const std::string USERNAME; + static const std::string USER; static const std::string PASSWORD; static const std::string USE_SSL; // Add properties for getting the certificates // Check if gRPC can use the system truststore, if not copy from Drill - Connection(OdbcVersion odbc_version) {} + Connection(OdbcVersion odbc_version); /** * Unified connect method @@ -88,4 +88,7 @@ class Connection { GetAttribute(Connection::AttributeId attribute) = 0; virtual Info GetInfo(uint16_t info_type) = 0; + +private: + OdbcVersion odbc_version_; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h index f54dba1431fcb..2c4e176c0081e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h @@ -1,16 +1,16 @@ #include #include "connection.h" +#include "types.h" #pragma once -// Let's make all interfaces have public no-op virtual destructors. class Driver { public: virtual ~Driver() = default; - // This should take an ODBC version which can be 2, 3, or 4. - virtual std::shared_ptr CreateConnection() = 0; + virtual std::shared_ptr + CreateConnection(OdbcVersion odbc_version) = 0; protected: Driver() = default; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cc index 2ae5bc4b7699a..99e2865a46f83 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cc @@ -1,10 +1,13 @@ #include "FlightSqlConnection.h" +#include "flight_sql_auth_method.h" #include using arrow::Result; using arrow::Status; using arrow::flight::FlightClient; +using arrow::flight::FlightClientOptions; using arrow::flight::Location; +using arrow::flight::TimeoutDuration; using arrow::flight::sql::FlightSqlClient; inline void ThrowIfNotOK(const Status &status) { @@ -16,43 +19,46 @@ inline void ThrowIfNotOK(const Status &status) { void FlightSqlConnection::Connect( const std::map &properties, std::vector &missing_attr) { - const std::string &host = - boost::get(properties.at(Connection::HOST)); - const int &port = boost::get(properties.at(Connection::PORT)); - - Location location; - if (properties.count("USE_SSL") && - boost::get(properties.at(Connection::USE_SSL))) { - ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); - } else { - ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); - } + Location location = GetLocation(properties); + FlightClientOptions client_options = GetFlightClientOptions(properties); std::unique_ptr client; + ThrowIfNotOK(FlightClient::Connect(location, client_options, &client)); - // TODO: Use timeout from attributes - ThrowIfNotOK(FlightClient::Connect(location, &client)); - - const std::string &username = - properties.count(Connection::USERNAME) - ? boost::get(properties.at(Connection::USERNAME)) - : ""; - const std::string &password = - properties.count(Connection::PASSWORD) - ? boost::get(properties.at(Connection::PASSWORD)) - : ""; - - if (!username.empty() || !password.empty()) { - Result> bearer_result = - client->AuthenticateBasicToken({}, username, password); - ThrowIfNotOK(bearer_result.status()); - - call_options_.headers.push_back(bearer_result.ValueOrDie()); + const boost::optional &connection_timeout = + GetAttribute(CONNECTION_TIMEOUT); + if (connection_timeout.has_value()) { + call_options_.timeout = + TimeoutDuration{boost::get(connection_timeout.value())}; } + std::unique_ptr auth_method = + FlightSqlAuthMethod::FromProperties(client, properties); + auth_method->Authenticate(call_options_); client_.reset(new FlightSqlClient(std::move(client))); } +FlightClientOptions FlightSqlConnection::GetFlightClientOptions( + const std::map &properties) { + // TODO: Use timeout from attributes + FlightClientOptions options; + return options; +} + +Location FlightSqlConnection::GetLocation( + const std::map &properties) { + const std::string &host = boost::get(properties.at(HOST)); + const int &port = boost::get(properties.at(PORT)); + + Location location; + if (properties.count(USE_SSL) && boost::get(properties.at(USE_SSL))) { + ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); + } else { + ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); + } + return location; +} + void FlightSqlConnection::Close() { if (closed_) { throw std::runtime_error("Connection already closed."); @@ -80,3 +86,6 @@ FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { throw std::runtime_error("GetInfo not implemented"); } + +FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version) + : Connection(odbc_version) {} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h index b90e0e0405ba5..221a40a2eb78b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h @@ -15,6 +15,8 @@ class FlightSqlConnection : public Connection { std::map attribute_; public: + FlightSqlConnection(OdbcVersion odbc_version); + void Connect(const std::map &properties, std::vector &missing_attr) override; @@ -28,4 +30,10 @@ class FlightSqlConnection : public Connection { GetAttribute(Connection::AttributeId attribute) override; Info GetInfo(uint16_t info_type) override; + + static arrow::flight::Location + GetLocation(const std::map &properties); + + static arrow::flight::FlightClientOptions + GetFlightClientOptions(const std::map &properties); }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cc index 4ed36500e4e44..6768bd7e29951 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cc @@ -1,6 +1,7 @@ #include "FlightSqlDriver.h" #include "FlightSqlConnection.h" -std::shared_ptr FlightSqlDriver::CreateConnection() { - return std::make_shared(); +std::shared_ptr +FlightSqlDriver::CreateConnection(OdbcVersion odbc_version) { + return std::make_shared(odbc_version); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h index 1954aae89c880..9aba1af666e8e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h @@ -4,5 +4,6 @@ class FlightSqlDriver : public Driver { public: - std::shared_ptr CreateConnection() override; + std::shared_ptr + CreateConnection(OdbcVersion odbc_version) override; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc new file mode 100644 index 0000000000000..445e5fbe2fd24 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -0,0 +1,63 @@ +#include "flight_sql_auth_method.h" + +#include + +#include + +using arrow::Result; +using arrow::flight::FlightClient; + +class NoOpAuthMethod : public FlightSqlAuthMethod { +public: + void Authenticate(FlightCallOptions &call_options) override { + // Do nothing + } +}; + +class UserPasswordAuthMethod : public FlightSqlAuthMethod { +public: + UserPasswordAuthMethod(FlightClient &client, std::string user, + std::string password) + : client_(client), user_(std::move(user)), + password_(std::move(password)) {} + + void Authenticate(FlightCallOptions &call_options) override { + Result> bearer_result = + client_.AuthenticateBasicToken(call_options, user_, password_); + if (!bearer_result.ok()) { + throw std::runtime_error( + "Failed to autenticate with user and password: " + + bearer_result.status().ToString()); + } + + call_options.headers.push_back(bearer_result.ValueOrDie()); + } + +private: + FlightClient &client_; + std::string user_; + std::string password_; +}; + +std::unique_ptr FlightSqlAuthMethod::FromProperties( + const std::unique_ptr &client, + const std::map &properties) { + + // Check if should use user-password authentication + if (properties.count(Connection::USER) || + properties.count(Connection::PASSWORD)) { + const std::string &user = + properties.count(Connection::USER) + ? boost::get(properties.at(Connection::USER)) + : ""; + const std::string &password = + properties.count(Connection::PASSWORD) + ? boost::get(properties.at(Connection::PASSWORD)) + : ""; + + return std::unique_ptr( + new UserPasswordAuthMethod(*client, user, password)); + } + + return std::unique_ptr(new NoOpAuthMethod); +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h new file mode 100644 index 0000000000000..c0cd7d9b6de58 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -0,0 +1,21 @@ +#pragma once + +#include "../connection.h" +#include +#include +#include + +using arrow::flight::FlightCallOptions; +using arrow::flight::FlightClient; + +class FlightSqlAuthMethod { +public: + virtual void Authenticate(FlightCallOptions &call_options) = 0; + + static std::unique_ptr + FromProperties(const std::unique_ptr &client, + const std::map &properties); + +protected: + FlightSqlAuthMethod() = default; +}; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cc index 36a454be4b355..c847133c20377 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/main.cc @@ -11,11 +11,13 @@ using arrow::flight::sql::FlightSqlClient; int main() { FlightSqlDriver driver; - const std::shared_ptr &connection = driver.CreateConnection(); + const std::shared_ptr &connection = driver.CreateConnection(V_3); std::map properties = { {Connection::HOST, std::string("0.0.0.0")}, - {Connection::PORT, 31337}, + {Connection::PORT, 32010}, + {Connection::USER, std::string("dremio")}, + {Connection::PASSWORD, std::string("dremio123")}, }; std::vector missing_attr; connection->Connect(properties, missing_attr); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/types.h new file mode 100644 index 0000000000000..7e4b1af72616d --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/types.h @@ -0,0 +1,3 @@ +#pragma once + +enum OdbcVersion { V_2, V_3, V_4 }; From f02b935fdd4778a50f7a3765b781d084d1637172 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Fri, 19 Nov 2021 13:40:32 -0300 Subject: [PATCH 015/183] Rename files to be consistent with Arrow's Change-Id: Id40f07822d1e4250ec32d36e6b585bfb142c81d4 --- .../flightsql-odbc/CMakeLists.txt | 7 ++---- .../flightsql-odbc/flight_sql/CMakeLists.txt | 22 +++++++++---------- ...Connection.cc => flight_sql_connection.cc} | 2 +- ...qlConnection.h => flight_sql_connection.h} | 0 ...nTest.cc => flight_sql_connection_test.cc} | 8 +++---- ...lightSqlDriver.cc => flight_sql_driver.cc} | 4 ++-- ...{FlightSqlDriver.h => flight_sql_driver.h} | 0 .../flightsql-odbc/flight_sql/main.cc | 2 +- 8 files changed, 19 insertions(+), 26 deletions(-) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/{FlightSqlConnection.cc => flight_sql_connection.cc} (98%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/{FlightSqlConnection.h => flight_sql_connection.h} (100%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/{FlightConnectionTest.cc => flight_sql_connection_test.cc} (92%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/{FlightSqlDriver.cc => flight_sql_driver.cc} (70%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/{FlightSqlDriver.h => flight_sql_driver.h} (100%) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index 584b5ccf909b0..81376a2ad2c52 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -4,10 +4,7 @@ set(CMAKE_CXX_STANDARD 11) project(flight_odbc_driver) include(FindODBC) -message(STATUS "Arrow version: ${ARROW_VERSION}") -message(STATUS "Arrow SO version: ${ARROW_FULL_SO_VERSION}") - add_subdirectory(flight_sql) -add_library(flight_odbc_driver connection.cc) -target_link_libraries(flight_odbc_driver ${ODBC_LIBRARIES}) \ No newline at end of file +add_library(abstraction_layer connection.cc) +target_link_libraries(abstraction_layer ${ODBC_LIBRARIES}) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 2a7abeb81267c..0de8a4ce78bfb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -8,18 +8,16 @@ find_package(ArrowFlightSql REQUIRED PATHS /usr/local/lib/cmake/arrow/) find_package(GTest REQUIRED) enable_testing() -add_executable(sql_moduler main.cc FlightSqlDriver.cc - FlightSqlConnection.cc - flight_sql_auth_method.cc) -target_link_libraries(sql_moduler flight_odbc_driver arrow_static arrow_flight arrow_flight_sql) +add_library(flight_odbc_driver flight_sql_driver.cc flight_sql_connection.cc flight_sql_auth_method.cc) +target_link_libraries(flight_odbc_driver abstraction_layer arrow_static arrow_flight arrow_flight_sql) +target_include_directories(flight_odbc_driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(sql_moduler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +# CLI +add_executable(flight_odbc_driver_cli main.cc) +target_link_libraries(flight_odbc_driver_cli flight_odbc_driver) -add_executable(odbc_test FlightConnectionTest.cc FlightSqlDriver.cc - FlightSqlConnection.cc - flight_sql_auth_method.cc) - -target_link_libraries(odbc_test flight_odbc_driver GTest::gtest GTest::gtest_main arrow_static arrow_flight arrow_flight_sql) - -add_test(connection_test odbc_test) \ No newline at end of file +# Unit tests +add_executable(flight_odbc_driver_test flight_sql_connection_test.cc) +target_link_libraries(flight_odbc_driver_test flight_odbc_driver GTest::gtest GTest::gtest_main) +add_test(connection_test flight_odbc_driver_test) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc similarity index 98% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cc rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 99e2865a46f83..792f389122708 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -1,4 +1,4 @@ -#include "FlightSqlConnection.h" +#include "flight_sql_connection.h" #include "flight_sql_auth_method.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h similarity index 100% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlConnection.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc similarity index 92% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cc rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 6398fe1e63c9e..89ca58795cf81 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightConnectionTest.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -1,4 +1,4 @@ -#include "FlightSqlDriver.h" +#include "flight_sql_driver.h" #include "gtest/gtest.h" TEST(AttributeTests, SetAndGetAttribute) { @@ -31,7 +31,5 @@ TEST(AttributeTests, GetAttributeWithoutSetting) { const boost::optional anOptional = connection->GetAttribute(Connection::CONNECTION_TIMEOUT); - bool b = anOptional.has_value(); - - EXPECT_FALSE(b); -} \ No newline at end of file + EXPECT_FALSE(anOptional.has_value()); +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc similarity index 70% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cc rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index 6768bd7e29951..9406f81e65af9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -1,5 +1,5 @@ -#include "FlightSqlDriver.h" -#include "FlightSqlConnection.h" +#include "flight_sql_driver.h" +#include "flight_sql_connection.h" std::shared_ptr FlightSqlDriver::CreateConnection(OdbcVersion odbc_version) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h similarity index 100% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/FlightSqlDriver.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 74fd51cdf5a39..c5ff1314cc49d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -1,4 +1,4 @@ -#include "FlightSqlDriver.h" +#include "flight_sql_driver.h" #include #include #include From 95a018cf2a56aa6fd14ed29a0dd78f64acde58d5 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Fri, 19 Nov 2021 14:43:26 -0300 Subject: [PATCH 016/183] Use LOGIN_TIMEOUT attribute when authenticating Change-Id: I8d5ec83f7478b1c316114ed30af13d314dd7a924 --- .../flightsql-odbc/connection.h | 23 ++++--------------- .../flight_sql/flight_sql_auth_method.cc | 21 +++++++++++++---- .../flight_sql/flight_sql_auth_method.h | 4 +++- .../flight_sql/flight_sql_connection.cc | 10 +------- .../flight_sql/flight_sql_connection.h | 2 +- 5 files changed, 26 insertions(+), 34 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h index 6dd24fff4aea8..85b32014271fc 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h @@ -11,31 +11,16 @@ class Connection { public: enum AttributeId { - ACCESS_MODE, // Writable attribute, tells if it should support write - // operations - ASYNC_DBC_EVENT, // Do not support async yet - ASYNC_DBC_FUNCTIONS_ENABLE, // Do not support async yet - ASYNC_DBC_PCALLBACK, // Do not support async yet - ASYNC_DBC_PCONTEXT, // Do not support async yet - ASYNC_ENABLE, // Do not support async yet + ACCESS_MODE, // Tells if it should support write operations AUTO_IPD, // Relevant to parameter binding on statements AUTOCOMMIT, // Do not support transactions yet CONNECTION_DEAD, // Tells if connection is still alive CONNECTION_TIMEOUT, // Matters to Connect() - CURRENT_CATALOG, // DO not support at first - Instead of passing catalog as - // argument, rely on this attribute - DBC_INFO_TOKEN, // lookup - ENLIST_IN_DTC, // Do not support + DBC_INFO_TOKEN, // Lookup LOGIN_TIMEOUT, // Matters to Connect() METADATA_ID, // Pass to statement - // ODBC_CURSORS, // Internal PACKET_SIZE, // Lookup if there is a packet size on Flight - QUIET_MODE, // lookup - // TRACE, - // TRACEFILE, - // TRANSLATE_LIB, - // TRANSLATE_OPTION, - TXN_ISOLATION, // Do not support transactions yet + QUIET_MODE, // Lookup }; typedef boost::variant Attribute; @@ -50,7 +35,7 @@ class Connection { // Add properties for getting the certificates // Check if gRPC can use the system truststore, if not copy from Drill - Connection(OdbcVersion odbc_version); + explicit Connection(OdbcVersion odbc_version); /** * Unified connect method diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 445e5fbe2fd24..c04e1c4850dd5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -1,15 +1,19 @@ #include "flight_sql_auth_method.h" +#include "flight_sql_connection.h" +#include #include #include using arrow::Result; using arrow::flight::FlightClient; +using arrow::flight::TimeoutDuration; class NoOpAuthMethod : public FlightSqlAuthMethod { public: - void Authenticate(FlightCallOptions &call_options) override { + void Authenticate(FlightSqlConnection &connection, + FlightCallOptions &call_options) override { // Do nothing } }; @@ -21,12 +25,21 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { : client_(client), user_(std::move(user)), password_(std::move(password)) {} - void Authenticate(FlightCallOptions &call_options) override { + void Authenticate(FlightSqlConnection &connection, + FlightCallOptions &call_options) override { + FlightCallOptions auth_call_options; + const boost::optional &login_timeout = + connection.GetAttribute(Connection::LOGIN_TIMEOUT); + if (login_timeout.has_value()) { + auth_call_options.timeout = + TimeoutDuration{boost::get(login_timeout.value())}; + } + Result> bearer_result = - client_.AuthenticateBasicToken(call_options, user_, password_); + client_.AuthenticateBasicToken(auth_call_options, user_, password_); if (!bearer_result.ok()) { throw std::runtime_error( - "Failed to autenticate with user and password: " + + "Failed to authenticate with user and password: " + bearer_result.status().ToString()); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index c0cd7d9b6de58..db6e0cd9c28a7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -1,6 +1,7 @@ #pragma once #include "../connection.h" +#include "flight_sql_connection.h" #include #include #include @@ -10,7 +11,8 @@ using arrow::flight::FlightClient; class FlightSqlAuthMethod { public: - virtual void Authenticate(FlightCallOptions &call_options) = 0; + virtual void Authenticate(FlightSqlConnection &connection, + FlightCallOptions &call_options) = 0; static std::unique_ptr FromProperties(const std::unique_ptr &client, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 792f389122708..850720c889963 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -7,7 +7,6 @@ using arrow::Status; using arrow::flight::FlightClient; using arrow::flight::FlightClientOptions; using arrow::flight::Location; -using arrow::flight::TimeoutDuration; using arrow::flight::sql::FlightSqlClient; inline void ThrowIfNotOK(const Status &status) { @@ -25,22 +24,15 @@ void FlightSqlConnection::Connect( std::unique_ptr client; ThrowIfNotOK(FlightClient::Connect(location, client_options, &client)); - const boost::optional &connection_timeout = - GetAttribute(CONNECTION_TIMEOUT); - if (connection_timeout.has_value()) { - call_options_.timeout = - TimeoutDuration{boost::get(connection_timeout.value())}; - } std::unique_ptr auth_method = FlightSqlAuthMethod::FromProperties(client, properties); - auth_method->Authenticate(call_options_); + auth_method->Authenticate(*this, call_options_); client_.reset(new FlightSqlClient(std::move(client))); } FlightClientOptions FlightSqlConnection::GetFlightClientOptions( const std::map &properties) { - // TODO: Use timeout from attributes FlightClientOptions options; return options; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 221a40a2eb78b..5725eb92e0af0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -15,7 +15,7 @@ class FlightSqlConnection : public Connection { std::map attribute_; public: - FlightSqlConnection(OdbcVersion odbc_version); + explicit FlightSqlConnection(OdbcVersion odbc_version); void Connect(const std::map &properties, std::vector &missing_attr) override; From f39cb78c1c7a1b90833449cb49dfaf0714b5defb Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Mon, 22 Nov 2021 13:09:24 -0300 Subject: [PATCH 017/183] Set CONNECTION_DEAD attribute on Connect() Change-Id: I618aa5b0d393bc296f90cd31b9f32f307dfa098f --- .../flightsql-odbc/connection.h | 20 ++++----- .../flight_sql/flight_sql_connection.cc | 43 +++++++++++++++---- .../flight_sql/flight_sql_connection.h | 3 ++ 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h index 85b32014271fc..465ac23f230d5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h @@ -11,16 +11,16 @@ class Connection { public: enum AttributeId { - ACCESS_MODE, // Tells if it should support write operations - AUTO_IPD, // Relevant to parameter binding on statements - AUTOCOMMIT, // Do not support transactions yet - CONNECTION_DEAD, // Tells if connection is still alive - CONNECTION_TIMEOUT, // Matters to Connect() - DBC_INFO_TOKEN, // Lookup - LOGIN_TIMEOUT, // Matters to Connect() - METADATA_ID, // Pass to statement - PACKET_SIZE, // Lookup if there is a packet size on Flight - QUIET_MODE, // Lookup + ACCESS_MODE, // Tells if it should support write operations + AUTO_IPD, // Relevant to parameter binding on statements + AUTOCOMMIT, // Do not support transactions yet + CONNECTION_DEAD, // Tells if connection is still alive + CONNECTION_TIMEOUT, // Matters to Connect() + DBC_INFO_TOKEN, // Lookup + LOGIN_TIMEOUT, // Matters to Connect() + METADATA_ID, // Pass to statement + PACKET_SIZE, // Lookup if there is a packet size on Flight + QUIET_MODE, // Lookup }; typedef boost::variant Attribute; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 850720c889963..f20bfda4dab11 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -1,12 +1,14 @@ #include "flight_sql_connection.h" #include "flight_sql_auth_method.h" #include +#include using arrow::Result; using arrow::Status; using arrow::flight::FlightClient; using arrow::flight::FlightClientOptions; using arrow::flight::Location; +using arrow::flight::TimeoutDuration; using arrow::flight::sql::FlightSqlClient; inline void ThrowIfNotOK(const Status &status) { @@ -18,17 +20,42 @@ inline void ThrowIfNotOK(const Status &status) { void FlightSqlConnection::Connect( const std::map &properties, std::vector &missing_attr) { - Location location = GetLocation(properties); - FlightClientOptions client_options = GetFlightClientOptions(properties); + try { + Location location = GetLocation(properties); + FlightClientOptions client_options = GetFlightClientOptions(properties); - std::unique_ptr client; - ThrowIfNotOK(FlightClient::Connect(location, client_options, &client)); + std::unique_ptr client; + ThrowIfNotOK(FlightClient::Connect(location, client_options, &client)); - std::unique_ptr auth_method = - FlightSqlAuthMethod::FromProperties(client, properties); - auth_method->Authenticate(*this, call_options_); + std::unique_ptr auth_method = + FlightSqlAuthMethod::FromProperties(client, properties); + auth_method->Authenticate(*this, call_options_); - client_.reset(new FlightSqlClient(std::move(client))); + client_.reset(new FlightSqlClient(std::move(client))); + SetAttribute(CONNECTION_DEAD, false); + + call_options_ = BuildCallOptions(properties); + } catch (std::exception &e) { + SetAttribute(CONNECTION_DEAD, true); + client_.reset(); + + throw e; + } +} + +FlightCallOptions FlightSqlConnection::BuildCallOptions( + const std::map &properties) { + + // Set CONNECTION_TIMEOUT attribute + FlightCallOptions call_options; + const boost::optional &connection_timeout = + GetAttribute(CONNECTION_TIMEOUT); + if (connection_timeout.has_value()) { + call_options.timeout = + TimeoutDuration{boost::get(connection_timeout.value())}; + } + + return call_options; } FlightClientOptions FlightSqlConnection::GetFlightClientOptions( diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 5725eb92e0af0..a9ce7913152f8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -36,4 +36,7 @@ class FlightSqlConnection : public Connection { static arrow::flight::FlightClientOptions GetFlightClientOptions(const std::map &properties); + + FlightCallOptions + BuildCallOptions(const std::map &properties); }; From 0f93644c05685b68fc202cb8d669ba5721c8a7e7 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Mon, 22 Nov 2021 14:16:37 -0300 Subject: [PATCH 018/183] Separate abstraction layer from Flight SQL implementation Change-Id: Id7e8c922539c95fbe4785fcde4f3d6d82c7069d3 --- .../flightsql-odbc/CMakeLists.txt | 7 +-- .../abstraction_layer/CMakeLists.txt | 4 ++ .../{ => abstraction_layer}/connection.cc | 3 -- .../{ => abstraction_layer}/connection.h | 51 ++++++++----------- .../{ => abstraction_layer}/driver.h | 3 ++ .../{ => abstraction_layer}/types.h | 1 + .../flightsql-odbc/flight_sql/CMakeLists.txt | 2 + .../flight_sql/flight_sql_auth_method.cc | 6 ++- .../flight_sql/flight_sql_auth_method.h | 4 +- .../flight_sql/flight_sql_connection.cc | 2 +- .../flight_sql/flight_sql_connection.h | 3 +- .../flight_sql/flight_sql_driver.h | 2 +- .../flightsql-odbc/flight_sql/main.cc | 4 +- .../flightsql-odbc/statement.h | 6 --- 14 files changed, 47 insertions(+), 51 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/CMakeLists.txt rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{ => abstraction_layer}/connection.cc (75%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{ => abstraction_layer}/connection.h (60%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{ => abstraction_layer}/driver.h (60%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{ => abstraction_layer}/types.h (58%) delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/statement.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index 81376a2ad2c52..b394e8ee1d517 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -1,10 +1,7 @@ cmake_minimum_required(VERSION 3.11) set(CMAKE_CXX_STANDARD 11) -project(flight_odbc_driver) -include(FindODBC) +project(flightsql_odbc) add_subdirectory(flight_sql) - -add_library(abstraction_layer connection.cc) -target_link_libraries(abstraction_layer ${ODBC_LIBRARIES}) +add_subdirectory(abstraction_layer) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/CMakeLists.txt new file mode 100644 index 0000000000000..f9cb295ccf663 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/CMakeLists.txt @@ -0,0 +1,4 @@ +include(FindODBC) + +add_library(abstraction_layer connection.cc) +target_link_libraries(abstraction_layer ${ODBC_LIBRARIES}) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.cc similarity index 75% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cc rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.cc index d87fec1add8c0..e466848e82d43 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.cc @@ -5,6 +5,3 @@ const std::string Connection::PORT = "PORT"; const std::string Connection::USER = "USER"; const std::string Connection::PASSWORD = "PASSWORD"; const std::string Connection::USE_SSL = "USE_SSL"; - -Connection::Connection(OdbcVersion odbc_version) - : odbc_version_(odbc_version) {} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.h similarity index 60% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.h index 465ac23f230d5..bd7431a354e9b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.h @@ -1,4 +1,3 @@ -#include "statement.h" #include #include #include @@ -8,8 +7,14 @@ #pragma once +class Statement; + +/// \brief High-level representation of an ODBC connection. class Connection { public: + virtual ~Connection() = default; + + /// \brief Connection attributes enum AttributeId { ACCESS_MODE, // Tells if it should support write operations AUTO_IPD, // Relevant to parameter binding on statements @@ -32,48 +37,36 @@ class Connection { static const std::string USER; static const std::string PASSWORD; static const std::string USE_SSL; - // Add properties for getting the certificates - // Check if gRPC can use the system truststore, if not copy from Drill + // TODO: Add properties for getting the certificates + // TODO: Check if gRPC can use the system truststore, if not copy from Drill explicit Connection(OdbcVersion odbc_version); - /** - * Unified connect method - * - * @param properties[in] - * @param missing_attr[out] - */ + /// \brief Establish the connection. + /// \param properties[in] properties used to establish the connection. + /// \param missing_properties[out] vector of missing properties (if any). virtual void Connect(const std::map &properties, - std::vector &missing_attr) = 0; + std::vector &missing_properties) = 0; - /** - * Close this connection - */ + /// \brief Close the connection. virtual void Close() = 0; - /** - * Allocates a statement - */ + /// \brief Create a statement. virtual std::shared_ptr CreateStatement() = 0; - /** - * Set a connection attribute (may be called at any time) - * @param attribute - * @param value - */ + /// \brief Set a connection attribute (may be called at any time). + /// \param attribute[in] Which attribute to set. + /// \param value The value to be set. virtual void SetAttribute(AttributeId attribute, const Attribute &value) = 0; - /** - * Retrieve a connection attribute - * - * @param attribute - * @return - */ + /// \brief Retrieve a connection attribute + /// \param attribute[in] Attribute to be retrieved. virtual boost::optional GetAttribute(Connection::AttributeId attribute) = 0; + /// \brief Retrieves info from the database (see ODBC's SQLGetInfo). virtual Info GetInfo(uint16_t info_type) = 0; -private: - OdbcVersion odbc_version_; +protected: + Connection() = default; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/driver.h similarity index 60% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/driver.h index 2c4e176c0081e..58b1d17c84f32 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/driver.h @@ -5,10 +5,13 @@ #pragma once +/// \brief High-level representation of an ODBC driver. class Driver { public: virtual ~Driver() = default; + /// \brief Create a connection using given ODBC version. + /// \param odbc_version ODBC version to be used. virtual std::shared_ptr CreateConnection(OdbcVersion odbc_version) = 0; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/types.h similarity index 58% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/types.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/types.h index 7e4b1af72616d..5e17082960007 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/types.h @@ -1,3 +1,4 @@ #pragma once +/// \brief Supported ODBC versions. enum OdbcVersion { V_2, V_3, V_4 }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 0de8a4ce78bfb..2c74b0feeb072 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 3.11) set(CMAKE_CXX_STANDARD 11) +include_directories(${CMAKE_SOURCE_DIR}/abstraction_layer) + SET(Arrow_STATIC ON) find_package(Arrow REQUIRED) find_package(ArrowFlight REQUIRED PATHS /usr/local/lib/cmake/arrow/) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index c04e1c4850dd5..98d0db537c37f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -31,8 +31,10 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { const boost::optional &login_timeout = connection.GetAttribute(Connection::LOGIN_TIMEOUT); if (login_timeout.has_value()) { - auth_call_options.timeout = - TimeoutDuration{boost::get(login_timeout.value())}; + double timeout_seconds = boost::get(login_timeout.value()); + if (timeout_seconds > 0) { + auth_call_options.timeout = TimeoutDuration{timeout_seconds}; + } } Result> bearer_result = diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index db6e0cd9c28a7..772489f86f3aa 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -1,6 +1,6 @@ #pragma once -#include "../connection.h" +#include "connection.h" #include "flight_sql_connection.h" #include #include @@ -11,6 +11,8 @@ using arrow::flight::FlightClient; class FlightSqlAuthMethod { public: + virtual ~FlightSqlAuthMethod() = default; + virtual void Authenticate(FlightSqlConnection &connection, FlightCallOptions &call_options) = 0; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index f20bfda4dab11..00a0849b98289 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -107,4 +107,4 @@ Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { } FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version) - : Connection(odbc_version) {} + : odbc_version_(odbc_version) {} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index a9ce7913152f8..0473c14e5b584 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -1,6 +1,6 @@ #pragma once -#include "../connection.h" +#include "connection.h" #include #include @@ -9,6 +9,7 @@ using arrow::flight::sql::FlightSqlClient; class FlightSqlConnection : public Connection { private: + OdbcVersion odbc_version_; std::unique_ptr client_; FlightCallOptions call_options_; bool closed_; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h index 9aba1af666e8e..b05e78a126016 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h @@ -1,6 +1,6 @@ #pragma once -#include "../driver.h" +#include "driver.h" class FlightSqlDriver : public Driver { public: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index c5ff1314cc49d..e3db5222b0ec5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -16,8 +16,8 @@ int main() { std::map properties = { {Connection::HOST, std::string("0.0.0.0")}, {Connection::PORT, 32010}, - {Connection::USER, std::string("dremio")}, - {Connection::PASSWORD, std::string("dremio123")}, + {Connection::USER, std::string("user")}, + {Connection::PASSWORD, std::string("password")}, }; std::vector missing_attr; connection->Connect(properties, missing_attr); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/statement.h deleted file mode 100644 index 1a94dd053d919..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/statement.h +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include - -#pragma once - -class Statement {}; From ddeffd1a0d9090a8367c8d3c8bec0dcffeb45f56 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Mon, 22 Nov 2021 14:25:09 -0300 Subject: [PATCH 019/183] Add namespace to all classes Change-Id: Ib9d65d17c4b4cbe8023d9855074c0e169a19064b --- .../flightsql-odbc/abstraction_layer/connection.cc | 4 ++++ .../flightsql-odbc/abstraction_layer/connection.h | 4 ++++ .../flightsql-odbc/abstraction_layer/driver.h | 3 +++ .../flightsql-odbc/abstraction_layer/types.h | 4 ++++ .../flightsql-odbc/flight_sql/flight_sql_auth_method.cc | 4 ++++ .../flightsql-odbc/flight_sql/flight_sql_auth_method.h | 4 ++++ .../flightsql-odbc/flight_sql/flight_sql_connection.cc | 4 ++++ .../flightsql-odbc/flight_sql/flight_sql_connection.h | 7 +++++++ .../flight_sql/flight_sql_connection_test.cc | 4 ++++ .../flightsql-odbc/flight_sql/flight_sql_driver.cc | 2 ++ .../flightsql-odbc/flight_sql/flight_sql_driver.h | 8 ++++++++ .../flightsql-odbc/flight_sql/main.cc | 6 +++++- 12 files changed, 53 insertions(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.cc index e466848e82d43..c23fcae25f924 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.cc @@ -1,7 +1,11 @@ #include "connection.h" +namespace abstraction_layer { + const std::string Connection::HOST = "HOST"; const std::string Connection::PORT = "PORT"; const std::string Connection::USER = "USER"; const std::string Connection::PASSWORD = "PASSWORD"; const std::string Connection::USE_SSL = "USE_SSL"; + +} // namespace abstraction_layer diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.h index bd7431a354e9b..4dff581291cae 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.h @@ -7,6 +7,8 @@ #pragma once +namespace abstraction_layer { + class Statement; /// \brief High-level representation of an ODBC connection. @@ -70,3 +72,5 @@ class Connection { protected: Connection() = default; }; + +} // namespace abstraction_layer diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/driver.h index 58b1d17c84f32..7f88dbb9c435b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/driver.h @@ -5,6 +5,7 @@ #pragma once +namespace abstraction_layer { /// \brief High-level representation of an ODBC driver. class Driver { public: @@ -18,3 +19,5 @@ class Driver { protected: Driver() = default; }; + +} // namespace abstraction_layer diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/types.h index 5e17082960007..3616d409be3ef 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/types.h @@ -1,4 +1,8 @@ #pragma once +namespace abstraction_layer { + /// \brief Supported ODBC versions. enum OdbcVersion { V_2, V_3, V_4 }; + +} // namespace abstraction_layer diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 98d0db537c37f..6b64c392da28d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -6,6 +6,8 @@ #include +namespace flight_sql_odbc { + using arrow::Result; using arrow::flight::FlightClient; using arrow::flight::TimeoutDuration; @@ -76,3 +78,5 @@ std::unique_ptr FlightSqlAuthMethod::FromProperties( return std::unique_ptr(new NoOpAuthMethod); } + +} // namespace flight_sql_odbc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index 772489f86f3aa..96488b1646205 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -6,6 +6,8 @@ #include #include +namespace flight_sql_odbc { + using arrow::flight::FlightCallOptions; using arrow::flight::FlightClient; @@ -23,3 +25,5 @@ class FlightSqlAuthMethod { protected: FlightSqlAuthMethod() = default; }; + +} // namespace flight_sql_odbc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 00a0849b98289..78ed210c92ed7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -3,6 +3,8 @@ #include #include +namespace flight_sql_odbc { + using arrow::Result; using arrow::Status; using arrow::flight::FlightClient; @@ -108,3 +110,5 @@ Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version) : odbc_version_(odbc_version) {} + +} // namespace flight_sql_odbc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 0473c14e5b584..bdd4a917a6f25 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -4,6 +4,11 @@ #include #include +namespace flight_sql_odbc { + +using abstraction_layer::Connection; +using abstraction_layer::OdbcVersion; +using abstraction_layer::Statement; using arrow::flight::FlightCallOptions; using arrow::flight::sql::FlightSqlClient; @@ -41,3 +46,5 @@ class FlightSqlConnection : public Connection { FlightCallOptions BuildCallOptions(const std::map &properties); }; + +} // namespace flight_sql_odbc \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 89ca58795cf81..90384538ee5eb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -1,6 +1,8 @@ #include "flight_sql_driver.h" #include "gtest/gtest.h" +namespace flight_sql_odbc { + TEST(AttributeTests, SetAndGetAttribute) { FlightSqlDriver driver; @@ -33,3 +35,5 @@ TEST(AttributeTests, GetAttributeWithoutSetting) { EXPECT_FALSE(anOptional.has_value()); } + +} // namespace flight_sql_odbc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index 9406f81e65af9..37d808bbe3183 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -1,7 +1,9 @@ #include "flight_sql_driver.h" #include "flight_sql_connection.h" +namespace flight_sql_odbc { std::shared_ptr FlightSqlDriver::CreateConnection(OdbcVersion odbc_version) { return std::make_shared(odbc_version); } +} // namespace flight_sql_odbc \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h index b05e78a126016..8a1fb8a080cb7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h @@ -2,8 +2,16 @@ #include "driver.h" +namespace flight_sql_odbc { + +using abstraction_layer::Connection; +using abstraction_layer::Driver; +using abstraction_layer::OdbcVersion; + class FlightSqlDriver : public Driver { public: std::shared_ptr CreateConnection(OdbcVersion odbc_version) override; }; + +}; // namespace flight_sql_odbc \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index e3db5222b0ec5..67eb5c9219054 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -8,10 +8,14 @@ using arrow::flight::FlightClient; using arrow::flight::Location; using arrow::flight::sql::FlightSqlClient; +using abstraction_layer::Connection; +using flight_sql_odbc::FlightSqlDriver; + int main() { FlightSqlDriver driver; - const std::shared_ptr &connection = driver.CreateConnection(V_3); + const std::shared_ptr &connection = + driver.CreateConnection(abstraction_layer::V_3); std::map properties = { {Connection::HOST, std::string("0.0.0.0")}, From 9baea931f33e1b5598c3b3ad72ce6948ad9d91a1 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Mon, 22 Nov 2021 14:30:54 -0300 Subject: [PATCH 020/183] Rename client_ to sql_client_ Change-Id: Ib24b7255f6c18e1376e8621f39a29a903c020ec8 --- .../flight_sql/flight_sql_connection.cc | 12 ++++++------ .../flight_sql/flight_sql_connection.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 78ed210c92ed7..668d47c77bbdd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -26,20 +26,20 @@ void FlightSqlConnection::Connect( Location location = GetLocation(properties); FlightClientOptions client_options = GetFlightClientOptions(properties); - std::unique_ptr client; - ThrowIfNotOK(FlightClient::Connect(location, client_options, &client)); + std::unique_ptr flight_client; + ThrowIfNotOK(FlightClient::Connect(location, client_options, &flight_client)); std::unique_ptr auth_method = - FlightSqlAuthMethod::FromProperties(client, properties); + FlightSqlAuthMethod::FromProperties(flight_client, properties); auth_method->Authenticate(*this, call_options_); - client_.reset(new FlightSqlClient(std::move(client))); + sql_client_.reset(new FlightSqlClient(std::move(flight_client))); SetAttribute(CONNECTION_DEAD, false); call_options_ = BuildCallOptions(properties); } catch (std::exception &e) { SetAttribute(CONNECTION_DEAD, true); - client_.reset(); + sql_client_.reset(); throw e; } @@ -85,7 +85,7 @@ void FlightSqlConnection::Close() { throw std::runtime_error("Connection already closed."); } - client_.reset(); + sql_client_.reset(); closed_ = true; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index bdd4a917a6f25..f65dc83d0f615 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -15,7 +15,7 @@ using arrow::flight::sql::FlightSqlClient; class FlightSqlConnection : public Connection { private: OdbcVersion odbc_version_; - std::unique_ptr client_; + std::unique_ptr sql_client_; FlightCallOptions call_options_; bool closed_; std::map attribute_; From 333af7d348747537313b45ce8fc07da95d452368 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Mon, 22 Nov 2021 14:35:47 -0300 Subject: [PATCH 021/183] Replace count/at usages to find() Change-Id: I6335c03453d2f42b224bd98ad56ed8719784476f --- .../flight_sql/flight_sql_auth_method.cc | 16 ++++++++-------- .../flight_sql/flight_sql_connection.cc | 10 ++++++---- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 6b64c392da28d..a9326af845aca 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -61,15 +61,15 @@ std::unique_ptr FlightSqlAuthMethod::FromProperties( const std::map &properties) { // Check if should use user-password authentication - if (properties.count(Connection::USER) || - properties.count(Connection::PASSWORD)) { - const std::string &user = - properties.count(Connection::USER) - ? boost::get(properties.at(Connection::USER)) - : ""; + const auto &it_user = properties.find(Connection::USER); + const auto &it_password = properties.find(Connection::PASSWORD); + if (it_user != properties.end() || it_password != properties.end()) { + const std::string &user = it_user != properties.end() + ? boost::get(it_user->second) + : ""; const std::string &password = - properties.count(Connection::PASSWORD) - ? boost::get(properties.at(Connection::PASSWORD)) + it_password != properties.end() + ? boost::get(it_password->second) : ""; return std::unique_ptr( diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 668d47c77bbdd..d3a076e33c44e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -27,7 +27,8 @@ void FlightSqlConnection::Connect( FlightClientOptions client_options = GetFlightClientOptions(properties); std::unique_ptr flight_client; - ThrowIfNotOK(FlightClient::Connect(location, client_options, &flight_client)); + ThrowIfNotOK( + FlightClient::Connect(location, client_options, &flight_client)); std::unique_ptr auth_method = FlightSqlAuthMethod::FromProperties(flight_client, properties); @@ -72,7 +73,8 @@ Location FlightSqlConnection::GetLocation( const int &port = boost::get(properties.at(PORT)); Location location; - if (properties.count(USE_SSL) && boost::get(properties.at(USE_SSL))) { + const auto &it_use_ssl = properties.find(USE_SSL); + if (it_use_ssl != properties.end() && boost::get(it_use_ssl->second)) { ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); } else { ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); @@ -100,8 +102,8 @@ void FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, boost::optional FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { - return boost::make_optional(attribute_.count(attribute), - attribute_.find(attribute)->second); + const auto &it = attribute_.find(attribute); + return boost::make_optional(it != attribute_.end(), it->second); } Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { From 74feab4c65eb99497544ea1b7c9adbcc9260619a Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Mon, 22 Nov 2021 14:55:22 -0300 Subject: [PATCH 022/183] Add OdbcException and AuthenticationException classes Change-Id: I6f6a16484ea95e783cbd690c63eae11f6957c4ff --- .../abstraction_layer/CMakeLists.txt | 2 +- .../abstraction_layer/exceptions.cc | 14 +++++++++++ .../abstraction_layer/exceptions.h | 23 +++++++++++++++++++ .../flight_sql/flight_sql_auth_method.cc | 6 ++++- .../flight_sql/flight_sql_connection.cc | 10 ++++---- 5 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/CMakeLists.txt index f9cb295ccf663..baae1d2cf5f0d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/CMakeLists.txt @@ -1,4 +1,4 @@ include(FindODBC) -add_library(abstraction_layer connection.cc) +add_library(abstraction_layer connection.cc exceptions.cc) target_link_libraries(abstraction_layer ${ODBC_LIBRARIES}) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.cc new file mode 100644 index 0000000000000..29aa6044825d1 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.cc @@ -0,0 +1,14 @@ +#include "exceptions.h" + +namespace abstraction_layer { + +OdbcException::OdbcException(const std::string &message) : message_(message) {} + +const char *OdbcException::what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { + return message_.c_str(); +} + +AuthenticationException::AuthenticationException(const std::string &message) + : OdbcException(message) {} + +} // namespace abstraction_layer diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.h new file mode 100644 index 0000000000000..049d398f3b7d2 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.h @@ -0,0 +1,23 @@ +#include +#include + +#pragma once + +namespace abstraction_layer { + +class OdbcException : public std::exception { +public: + explicit OdbcException(const std::string &message); + + const char *what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW override; + +private: + const std::string &message_; +}; + +class AuthenticationException : public OdbcException { +public: + explicit AuthenticationException(const std::string &message); +}; + +} // namespace abstraction_layer diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index a9326af845aca..815f187cff8c3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -1,4 +1,5 @@ #include "flight_sql_auth_method.h" +#include "exceptions.h" #include "flight_sql_connection.h" #include @@ -8,6 +9,7 @@ namespace flight_sql_odbc { +using abstraction_layer::AuthenticationException; using arrow::Result; using arrow::flight::FlightClient; using arrow::flight::TimeoutDuration; @@ -33,6 +35,8 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { const boost::optional &login_timeout = connection.GetAttribute(Connection::LOGIN_TIMEOUT); if (login_timeout.has_value()) { + // ODBC's LOGIN_TIMEOUT attribute and FlightCallOptions.timeout use + // seconds as time unit. double timeout_seconds = boost::get(login_timeout.value()); if (timeout_seconds > 0) { auth_call_options.timeout = TimeoutDuration{timeout_seconds}; @@ -42,7 +46,7 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { Result> bearer_result = client_.AuthenticateBasicToken(auth_call_options, user_, password_); if (!bearer_result.ok()) { - throw std::runtime_error( + throw AuthenticationException( "Failed to authenticate with user and password: " + bearer_result.status().ToString()); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index d3a076e33c44e..cac5f14263916 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -1,10 +1,12 @@ #include "flight_sql_connection.h" +#include "exceptions.h" #include "flight_sql_auth_method.h" #include #include namespace flight_sql_odbc { +using abstraction_layer::OdbcException; using arrow::Result; using arrow::Status; using arrow::flight::FlightClient; @@ -15,7 +17,7 @@ using arrow::flight::sql::FlightSqlClient; inline void ThrowIfNotOK(const Status &status) { if (!status.ok()) { - throw std::runtime_error(status.ToString()); + throw OdbcException(status.ToString()); } } @@ -84,7 +86,7 @@ Location FlightSqlConnection::GetLocation( void FlightSqlConnection::Close() { if (closed_) { - throw std::runtime_error("Connection already closed."); + throw OdbcException("Connection already closed."); } sql_client_.reset(); @@ -92,7 +94,7 @@ void FlightSqlConnection::Close() { } std::shared_ptr FlightSqlConnection::CreateStatement() { - throw std::runtime_error("CreateStatement not implemented"); + throw OdbcException("CreateStatement not implemented"); } void FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, @@ -107,7 +109,7 @@ FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { } Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { - throw std::runtime_error("GetInfo not implemented"); + throw OdbcException("GetInfo not implemented"); } FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version) From da6f2bf6c3c3c3aeca295580a06bdf132e87aca3 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 23 Nov 2021 11:12:12 -0300 Subject: [PATCH 023/183] Add unit tests for auxiliary functions Change-Id: I6708938aa7040b9af7002e9514387767d4c2764a --- .../flight_sql/flight_sql_connection.cc | 7 +-- .../flight_sql/flight_sql_connection.h | 3 +- .../flight_sql/flight_sql_connection_test.cc | 56 +++++++++++++++---- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index cac5f14263916..7a739be3ba260 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -39,7 +39,7 @@ void FlightSqlConnection::Connect( sql_client_.reset(new FlightSqlClient(std::move(flight_client))); SetAttribute(CONNECTION_DEAD, false); - call_options_ = BuildCallOptions(properties); + call_options_ = BuildCallOptions(); } catch (std::exception &e) { SetAttribute(CONNECTION_DEAD, true); sql_client_.reset(); @@ -48,9 +48,7 @@ void FlightSqlConnection::Connect( } } -FlightCallOptions FlightSqlConnection::BuildCallOptions( - const std::map &properties) { - +FlightCallOptions FlightSqlConnection::BuildCallOptions() { // Set CONNECTION_TIMEOUT attribute FlightCallOptions call_options; const boost::optional &connection_timeout = @@ -66,6 +64,7 @@ FlightCallOptions FlightSqlConnection::BuildCallOptions( FlightClientOptions FlightSqlConnection::GetFlightClientOptions( const std::map &properties) { FlightClientOptions options; + // TODO: Set up SSL properties return options; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index f65dc83d0f615..89f27f66a66af 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -43,8 +43,7 @@ class FlightSqlConnection : public Connection { static arrow::flight::FlightClientOptions GetFlightClientOptions(const std::map &properties); - FlightCallOptions - BuildCallOptions(const std::map &properties); + FlightCallOptions BuildCallOptions(); }; } // namespace flight_sql_odbc \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 90384538ee5eb..c27e6e027daf4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -1,39 +1,71 @@ -#include "flight_sql_driver.h" +#include "flight_sql_connection.h" #include "gtest/gtest.h" +#include namespace flight_sql_odbc { -TEST(AttributeTests, SetAndGetAttribute) { - FlightSqlDriver driver; +using abstraction_layer::Connection; +using arrow::flight::Location; +using arrow::flight::TimeoutDuration; - const std::shared_ptr &connection = driver.CreateConnection(V_3); +TEST(AttributeTests, SetAndGetAttribute) { + FlightSqlConnection connection(abstraction_layer::V_3); - connection->SetAttribute(Connection::CONNECTION_TIMEOUT, 200); + connection.SetAttribute(Connection::CONNECTION_TIMEOUT, 200); const boost::optional firstValue = - connection->GetAttribute(Connection::CONNECTION_TIMEOUT); + connection.GetAttribute(Connection::CONNECTION_TIMEOUT); EXPECT_TRUE(firstValue.has_value()); EXPECT_EQ(boost::get(firstValue.value()), 200); - connection->SetAttribute(Connection::CONNECTION_TIMEOUT, 300); + connection.SetAttribute(Connection::CONNECTION_TIMEOUT, 300); const boost::optional changeValue = - connection->GetAttribute(Connection::CONNECTION_TIMEOUT); + connection.GetAttribute(Connection::CONNECTION_TIMEOUT); EXPECT_TRUE(changeValue.has_value()); EXPECT_EQ(boost::get(changeValue.value()), 300); } TEST(AttributeTests, GetAttributeWithoutSetting) { - FlightSqlDriver driver; - - const std::shared_ptr &connection = driver.CreateConnection(V_3); + FlightSqlConnection connection(abstraction_layer::V_3); const boost::optional anOptional = - connection->GetAttribute(Connection::CONNECTION_TIMEOUT); + connection.GetAttribute(Connection::CONNECTION_TIMEOUT); EXPECT_FALSE(anOptional.has_value()); } +TEST(ConnectTests, GetLocationTcp) { + const Location &actual_location1 = + flight_sql_odbc::FlightSqlConnection::GetLocation({ + {Connection::HOST, std::string("localhost")}, + {Connection::PORT, 32010}, + }); + const Location &actual_location2 = + flight_sql_odbc::FlightSqlConnection::GetLocation({ + {Connection::HOST, std::string("localhost")}, + {Connection::PORT, 32011}, + }); + + Location expected_location; + ASSERT_TRUE( + Location::ForGrpcTcp("localhost", 32010, &expected_location).ok()); + ASSERT_EQ(expected_location, actual_location1); + ASSERT_NE(expected_location, actual_location2); + + // TODO: Add tests for SSL +} + +TEST(ConnectTests, BuildCallOptions) { + FlightSqlConnection connection(abstraction_layer::V_3); + + ASSERT_EQ(arrow::flight::TimeoutDuration{-1.0}, + connection.BuildCallOptions().timeout); + + connection.SetAttribute(Connection::CONNECTION_TIMEOUT, 10.0); + ASSERT_EQ(TimeoutDuration{10.0}, connection.BuildCallOptions().timeout); +} + } // namespace flight_sql_odbc From 9b511c87cf2487d7e2e58f11c1c2b254385a28ee Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 23 Nov 2021 11:36:27 -0300 Subject: [PATCH 024/183] Change namespaces Change-Id: I795a9425e0604c5d17d0ae7113f75627f43f2c29 --- .../flightsql-odbc/CMakeLists.txt | 2 +- .../abstraction_layer/CMakeLists.txt | 4 --- .../abstraction_layer/exceptions.cc | 14 -------- .../flightsql-odbc/flight_sql/CMakeLists.txt | 4 +-- .../flight_sql/flight_sql_auth_method.cc | 8 +++-- .../flight_sql/flight_sql_auth_method.h | 6 ++-- .../flight_sql/flight_sql_connection.cc | 8 +++-- .../flight_sql/flight_sql_connection.h | 13 ++++---- .../flight_sql/flight_sql_connection_test.cc | 32 +++++++++---------- .../flight_sql/flight_sql_driver.cc | 6 ++-- .../flight_sql/flight_sql_driver.h | 12 ++++--- .../flightsql-odbc/flight_sql/main.cc | 6 ++-- .../flightsql-odbc/spi/CMakeLists.txt | 4 +++ .../{abstraction_layer => spi}/connection.cc | 6 ++-- .../{abstraction_layer => spi}/connection.h | 6 ++-- .../{abstraction_layer => spi}/driver.h | 7 ++-- .../flightsql-odbc/spi/exceptions.cc | 19 +++++++++++ .../{abstraction_layer => spi}/exceptions.h | 12 ++++--- .../{abstraction_layer => spi}/types.h | 6 ++-- 19 files changed, 101 insertions(+), 74 deletions(-) delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/CMakeLists.txt delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{abstraction_layer => spi}/connection.cc (77%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{abstraction_layer => spi}/connection.h (97%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{abstraction_layer => spi}/driver.h (84%) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{abstraction_layer => spi}/exceptions.h (55%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{abstraction_layer => spi}/types.h (53%) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index b394e8ee1d517..682e644022f3a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -4,4 +4,4 @@ set(CMAKE_CXX_STANDARD 11) project(flightsql_odbc) add_subdirectory(flight_sql) -add_subdirectory(abstraction_layer) +add_subdirectory(spi) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/CMakeLists.txt deleted file mode 100644 index baae1d2cf5f0d..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -include(FindODBC) - -add_library(abstraction_layer connection.cc exceptions.cc) -target_link_libraries(abstraction_layer ${ODBC_LIBRARIES}) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.cc deleted file mode 100644 index 29aa6044825d1..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.cc +++ /dev/null @@ -1,14 +0,0 @@ -#include "exceptions.h" - -namespace abstraction_layer { - -OdbcException::OdbcException(const std::string &message) : message_(message) {} - -const char *OdbcException::what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { - return message_.c_str(); -} - -AuthenticationException::AuthenticationException(const std::string &message) - : OdbcException(message) {} - -} // namespace abstraction_layer diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 2c74b0feeb072..ba7b96d195954 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.11) set(CMAKE_CXX_STANDARD 11) -include_directories(${CMAKE_SOURCE_DIR}/abstraction_layer) +include_directories(${CMAKE_SOURCE_DIR}/spi) SET(Arrow_STATIC ON) find_package(Arrow REQUIRED) @@ -12,7 +12,7 @@ find_package(GTest REQUIRED) enable_testing() add_library(flight_odbc_driver flight_sql_driver.cc flight_sql_connection.cc flight_sql_auth_method.cc) -target_link_libraries(flight_odbc_driver abstraction_layer arrow_static arrow_flight arrow_flight_sql) +target_link_libraries(flight_odbc_driver spi arrow_static arrow_flight arrow_flight_sql) target_include_directories(flight_odbc_driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) # CLI diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 815f187cff8c3..d3f4f59b725fb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -7,12 +7,13 @@ #include -namespace flight_sql_odbc { +namespace driver { +namespace flight_sql { -using abstraction_layer::AuthenticationException; using arrow::Result; using arrow::flight::FlightClient; using arrow::flight::TimeoutDuration; +using spi::AuthenticationException; class NoOpAuthMethod : public FlightSqlAuthMethod { public: @@ -83,4 +84,5 @@ std::unique_ptr FlightSqlAuthMethod::FromProperties( return std::unique_ptr(new NoOpAuthMethod); } -} // namespace flight_sql_odbc +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index 96488b1646205..de33a43d3bf4e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -6,7 +6,8 @@ #include #include -namespace flight_sql_odbc { +namespace driver { +namespace flight_sql { using arrow::flight::FlightCallOptions; using arrow::flight::FlightClient; @@ -26,4 +27,5 @@ class FlightSqlAuthMethod { FlightSqlAuthMethod() = default; }; -} // namespace flight_sql_odbc +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 7a739be3ba260..6982e341b5d09 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -4,9 +4,9 @@ #include #include -namespace flight_sql_odbc { +namespace driver { +namespace flight_sql { -using abstraction_layer::OdbcException; using arrow::Result; using arrow::Status; using arrow::flight::FlightClient; @@ -14,6 +14,7 @@ using arrow::flight::FlightClientOptions; using arrow::flight::Location; using arrow::flight::TimeoutDuration; using arrow::flight::sql::FlightSqlClient; +using spi::OdbcException; inline void ThrowIfNotOK(const Status &status) { if (!status.ok()) { @@ -114,4 +115,5 @@ Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version) : odbc_version_(odbc_version) {} -} // namespace flight_sql_odbc +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 89f27f66a66af..06696cd642a2c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -4,13 +4,14 @@ #include #include -namespace flight_sql_odbc { +namespace driver { +namespace flight_sql { -using abstraction_layer::Connection; -using abstraction_layer::OdbcVersion; -using abstraction_layer::Statement; using arrow::flight::FlightCallOptions; using arrow::flight::sql::FlightSqlClient; +using spi::Connection; +using spi::OdbcVersion; +using spi::Statement; class FlightSqlConnection : public Connection { private: @@ -45,5 +46,5 @@ class FlightSqlConnection : public Connection { FlightCallOptions BuildCallOptions(); }; - -} // namespace flight_sql_odbc \ No newline at end of file +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index c27e6e027daf4..eb9b8d6536b38 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -2,14 +2,15 @@ #include "gtest/gtest.h" #include -namespace flight_sql_odbc { +namespace driver { +namespace flight_sql { -using abstraction_layer::Connection; using arrow::flight::Location; using arrow::flight::TimeoutDuration; +using spi::Connection; TEST(AttributeTests, SetAndGetAttribute) { - FlightSqlConnection connection(abstraction_layer::V_3); + FlightSqlConnection connection(spi::V_3); connection.SetAttribute(Connection::CONNECTION_TIMEOUT, 200); const boost::optional firstValue = @@ -29,7 +30,7 @@ TEST(AttributeTests, SetAndGetAttribute) { } TEST(AttributeTests, GetAttributeWithoutSetting) { - FlightSqlConnection connection(abstraction_layer::V_3); + FlightSqlConnection connection(spi::V_3); const boost::optional anOptional = connection.GetAttribute(Connection::CONNECTION_TIMEOUT); @@ -38,16 +39,14 @@ TEST(AttributeTests, GetAttributeWithoutSetting) { } TEST(ConnectTests, GetLocationTcp) { - const Location &actual_location1 = - flight_sql_odbc::FlightSqlConnection::GetLocation({ - {Connection::HOST, std::string("localhost")}, - {Connection::PORT, 32010}, - }); - const Location &actual_location2 = - flight_sql_odbc::FlightSqlConnection::GetLocation({ - {Connection::HOST, std::string("localhost")}, - {Connection::PORT, 32011}, - }); + const Location &actual_location1 = FlightSqlConnection::GetLocation({ + {Connection::HOST, std::string("localhost")}, + {Connection::PORT, 32010}, + }); + const Location &actual_location2 = FlightSqlConnection::GetLocation({ + {Connection::HOST, std::string("localhost")}, + {Connection::PORT, 32011}, + }); Location expected_location; ASSERT_TRUE( @@ -59,7 +58,7 @@ TEST(ConnectTests, GetLocationTcp) { } TEST(ConnectTests, BuildCallOptions) { - FlightSqlConnection connection(abstraction_layer::V_3); + FlightSqlConnection connection(spi::V_3); ASSERT_EQ(arrow::flight::TimeoutDuration{-1.0}, connection.BuildCallOptions().timeout); @@ -68,4 +67,5 @@ TEST(ConnectTests, BuildCallOptions) { ASSERT_EQ(TimeoutDuration{10.0}, connection.BuildCallOptions().timeout); } -} // namespace flight_sql_odbc +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index 37d808bbe3183..0417e455f415d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -1,9 +1,11 @@ #include "flight_sql_driver.h" #include "flight_sql_connection.h" -namespace flight_sql_odbc { +namespace driver { +namespace flight_sql { std::shared_ptr FlightSqlDriver::CreateConnection(OdbcVersion odbc_version) { return std::make_shared(odbc_version); } -} // namespace flight_sql_odbc \ No newline at end of file +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h index 8a1fb8a080cb7..f855b3de3e7c9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h @@ -2,11 +2,12 @@ #include "driver.h" -namespace flight_sql_odbc { +namespace driver { +namespace flight_sql { -using abstraction_layer::Connection; -using abstraction_layer::Driver; -using abstraction_layer::OdbcVersion; +using spi::Connection; +using spi::Driver; +using spi::OdbcVersion; class FlightSqlDriver : public Driver { public: @@ -14,4 +15,5 @@ class FlightSqlDriver : public Driver { CreateConnection(OdbcVersion odbc_version) override; }; -}; // namespace flight_sql_odbc \ No newline at end of file +}; // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 67eb5c9219054..eefbebc6bb552 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -8,14 +8,14 @@ using arrow::flight::FlightClient; using arrow::flight::Location; using arrow::flight::sql::FlightSqlClient; -using abstraction_layer::Connection; -using flight_sql_odbc::FlightSqlDriver; +using driver::flight_sql::FlightSqlDriver; +using driver::spi::Connection; int main() { FlightSqlDriver driver; const std::shared_ptr &connection = - driver.CreateConnection(abstraction_layer::V_3); + driver.CreateConnection(driver::spi::V_3); std::map properties = { {Connection::HOST, std::string("0.0.0.0")}, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt new file mode 100644 index 0000000000000..ee640709a78c6 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt @@ -0,0 +1,4 @@ +include(FindODBC) + +add_library(spi connection.cc exceptions.cc) +target_link_libraries(spi ${ODBC_LIBRARIES}) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc similarity index 77% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.cc rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc index c23fcae25f924..c35adf7bea6bb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc @@ -1,6 +1,7 @@ #include "connection.h" -namespace abstraction_layer { +namespace driver { +namespace spi { const std::string Connection::HOST = "HOST"; const std::string Connection::PORT = "PORT"; @@ -8,4 +9,5 @@ const std::string Connection::USER = "USER"; const std::string Connection::PASSWORD = "PASSWORD"; const std::string Connection::USE_SSL = "USE_SSL"; -} // namespace abstraction_layer +} // namespace spi +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h similarity index 97% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h index 4dff581291cae..a2cc37a17fd2f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h @@ -7,7 +7,8 @@ #pragma once -namespace abstraction_layer { +namespace driver { +namespace spi { class Statement; @@ -73,4 +74,5 @@ class Connection { Connection() = default; }; -} // namespace abstraction_layer +} // namespace spi +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/driver.h similarity index 84% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/driver.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/driver.h index 7f88dbb9c435b..dc846816a0bde 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/driver.h @@ -5,7 +5,9 @@ #pragma once -namespace abstraction_layer { +namespace driver { +namespace spi { + /// \brief High-level representation of an ODBC driver. class Driver { public: @@ -20,4 +22,5 @@ class Driver { Driver() = default; }; -} // namespace abstraction_layer +} // namespace spi +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc new file mode 100644 index 0000000000000..0e929ca46bb2d --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc @@ -0,0 +1,19 @@ +#include "exceptions.h" + +#include + +namespace driver { +namespace spi { + +OdbcException::OdbcException(std::string message) + : message_(std::move(message)) {} + +const char *OdbcException::what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { + return message_.c_str(); +} + +AuthenticationException::AuthenticationException(std::string message) + : OdbcException(std::move(message)) {} + +} // namespace spi +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h similarity index 55% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h index 049d398f3b7d2..73fb6f2bd0fc1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/exceptions.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h @@ -3,21 +3,23 @@ #pragma once -namespace abstraction_layer { +namespace driver { +namespace spi { class OdbcException : public std::exception { public: - explicit OdbcException(const std::string &message); + explicit OdbcException(std::string message); const char *what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW override; private: - const std::string &message_; + const std::string message_; }; class AuthenticationException : public OdbcException { public: - explicit AuthenticationException(const std::string &message); + explicit AuthenticationException(std::string message); }; -} // namespace abstraction_layer +} // namespace spi +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/types.h similarity index 53% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/types.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/types.h index 3616d409be3ef..bff93d4fb9c5e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/abstraction_layer/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/types.h @@ -1,8 +1,10 @@ #pragma once -namespace abstraction_layer { +namespace driver { +namespace spi { /// \brief Supported ODBC versions. enum OdbcVersion { V_2, V_3, V_4 }; -} // namespace abstraction_layer +} // namespace spi +} // namespace driver From df1c6eb739c579a3ef090056f928961eb1e32f5e Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 23 Nov 2021 11:44:38 -0300 Subject: [PATCH 025/183] Avoid 'using' statements on headers Change-Id: Ifb49615e533f0d049e71c9e23a4a538327c5f217 --- .../flight_sql/flight_sql_auth_method.cc | 2 ++ .../flight_sql/flight_sql_auth_method.h | 11 ++++------ .../flight_sql/flight_sql_connection.cc | 4 ++++ .../flight_sql/flight_sql_connection.h | 20 +++++++------------ .../flight_sql/flight_sql_driver.cc | 4 ++++ .../flight_sql/flight_sql_driver.h | 10 +++------- 6 files changed, 24 insertions(+), 27 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index d3f4f59b725fb..74f48f66b1931 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -11,9 +11,11 @@ namespace driver { namespace flight_sql { using arrow::Result; +using arrow::flight::FlightCallOptions; using arrow::flight::FlightClient; using arrow::flight::TimeoutDuration; using spi::AuthenticationException; +using spi::Connection; class NoOpAuthMethod : public FlightSqlAuthMethod { public: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index de33a43d3bf4e..4f8757548579b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -9,19 +9,16 @@ namespace driver { namespace flight_sql { -using arrow::flight::FlightCallOptions; -using arrow::flight::FlightClient; - class FlightSqlAuthMethod { public: virtual ~FlightSqlAuthMethod() = default; virtual void Authenticate(FlightSqlConnection &connection, - FlightCallOptions &call_options) = 0; + arrow::flight::FlightCallOptions &call_options) = 0; - static std::unique_ptr - FromProperties(const std::unique_ptr &client, - const std::map &properties); + static std::unique_ptr FromProperties( + const std::unique_ptr &client, + const std::map &properties); protected: FlightSqlAuthMethod() = default; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 6982e341b5d09..f1cdf53b45129 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -9,12 +9,16 @@ namespace flight_sql { using arrow::Result; using arrow::Status; +using arrow::flight::FlightCallOptions; using arrow::flight::FlightClient; using arrow::flight::FlightClientOptions; using arrow::flight::Location; using arrow::flight::TimeoutDuration; using arrow::flight::sql::FlightSqlClient; +using spi::Connection; using spi::OdbcException; +using spi::OdbcVersion; +using spi::Statement; inline void ThrowIfNotOK(const Status &status) { if (!status.ok()) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 06696cd642a2c..4994524096656 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -7,29 +7,23 @@ namespace driver { namespace flight_sql { -using arrow::flight::FlightCallOptions; -using arrow::flight::sql::FlightSqlClient; -using spi::Connection; -using spi::OdbcVersion; -using spi::Statement; - -class FlightSqlConnection : public Connection { +class FlightSqlConnection : public spi::Connection { private: - OdbcVersion odbc_version_; - std::unique_ptr sql_client_; - FlightCallOptions call_options_; + spi::OdbcVersion odbc_version_; + std::unique_ptr sql_client_; + arrow::flight::FlightCallOptions call_options_; bool closed_; std::map attribute_; public: - explicit FlightSqlConnection(OdbcVersion odbc_version); + explicit FlightSqlConnection(spi::OdbcVersion odbc_version); void Connect(const std::map &properties, std::vector &missing_attr) override; void Close() override; - std::shared_ptr CreateStatement() override; + std::shared_ptr CreateStatement() override; void SetAttribute(AttributeId attribute, const Attribute &value) override; @@ -44,7 +38,7 @@ class FlightSqlConnection : public Connection { static arrow::flight::FlightClientOptions GetFlightClientOptions(const std::map &properties); - FlightCallOptions BuildCallOptions(); + arrow::flight::FlightCallOptions BuildCallOptions(); }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index 0417e455f415d..dd72419d698d4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -3,6 +3,10 @@ namespace driver { namespace flight_sql { + +using spi::Connection; +using spi::OdbcVersion; + std::shared_ptr FlightSqlDriver::CreateConnection(OdbcVersion odbc_version) { return std::make_shared(odbc_version); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h index f855b3de3e7c9..e6e9d21c938e4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h @@ -5,14 +5,10 @@ namespace driver { namespace flight_sql { -using spi::Connection; -using spi::Driver; -using spi::OdbcVersion; - -class FlightSqlDriver : public Driver { +class FlightSqlDriver : public spi::Driver { public: - std::shared_ptr - CreateConnection(OdbcVersion odbc_version) override; + std::shared_ptr + CreateConnection(spi::OdbcVersion odbc_version) override; }; }; // namespace flight_sql From 809cab9fbb2634e64cb05b4dd0f54f65869a6658 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 23 Nov 2021 11:51:36 -0300 Subject: [PATCH 026/183] cla Change-Id: I70a010f0886ddd69cc4d59400f0eca0d46392bc6 --- .../flightsql-odbc/flight_sql/flight_sql_auth_method.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 74f48f66b1931..14dacc8073673 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -17,6 +17,8 @@ using arrow::flight::TimeoutDuration; using spi::AuthenticationException; using spi::Connection; +namespace { + class NoOpAuthMethod : public FlightSqlAuthMethod { public: void Authenticate(FlightSqlConnection &connection, @@ -63,6 +65,8 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { std::string password_; }; +} // namespace + std::unique_ptr FlightSqlAuthMethod::FromProperties( const std::unique_ptr &client, const std::map &properties) { From e2e3ae1f737d05b720fa6f6f2a29cf88aac3068a Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 23 Nov 2021 11:52:12 -0300 Subject: [PATCH 027/183] Avoid including implementations of FlightSqlAuthMethod on flight_sql namespace Change-Id: I4ec35016ab51d986c4cd91e47b3de5dd19bd1320 --- .../flight_sql/flight_sql_auth_method.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 14dacc8073673..33a20beb56317 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -7,17 +7,14 @@ #include -namespace driver { -namespace flight_sql { +using namespace driver::flight_sql; using arrow::Result; using arrow::flight::FlightCallOptions; using arrow::flight::FlightClient; using arrow::flight::TimeoutDuration; -using spi::AuthenticationException; -using spi::Connection; - -namespace { +using driver::spi::AuthenticationException; +using driver::spi::Connection; class NoOpAuthMethod : public FlightSqlAuthMethod { public: @@ -65,7 +62,8 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { std::string password_; }; -} // namespace +namespace driver { +namespace flight_sql { std::unique_ptr FlightSqlAuthMethod::FromProperties( const std::unique_ptr &client, From 95730094a5d77ee7c551968d6c2f57ac627534f6 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 23 Nov 2021 11:53:10 -0300 Subject: [PATCH 028/183] Reorder FlightSqlConnection fields Change-Id: Ifad7c7b05b2a0e9d96e33715de49b5867f79c954 --- .../flightsql-odbc/flight_sql/flight_sql_connection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 4994524096656..1bbb63a4a0c96 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -9,10 +9,10 @@ namespace flight_sql { class FlightSqlConnection : public spi::Connection { private: + bool closed_; spi::OdbcVersion odbc_version_; std::unique_ptr sql_client_; arrow::flight::FlightCallOptions call_options_; - bool closed_; std::map attribute_; public: From e6f964d37c9c9d389e903230f6809c32cc430b1b Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 23 Nov 2021 11:55:15 -0300 Subject: [PATCH 029/183] Remove unimplemented constructor Change-Id: I6b8c2095eda33040742d3c8f029a4d38a0a79515 --- .../flightsql-odbc-clone/flightsql-odbc/spi/connection.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h index a2cc37a17fd2f..dc8b3e160276f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h @@ -43,8 +43,6 @@ class Connection { // TODO: Add properties for getting the certificates // TODO: Check if gRPC can use the system truststore, if not copy from Drill - explicit Connection(OdbcVersion odbc_version); - /// \brief Establish the connection. /// \param properties[in] properties used to establish the connection. /// \param missing_properties[out] vector of missing properties (if any). From 1f6fe97a29b5cfa83ee350ba09bef746ffd45d6f Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 23 Nov 2021 13:12:23 -0300 Subject: [PATCH 030/183] Add comments to driver exceptions Change-Id: Ifb4b62d45574c4066204c5c9b3f76c8d972860c1 --- .../flightsql-odbc/flight_sql/flight_sql_connection.cc | 10 +++++----- .../flight_sql/flight_sql_connection_test.cc | 2 ++ .../flightsql-odbc/spi/exceptions.cc | 6 +++--- .../flightsql-odbc/spi/exceptions.h | 8 +++++--- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index f1cdf53b45129..216cad4c985ad 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -16,13 +16,13 @@ using arrow::flight::Location; using arrow::flight::TimeoutDuration; using arrow::flight::sql::FlightSqlClient; using spi::Connection; -using spi::OdbcException; +using spi::DriverException; using spi::OdbcVersion; using spi::Statement; inline void ThrowIfNotOK(const Status &status) { if (!status.ok()) { - throw OdbcException(status.ToString()); + throw DriverException(status.ToString()); } } @@ -90,7 +90,7 @@ Location FlightSqlConnection::GetLocation( void FlightSqlConnection::Close() { if (closed_) { - throw OdbcException("Connection already closed."); + throw DriverException("Connection already closed."); } sql_client_.reset(); @@ -98,7 +98,7 @@ void FlightSqlConnection::Close() { } std::shared_ptr FlightSqlConnection::CreateStatement() { - throw OdbcException("CreateStatement not implemented"); + throw DriverException("CreateStatement not implemented"); } void FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, @@ -113,7 +113,7 @@ FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { } Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { - throw OdbcException("GetInfo not implemented"); + throw DriverException("GetInfo not implemented"); } FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index eb9b8d6536b38..30b978f68dff1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -36,6 +36,8 @@ TEST(AttributeTests, GetAttributeWithoutSetting) { connection.GetAttribute(Connection::CONNECTION_TIMEOUT); EXPECT_FALSE(anOptional.has_value()); + + connection.Close(); } TEST(ConnectTests, GetLocationTcp) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc index 0e929ca46bb2d..c1e4505796001 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc @@ -5,15 +5,15 @@ namespace driver { namespace spi { -OdbcException::OdbcException(std::string message) +DriverException::DriverException(std::string message) : message_(std::move(message)) {} -const char *OdbcException::what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { +const char *DriverException::what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { return message_.c_str(); } AuthenticationException::AuthenticationException(std::string message) - : OdbcException(std::move(message)) {} + : DriverException(std::move(message)) {} } // namespace spi } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h index 73fb6f2bd0fc1..1fa2af07e12d0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h @@ -6,9 +6,10 @@ namespace driver { namespace spi { -class OdbcException : public std::exception { +/// \brief Base for all driver specific exceptions +class DriverException : public std::exception { public: - explicit OdbcException(std::string message); + explicit DriverException(std::string message); const char *what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW override; @@ -16,7 +17,8 @@ class OdbcException : public std::exception { const std::string message_; }; -class AuthenticationException : public OdbcException { +/// \brief Authentication specific exception +class AuthenticationException : public DriverException { public: explicit AuthenticationException(std::string message); }; From d5df520422591f7897f12b75e3c3dea77357139a Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 23 Nov 2021 13:41:16 -0300 Subject: [PATCH 031/183] Make sure properties are consistent with JDBC Change-Id: If46d773ac4c52e010e6c1fb8aff93e9de24f1d84 --- .../flightsql-odbc/flight_sql/flight_sql_connection.cc | 6 +++--- .../flightsql-odbc/spi/connection.cc | 10 +++++----- .../flightsql-odbc/spi/connection.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 216cad4c985ad..34b09a987dff2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -69,7 +69,7 @@ FlightCallOptions FlightSqlConnection::BuildCallOptions() { FlightClientOptions FlightSqlConnection::GetFlightClientOptions( const std::map &properties) { FlightClientOptions options; - // TODO: Set up SSL properties + // TODO: Set up TLS properties return options; } @@ -79,8 +79,8 @@ Location FlightSqlConnection::GetLocation( const int &port = boost::get(properties.at(PORT)); Location location; - const auto &it_use_ssl = properties.find(USE_SSL); - if (it_use_ssl != properties.end() && boost::get(it_use_ssl->second)) { + const auto &it_use_tls = properties.find(USE_TLS); + if (it_use_tls != properties.end() && boost::get(it_use_tls->second)) { ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); } else { ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc index c35adf7bea6bb..d59d8859df47b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc @@ -3,11 +3,11 @@ namespace driver { namespace spi { -const std::string Connection::HOST = "HOST"; -const std::string Connection::PORT = "PORT"; -const std::string Connection::USER = "USER"; -const std::string Connection::PASSWORD = "PASSWORD"; -const std::string Connection::USE_SSL = "USE_SSL"; +const std::string Connection::HOST = "host"; +const std::string Connection::PORT = "port"; +const std::string Connection::USER = "user"; +const std::string Connection::PASSWORD = "password"; +const std::string Connection::USE_TLS = "useTls"; } // namespace spi } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h index dc8b3e160276f..4e6fbe2ec4828 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h @@ -39,7 +39,7 @@ class Connection { static const std::string PORT; static const std::string USER; static const std::string PASSWORD; - static const std::string USE_SSL; + static const std::string USE_TLS; // TODO: Add properties for getting the certificates // TODO: Check if gRPC can use the system truststore, if not copy from Drill From 9af64d3a81ba6ff898d5104bb11e7d61adef9e0f Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 23 Nov 2021 13:43:09 -0300 Subject: [PATCH 032/183] Close connections on tests Change-Id: I13b0b7c513ba42a5e724e635c3a71123f99b0014 --- .../flight_sql/flight_sql_connection.cc | 10 +++--- .../flight_sql/flight_sql_connection.h | 10 ++++-- .../flight_sql/flight_sql_connection_test.cc | 33 +++++++++++++++---- .../flightsql-odbc/spi/exceptions.cc | 4 +-- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 34b09a987dff2..50a9262bb828a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -30,8 +30,8 @@ void FlightSqlConnection::Connect( const std::map &properties, std::vector &missing_attr) { try { - Location location = GetLocation(properties); - FlightClientOptions client_options = GetFlightClientOptions(properties); + Location location = BuildLocation(properties); + FlightClientOptions client_options = BuildFlightClientOptions(properties); std::unique_ptr flight_client; ThrowIfNotOK( @@ -66,14 +66,14 @@ FlightCallOptions FlightSqlConnection::BuildCallOptions() { return call_options; } -FlightClientOptions FlightSqlConnection::GetFlightClientOptions( +FlightClientOptions FlightSqlConnection::BuildFlightClientOptions( const std::map &properties) { FlightClientOptions options; - // TODO: Set up TLS properties + // TODO: Set up TLS properties return options; } -Location FlightSqlConnection::GetLocation( +Location FlightSqlConnection::BuildLocation( const std::map &properties) { const std::string &host = boost::get(properties.at(HOST)); const int &port = boost::get(properties.at(PORT)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 1bbb63a4a0c96..1b739e4a481f1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -32,12 +32,18 @@ class FlightSqlConnection : public spi::Connection { Info GetInfo(uint16_t info_type) override; + /// \brief Builds a Location used for FlightClient connection. + /// \note Visible for testing static arrow::flight::Location - GetLocation(const std::map &properties); + BuildLocation(const std::map &properties); + /// \brief Builds a FlightClientOptions used for FlightClient connection. + /// \note Visible for testing static arrow::flight::FlightClientOptions - GetFlightClientOptions(const std::map &properties); + BuildFlightClientOptions(const std::map &properties); + /// \brief Builds a FlightCallOptions used on gRPC calls. + /// \note Visible for testing arrow::flight::FlightCallOptions BuildCallOptions(); }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 30b978f68dff1..f2a58ab1d8a69 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -27,6 +27,8 @@ TEST(AttributeTests, SetAndGetAttribute) { EXPECT_TRUE(changeValue.has_value()); EXPECT_EQ(boost::get(changeValue.value()), 300); + + connection.Close(); } TEST(AttributeTests, GetAttributeWithoutSetting) { @@ -40,12 +42,12 @@ TEST(AttributeTests, GetAttributeWithoutSetting) { connection.Close(); } -TEST(ConnectTests, GetLocationTcp) { - const Location &actual_location1 = FlightSqlConnection::GetLocation({ +TEST(BuildLocationTests, ForTcp) { + const Location &actual_location1 = FlightSqlConnection::BuildLocation({ {Connection::HOST, std::string("localhost")}, {Connection::PORT, 32010}, }); - const Location &actual_location2 = FlightSqlConnection::GetLocation({ + const Location &actual_location2 = FlightSqlConnection::BuildLocation({ {Connection::HOST, std::string("localhost")}, {Connection::PORT, 32011}, }); @@ -55,15 +57,32 @@ TEST(ConnectTests, GetLocationTcp) { Location::ForGrpcTcp("localhost", 32010, &expected_location).ok()); ASSERT_EQ(expected_location, actual_location1); ASSERT_NE(expected_location, actual_location2); +} + +TEST(BuildLocationTests, ForTls) { + const Location &actual_location1 = FlightSqlConnection::BuildLocation({ + {Connection::HOST, std::string("localhost")}, + {Connection::PORT, 32010}, + {Connection::USE_TLS, true}, + }); + const Location &actual_location2 = FlightSqlConnection::BuildLocation({ + {Connection::HOST, std::string("localhost")}, + {Connection::PORT, 32011}, + {Connection::USE_TLS, true}, + }); - // TODO: Add tests for SSL + Location expected_location; + ASSERT_TRUE( + Location::ForGrpcTls("localhost", 32010, &expected_location).ok()); + ASSERT_EQ(expected_location, actual_location1); + ASSERT_NE(expected_location, actual_location2); } -TEST(ConnectTests, BuildCallOptions) { +TEST(BuildCallOptionsTest, ConnectionTimeout) { FlightSqlConnection connection(spi::V_3); - ASSERT_EQ(arrow::flight::TimeoutDuration{-1.0}, - connection.BuildCallOptions().timeout); + // Expect default timeout to be -1 + ASSERT_EQ(TimeoutDuration{-1.0}, connection.BuildCallOptions().timeout); connection.SetAttribute(Connection::CONNECTION_TIMEOUT, 10.0); ASSERT_EQ(TimeoutDuration{10.0}, connection.BuildCallOptions().timeout); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc index c1e4505796001..2d65f46e1c29c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc @@ -1,5 +1,4 @@ #include "exceptions.h" - #include namespace driver { @@ -8,7 +7,8 @@ namespace spi { DriverException::DriverException(std::string message) : message_(std::move(message)) {} -const char *DriverException::what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { +const char * +DriverException::what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { return message_.c_str(); } From cf26bb50912725ca1ab0285b81bb3009455d60d8 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 23 Nov 2021 17:40:23 -0300 Subject: [PATCH 033/183] Add Apache license to all files Change-Id: I2ced061bc40c5f93bdb2e3197bbec24605448835 --- .../flightsql-odbc/CMakeLists.txt | 17 +++++++++++++++++ .../flightsql-odbc/flight_sql/CMakeLists.txt | 17 +++++++++++++++++ .../flight_sql/flight_sql_auth_method.cc | 17 +++++++++++++++++ .../flight_sql/flight_sql_auth_method.h | 17 +++++++++++++++++ .../flight_sql/flight_sql_connection.cc | 17 +++++++++++++++++ .../flight_sql/flight_sql_connection.h | 17 +++++++++++++++++ .../flight_sql/flight_sql_connection_test.cc | 17 +++++++++++++++++ .../flight_sql/flight_sql_driver.cc | 17 +++++++++++++++++ .../flight_sql/flight_sql_driver.h | 17 +++++++++++++++++ .../flightsql-odbc/flight_sql/main.cc | 17 +++++++++++++++++ .../flightsql-odbc/spi/CMakeLists.txt | 17 +++++++++++++++++ .../flightsql-odbc/spi/connection.cc | 17 +++++++++++++++++ .../flightsql-odbc/spi/connection.h | 17 +++++++++++++++++ .../flightsql-odbc/spi/driver.h | 17 +++++++++++++++++ .../flightsql-odbc/spi/exceptions.cc | 17 +++++++++++++++++ .../flightsql-odbc/spi/exceptions.h | 17 +++++++++++++++++ .../flightsql-odbc/spi/types.h | 17 +++++++++++++++++ 17 files changed, 289 insertions(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index 682e644022f3a..dc8a1ae13bd5d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -1,3 +1,20 @@ +# 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.11) set(CMAKE_CXX_STANDARD 11) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index ba7b96d195954..f7e4be1721765 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -1,3 +1,20 @@ +# 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.11) set(CMAKE_CXX_STANDARD 11) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 33a20beb56317..f988ade87157d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -1,3 +1,20 @@ +// 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 "flight_sql_auth_method.h" #include "exceptions.h" #include "flight_sql_connection.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index 4f8757548579b..4a5acb352228e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -1,3 +1,20 @@ +// 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. + #pragma once #include "connection.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 50a9262bb828a..87f5b10b308d6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -1,3 +1,20 @@ +// 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 "flight_sql_connection.h" #include "exceptions.h" #include "flight_sql_auth_method.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 1b739e4a481f1..3faf3f52d0e59 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -1,3 +1,20 @@ +// 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. + #pragma once #include "connection.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index f2a58ab1d8a69..e1e87f72eaba5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -1,3 +1,20 @@ +// 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 "flight_sql_connection.h" #include "gtest/gtest.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index dd72419d698d4..a711b432528c8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -1,3 +1,20 @@ +// 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 "flight_sql_driver.h" #include "flight_sql_connection.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h index e6e9d21c938e4..1dd6930e55997 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h @@ -1,3 +1,20 @@ +// 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. + #pragma once #include "driver.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index eefbebc6bb552..024488ac47cc3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -1,3 +1,20 @@ +// 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 "flight_sql_driver.h" #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt index ee640709a78c6..6c9e634629de6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt @@ -1,3 +1,20 @@ +# 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(FindODBC) add_library(spi connection.cc exceptions.cc) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc index d59d8859df47b..6c4e0c916ea01 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc @@ -1,3 +1,20 @@ +// 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 "connection.h" namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h index 4e6fbe2ec4828..4d6de406f0bdf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h @@ -1,3 +1,20 @@ +// 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 diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/driver.h index dc846816a0bde..6cc9034868c94 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/driver.h @@ -1,3 +1,20 @@ +// 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 "connection.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc index 2d65f46e1c29c..c97976be44be5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc @@ -1,3 +1,20 @@ +// 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 "exceptions.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h index 1fa2af07e12d0..1a28192e7b585 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h @@ -1,3 +1,20 @@ +// 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 diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/types.h index bff93d4fb9c5e..b76a47c1d1303 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/types.h @@ -1,3 +1,20 @@ +// 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. + #pragma once namespace driver { From 03c29ae67e481caac969dd8a207152a821093009 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Wed, 24 Nov 2021 15:03:30 -0300 Subject: [PATCH 034/183] Fix minor issues Change-Id: Ieb28b13ec901cdadfd98b1dc550aa1de8d4259e5 --- .../flightsql-odbc/flight_sql/flight_sql_auth_method.cc | 8 +++++--- .../flightsql-odbc/flight_sql/flight_sql_connection.cc | 4 ++++ .../flightsql-odbc/flight_sql/flight_sql_connection.h | 8 ++++---- .../flightsql-odbc/flight_sql/main.cc | 1 + .../flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h | 4 ++-- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index f988ade87157d..71de1dbf6ae30 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -26,6 +26,9 @@ using namespace driver::flight_sql; +namespace driver { +namespace flight_sql { + using arrow::Result; using arrow::flight::FlightCallOptions; using arrow::flight::FlightClient; @@ -33,6 +36,7 @@ using arrow::flight::TimeoutDuration; using driver::spi::AuthenticationException; using driver::spi::Connection; +namespace { class NoOpAuthMethod : public FlightSqlAuthMethod { public: void Authenticate(FlightSqlConnection &connection, @@ -78,9 +82,7 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { std::string user_; std::string password_; }; - -namespace driver { -namespace flight_sql { +} // namespace std::unique_ptr FlightSqlAuthMethod::FromProperties( const std::unique_ptr &client, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 87f5b10b308d6..a747190ce4538 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -37,12 +37,16 @@ using spi::DriverException; using spi::OdbcVersion; using spi::Statement; +namespace { + inline void ThrowIfNotOK(const Status &status) { if (!status.ok()) { throw DriverException(status.ToString()); } } +} // namespace + void FlightSqlConnection::Connect( const std::map &properties, std::vector &missing_attr) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 3faf3f52d0e59..076486132cea1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -26,11 +26,11 @@ namespace flight_sql { class FlightSqlConnection : public spi::Connection { private: - bool closed_; - spi::OdbcVersion odbc_version_; - std::unique_ptr sql_client_; - arrow::flight::FlightCallOptions call_options_; std::map attribute_; + arrow::flight::FlightCallOptions call_options_; + std::unique_ptr sql_client_; + spi::OdbcVersion odbc_version_; + bool closed_; public: explicit FlightSqlConnection(spi::OdbcVersion odbc_version); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 024488ac47cc3..8aec9848b8fa3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -43,5 +43,6 @@ int main() { std::vector missing_attr; connection->Connect(properties, missing_attr); + connection->Close(); return 0; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h index 1a28192e7b585..d97b735e11160 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h @@ -15,11 +15,11 @@ // specific language governing permissions and limitations // under the License. +#pragma once + #include #include -#pragma once - namespace driver { namespace spi { From 8a23700a44704b9272282e2cf36e01e7119052f1 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Fri, 26 Nov 2021 13:55:27 -0300 Subject: [PATCH 035/183] Improve catch block on flight_sql_connection.cc Change-Id: I90419e19fe64065a6b4ccbf9d6f28b7589b94bf4 --- .../flightsql-odbc/flight_sql/flight_sql_connection.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index a747190ce4538..8c8330370cce6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -66,11 +66,11 @@ void FlightSqlConnection::Connect( SetAttribute(CONNECTION_DEAD, false); call_options_ = BuildCallOptions(); - } catch (std::exception &e) { + } catch (...) { SetAttribute(CONNECTION_DEAD, true); sql_client_.reset(); - throw e; + throw; } } From 66711cdb25dfd0b70a3cd4a9fec855cc66e9764a Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 7 Jan 2022 10:47:27 -0800 Subject: [PATCH 036/183] Fix mac build issues - Update references to Flight-SQL code to use current version from Arrow-master - Fix up detection of dependencies such as Boost, OpenSSL, Arrow, Protobuf, GRPC, Zlib. Automatically pull Arrow, Boost, and Google Test - Fix use of GCC-specific keywords in code --- .../flightsql-odbc/.gitignore | 9 ++ .../flightsql-odbc/CMakeLists.txt | 15 +++ .../flightsql-odbc/flight_sql/CMakeLists.txt | 106 ++++++++++++++++-- .../flight_sql/flight_sql_connection.h | 2 +- .../flightsql-odbc/flight_sql/main.cc | 2 +- .../flightsql-odbc/spi/CMakeLists.txt | 6 + .../flightsql-odbc/spi/exceptions.cc | 2 +- .../flightsql-odbc/spi/exceptions.h | 2 +- 8 files changed, 128 insertions(+), 16 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore index c8c0f0a42c1e5..f2f4387daf9eb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore @@ -27,3 +27,12 @@ cmake-build-*/ .idea vcpkg_installed +*-prefix +_deps +lib + +build.* +.ninja_* +*lib*.a +*arrow_odbc_spi_impl_cli +*arrow_odbc_spi_impl_test diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index dc8a1ae13bd5d..037b6fcb9fad6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -20,5 +20,20 @@ set(CMAKE_CXX_STANDARD 11) project(flightsql_odbc) +# Add Boost dependencies. Should be pre-installed (Brew on Mac). +find_package(Boost REQUIRED) +include_directories(${Boost_INCLUDE_DIRS}) + +# 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/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.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(spi) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index f7e4be1721765..870654d2f7463 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -21,22 +21,104 @@ set(CMAKE_CXX_STANDARD 11) include_directories(${CMAKE_SOURCE_DIR}/spi) SET(Arrow_STATIC ON) -find_package(Arrow REQUIRED) -find_package(ArrowFlight REQUIRED PATHS /usr/local/lib/cmake/arrow/) -find_package(ArrowFlightSql REQUIRED PATHS /usr/local/lib/cmake/arrow/) -find_package(GTest REQUIRED) + +# Get Arrow using git. +include(ExternalProject) + +set(ARROW_CMAKE_ARGS +# -DCMAKE_TOOLCHAIN_FILE=${DEPENDENCY_PATH} + -DARROW_FLIGHT=ON + -DARROW_FLIGHT_SQL=ON + -DARROW_IPC=ON + -DARROW_COMPUTE=OFF + -DARROW_BUILD_SHARED=OFF + -DARROW_BUILD_STATIC=ON + -DARROW_COMPUTE=ON + -DARROW_BUILD_TESTS=OFF +# -DARROW_DEPENDENCY_SOURCE=VCPKG + -DARROW_DEPENDENCY_USE_SHARED=OFF + -DCMAKE_DEPENDS_USE_COMPILER=FALSE + -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install + ${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow/cpp +) + +ExternalProject_Add(ApacheArrow + GIT_REPOSITORY https://github.com/apache/arrow.git + CMAKE_ARGS ${ARROW_CMAKE_ARGS}) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install/include) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install/lib) + +# Add Zlib dependencies needed by Arrow Flight. Should be pre-installed. +find_package(ZLIB REQUIRED) + +# Add Protobuf dependencies needed by Arrow Flight. Should be pre-installed. +set(Protobuf_USE_STATIC_LIBS ON) +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) + set(OPENSSL_ROOT_DIR /usr/local/Cellar/openssl@1.1/1.1.1m) +endif() +set(OpenSSL_USE_STATIC_LIBS ON) +set(OPENSSL_USE_STATIC_LIBS ON) +find_package(OpenSSL REQUIRED) + +# Add gRPC dependencies needed by Arrow Flight. Should be pre-installed. +find_package(gRPC 1.36 CONFIG REQUIRED) enable_testing() -add_library(flight_odbc_driver flight_sql_driver.cc flight_sql_connection.cc flight_sql_auth_method.cc) -target_link_libraries(flight_odbc_driver spi arrow_static arrow_flight arrow_flight_sql) -target_include_directories(flight_odbc_driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +set(ARROW_ODBC_SPI_SOURCES + flight_sql_driver.cc + flight_sql_connection.cc + flight_sql_auth_method.cc +) + +set(ARROW_ODBC_SPI_THIRDPARTY_LIBS + arrow + arrow_flight + arrow_flight_sql + arrow_bundled_dependencies + ${ZLIB_LIBRARIES} + ${Protobuf_LIBRARIES} + gRPC::grpc++ +) + +add_library(arrow_odbc_spi_impl ${ARROW_ODBC_SPI_SOURCES}) +add_dependencies(arrow_odbc_spi_impl ApacheArrow) + +set_target_properties(arrow_odbc_spi_impl + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib + ) + +target_link_libraries(arrow_odbc_spi_impl spi ${ARROW_ODBC_SPI_THIRDPARTY_LIBS}) +target_include_directories(arrow_odbc_spi_impl PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) # CLI -add_executable(flight_odbc_driver_cli main.cc) -target_link_libraries(flight_odbc_driver_cli flight_odbc_driver) +add_executable(arrow_odbc_spi_impl_cli main.cc) +set_target_properties(arrow_odbc_spi_impl_cli + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/bin + ) +target_link_libraries(arrow_odbc_spi_impl_cli arrow_odbc_spi_impl) # Unit tests -add_executable(flight_odbc_driver_test flight_sql_connection_test.cc) -target_link_libraries(flight_odbc_driver_test flight_odbc_driver GTest::gtest GTest::gtest_main) -add_test(connection_test flight_odbc_driver_test) +set(ARROW_ODBC_SPI_TEST_SOURCES + flight_sql_connection_test.cc +) + +add_executable(arrow_odbc_spi_impl_test ${ARROW_ODBC_SPI_TEST_SOURCES}) +add_dependencies(arrow_odbc_spi_impl_test ApacheArrow) +set_target_properties(arrow_odbc_spi_impl_test + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test/$/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) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 076486132cea1..81fee8485737a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -19,7 +19,7 @@ #include "connection.h" #include -#include +#include namespace driver { namespace flight_sql { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 8aec9848b8fa3..aff19a4bee3c0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -17,7 +17,7 @@ #include "flight_sql_driver.h" #include -#include +#include #include using arrow::Status; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt index 6c9e634629de6..558cc2dbcb40d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt @@ -18,4 +18,10 @@ include(FindODBC) add_library(spi connection.cc exceptions.cc) +set_target_properties(spi + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib + ) target_link_libraries(spi ${ODBC_LIBRARIES}) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc index c97976be44be5..26daa725f0dd8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc @@ -25,7 +25,7 @@ DriverException::DriverException(std::string message) : message_(std::move(message)) {} const char * -DriverException::what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { +DriverException::what() const throw() { return message_.c_str(); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h index d97b735e11160..be3ab854304d8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h @@ -28,7 +28,7 @@ class DriverException : public std::exception { public: explicit DriverException(std::string message); - const char *what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW override; + const char *what() const throw() override; private: const std::string message_; From ea0751d9fca2991daadc00c511e811bc34f66b8a Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Mon, 10 Jan 2022 17:56:28 -0300 Subject: [PATCH 037/183] Fix linking issues when building with gcc Change-Id: Ic77e8da93e499b90c40838bafab01062e81cbd2b --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 870654d2f7463..75594e40a204d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -79,9 +79,9 @@ set(ARROW_ODBC_SPI_SOURCES ) set(ARROW_ODBC_SPI_THIRDPARTY_LIBS - arrow - arrow_flight arrow_flight_sql + arrow_flight + arrow arrow_bundled_dependencies ${ZLIB_LIBRARIES} ${Protobuf_LIBRARIES} From ba4d6cfe5c0accb9d9905cdd9d27b6274624735a Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Mon, 10 Jan 2022 18:32:44 -0300 Subject: [PATCH 038/183] Add CMake variables ARROW_GIT_REPOSITORY and ARROW_GIT_TAG to make it possible to use different repo and commit for building Arrow Change-Id: I6b1d1e2b1f23906a3bd17c803b9586b6b4c9a832 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 75594e40a204d..330afc0b13d73 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -42,8 +42,17 @@ set(ARROW_CMAKE_ARGS ${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow/cpp ) +if(NOT ARROW_GIT_REPOSITORY) + set(ARROW_GIT_REPOSITORY https://github.com/apache/arrow.git) +endif() +if(NOT ARROW_GIT_TAG) + set(ARROW_GIT_TAG master) +endif() + +message("Using Arrow from ${ARROW_GIT_REPOSITORY} on tag ${ARROW_GIT_TAG}") ExternalProject_Add(ApacheArrow - GIT_REPOSITORY https://github.com/apache/arrow.git + GIT_REPOSITORY ${ARROW_GIT_REPOSITORY} + GIT_TAG ${ARROW_GIT_TAG} CMAKE_ARGS ${ARROW_CMAKE_ARGS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install/include) From a800cc03e829ac10e5af7098ada149ea6e4b86d4 Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 10 Jan 2022 13:47:46 -0800 Subject: [PATCH 039/183] Address code review comments --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 330afc0b13d73..0620f6825ddbd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -26,7 +26,6 @@ SET(Arrow_STATIC ON) include(ExternalProject) set(ARROW_CMAKE_ARGS -# -DCMAKE_TOOLCHAIN_FILE=${DEPENDENCY_PATH} -DARROW_FLIGHT=ON -DARROW_FLIGHT_SQL=ON -DARROW_IPC=ON @@ -35,7 +34,6 @@ set(ARROW_CMAKE_ARGS -DARROW_BUILD_STATIC=ON -DARROW_COMPUTE=ON -DARROW_BUILD_TESTS=OFF -# -DARROW_DEPENDENCY_SOURCE=VCPKG -DARROW_DEPENDENCY_USE_SHARED=OFF -DCMAKE_DEPENDS_USE_COMPILER=FALSE -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install @@ -72,6 +70,8 @@ find_package(Protobuf REQUIRED) if (NOT DEFINED OPENSSL_ROOT_DIR AND DEFINED APPLE) 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. set(OpenSSL_USE_STATIC_LIBS ON) set(OPENSSL_USE_STATIC_LIBS ON) find_package(OpenSSL REQUIRED) From c4e4239f79cae33aa12cb4af3f97ea6df4b9fb83 Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 10 Jan 2022 13:49:51 -0800 Subject: [PATCH 040/183] Tidy up indentation --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 0620f6825ddbd..e6653f79b1703 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -26,18 +26,18 @@ SET(Arrow_STATIC ON) include(ExternalProject) set(ARROW_CMAKE_ARGS - -DARROW_FLIGHT=ON - -DARROW_FLIGHT_SQL=ON - -DARROW_IPC=ON - -DARROW_COMPUTE=OFF - -DARROW_BUILD_SHARED=OFF - -DARROW_BUILD_STATIC=ON - -DARROW_COMPUTE=ON - -DARROW_BUILD_TESTS=OFF - -DARROW_DEPENDENCY_USE_SHARED=OFF - -DCMAKE_DEPENDS_USE_COMPILER=FALSE - -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install - ${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow/cpp + -DARROW_FLIGHT=ON + -DARROW_FLIGHT_SQL=ON + -DARROW_IPC=ON + -DARROW_COMPUTE=OFF + -DARROW_BUILD_SHARED=OFF + -DARROW_BUILD_STATIC=ON + -DARROW_COMPUTE=ON + -DARROW_BUILD_TESTS=OFF + -DARROW_DEPENDENCY_USE_SHARED=OFF + -DCMAKE_DEPENDS_USE_COMPILER=FALSE + -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install + ${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow/cpp ) if(NOT ARROW_GIT_REPOSITORY) @@ -49,9 +49,9 @@ endif() message("Using Arrow from ${ARROW_GIT_REPOSITORY} on tag ${ARROW_GIT_TAG}") ExternalProject_Add(ApacheArrow - GIT_REPOSITORY ${ARROW_GIT_REPOSITORY} - GIT_TAG ${ARROW_GIT_TAG} - CMAKE_ARGS ${ARROW_CMAKE_ARGS}) + GIT_REPOSITORY ${ARROW_GIT_REPOSITORY} + GIT_TAG ${ARROW_GIT_TAG} + CMAKE_ARGS ${ARROW_CMAKE_ARGS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install/include) link_directories(${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install/lib) @@ -101,11 +101,11 @@ add_library(arrow_odbc_spi_impl ${ARROW_ODBC_SPI_SOURCES}) add_dependencies(arrow_odbc_spi_impl ApacheArrow) set_target_properties(arrow_odbc_spi_impl - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib - ) + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib +) target_link_libraries(arrow_odbc_spi_impl spi ${ARROW_ODBC_SPI_THIRDPARTY_LIBS}) target_include_directories(arrow_odbc_spi_impl PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) @@ -113,9 +113,9 @@ 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}/$/bin - ) + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/bin +) target_link_libraries(arrow_odbc_spi_impl_cli arrow_odbc_spi_impl) # Unit tests @@ -126,8 +126,8 @@ set(ARROW_ODBC_SPI_TEST_SOURCES add_executable(arrow_odbc_spi_impl_test ${ARROW_ODBC_SPI_TEST_SOURCES}) add_dependencies(arrow_odbc_spi_impl_test ApacheArrow) set_target_properties(arrow_odbc_spi_impl_test - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test/$/bin - ) + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test/$/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) From e9dc6ecb4f1e91aeae237a1471c050203d8e6a85 Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 13 Jan 2022 15:45:18 -0800 Subject: [PATCH 041/183] Restructure for public headers The library is difficult to use due to some header names being common (such as "connection.h"). Move headers that are intended to be exposed to an include/ directory and have code reference the sub-project directory when referencing public headers to avoid potential conflicts. Rename the spi module to odbcabstraction to make it less generic. --- .../flightsql-odbc/CMakeLists.txt | 2 +- .../flightsql-odbc/flight_sql/CMakeLists.txt | 9 +++++++-- .../flight_sql/flight_sql_auth_method.cc | 7 ++++--- .../flight_sql/flight_sql_auth_method.h | 4 ++-- .../flight_sql/flight_sql_connection.cc | 11 ++++++----- .../flightsql-odbc/flight_sql/flight_sql_connection.h | 11 ++++++----- .../flight_sql/flight_sql_connection_test.cc | 8 ++++---- .../flightsql-odbc/flight_sql/flight_sql_driver.cc | 6 +++--- .../{ => include/flight_sql}/flight_sql_driver.h | 8 ++++---- .../flightsql-odbc/flight_sql/main.cc | 7 ++++--- .../{spi => odbcabstraction}/CMakeLists.txt | 7 ++++--- .../{spi => odbcabstraction}/connection.cc | 6 +++--- .../{spi => odbcabstraction}/exceptions.cc | 6 +++--- .../include/odbcabstraction}/connection.h | 4 ++-- .../include/odbcabstraction}/driver.h | 6 +++--- .../include/odbcabstraction}/exceptions.h | 4 ++-- .../include/odbcabstraction}/types.h | 4 ++-- 17 files changed, 60 insertions(+), 50 deletions(-) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/{ => include/flight_sql}/flight_sql_driver.h (81%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{spi => odbcabstraction}/CMakeLists.txt (84%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{spi => odbcabstraction}/connection.cc (91%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{spi => odbcabstraction}/exceptions.cc (92%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{spi => odbcabstraction/include/odbcabstraction}/connection.h (98%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{spi => odbcabstraction/include/odbcabstraction}/driver.h (92%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{spi => odbcabstraction/include/odbcabstraction}/exceptions.h (95%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/{spi => odbcabstraction/include/odbcabstraction}/types.h (94%) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index 037b6fcb9fad6..d4967e22f2634 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -36,4 +36,4 @@ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) add_subdirectory(flight_sql) -add_subdirectory(spi) +add_subdirectory(odbcabstraction) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index e6653f79b1703..7b04d2cf39846 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -18,7 +18,9 @@ cmake_minimum_required(VERSION 3.11) set(CMAKE_CXX_STANDARD 11) -include_directories(${CMAKE_SOURCE_DIR}/spi) +include_directories( + include + ${CMAKE_SOURCE_DIR}/odbcabstraction/include) SET(Arrow_STATIC ON) @@ -107,7 +109,10 @@ set_target_properties(arrow_odbc_spi_impl RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib ) -target_link_libraries(arrow_odbc_spi_impl spi ${ARROW_ODBC_SPI_THIRDPARTY_LIBS}) +target_link_libraries( + arrow_odbc_spi_impl + odbcabstraction + ${ARROW_ODBC_SPI_THIRDPARTY_LIBS}) target_include_directories(arrow_odbc_spi_impl PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) # CLI diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 71de1dbf6ae30..73b2fae298f23 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -16,7 +16,8 @@ // under the License. #include "flight_sql_auth_method.h" -#include "exceptions.h" + +#include #include "flight_sql_connection.h" #include @@ -33,8 +34,8 @@ using arrow::Result; using arrow::flight::FlightCallOptions; using arrow::flight::FlightClient; using arrow::flight::TimeoutDuration; -using driver::spi::AuthenticationException; -using driver::spi::Connection; +using driver::odbcabstraction::AuthenticationException; +using driver::odbcabstraction::Connection; namespace { class NoOpAuthMethod : public FlightSqlAuthMethod { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index 4a5acb352228e..f557d248a9ed5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -17,7 +17,7 @@ #pragma once -#include "connection.h" +#include #include "flight_sql_connection.h" #include #include @@ -35,7 +35,7 @@ class FlightSqlAuthMethod { static std::unique_ptr FromProperties( const std::unique_ptr &client, - const std::map &properties); + const std::map &properties); protected: FlightSqlAuthMethod() = default; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 8c8330370cce6..0ad67d232c37e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -16,7 +16,8 @@ // under the License. #include "flight_sql_connection.h" -#include "exceptions.h" + +#include #include "flight_sql_auth_method.h" #include #include @@ -32,10 +33,10 @@ using arrow::flight::FlightClientOptions; using arrow::flight::Location; using arrow::flight::TimeoutDuration; using arrow::flight::sql::FlightSqlClient; -using spi::Connection; -using spi::DriverException; -using spi::OdbcVersion; -using spi::Statement; +using driver::odbcabstraction::Connection; +using driver::odbcabstraction::DriverException; +using driver::odbcabstraction::OdbcVersion; +using driver::odbcabstraction::Statement; namespace { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 81fee8485737a..f0dab0326f44c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -17,30 +17,31 @@ #pragma once -#include "connection.h" +#include + #include #include namespace driver { namespace flight_sql { -class FlightSqlConnection : public spi::Connection { +class FlightSqlConnection : public odbcabstraction::Connection { private: std::map attribute_; arrow::flight::FlightCallOptions call_options_; std::unique_ptr sql_client_; - spi::OdbcVersion odbc_version_; + odbcabstraction::OdbcVersion odbc_version_; bool closed_; public: - explicit FlightSqlConnection(spi::OdbcVersion odbc_version); + explicit FlightSqlConnection(odbcabstraction::OdbcVersion odbc_version); void Connect(const std::map &properties, std::vector &missing_attr) override; void Close() override; - std::shared_ptr CreateStatement() override; + std::shared_ptr CreateStatement() override; void SetAttribute(AttributeId attribute, const Attribute &value) override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index e1e87f72eaba5..b4858452f03ac 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -24,10 +24,10 @@ namespace flight_sql { using arrow::flight::Location; using arrow::flight::TimeoutDuration; -using spi::Connection; +using odbcabstraction::Connection; TEST(AttributeTests, SetAndGetAttribute) { - FlightSqlConnection connection(spi::V_3); + FlightSqlConnection connection(odbcabstraction::V_3); connection.SetAttribute(Connection::CONNECTION_TIMEOUT, 200); const boost::optional firstValue = @@ -49,7 +49,7 @@ TEST(AttributeTests, SetAndGetAttribute) { } TEST(AttributeTests, GetAttributeWithoutSetting) { - FlightSqlConnection connection(spi::V_3); + FlightSqlConnection connection(odbcabstraction::V_3); const boost::optional anOptional = connection.GetAttribute(Connection::CONNECTION_TIMEOUT); @@ -96,7 +96,7 @@ TEST(BuildLocationTests, ForTls) { } TEST(BuildCallOptionsTest, ConnectionTimeout) { - FlightSqlConnection connection(spi::V_3); + FlightSqlConnection connection(odbcabstraction::V_3); // Expect default timeout to be -1 ASSERT_EQ(TimeoutDuration{-1.0}, connection.BuildCallOptions().timeout); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index a711b432528c8..4bbc627223fc1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -15,14 +15,14 @@ // specific language governing permissions and limitations // under the License. -#include "flight_sql_driver.h" +#include #include "flight_sql_connection.h" namespace driver { namespace flight_sql { -using spi::Connection; -using spi::OdbcVersion; +using odbcabstraction::Connection; +using odbcabstraction::OdbcVersion; std::shared_ptr FlightSqlDriver::CreateConnection(OdbcVersion odbc_version) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h similarity index 81% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h index 1dd6930e55997..506fd5c3fff04 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h @@ -17,15 +17,15 @@ #pragma once -#include "driver.h" +#include namespace driver { namespace flight_sql { -class FlightSqlDriver : public spi::Driver { +class FlightSqlDriver : public odbcabstraction::Driver { public: - std::shared_ptr - CreateConnection(spi::OdbcVersion odbc_version) override; + std::shared_ptr + CreateConnection(odbcabstraction::OdbcVersion odbc_version) override; }; }; // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index aff19a4bee3c0..0fcf484c72d6b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -15,7 +15,8 @@ // specific language governing permissions and limitations // under the License. -#include "flight_sql_driver.h" +#include + #include #include #include @@ -26,13 +27,13 @@ using arrow::flight::Location; using arrow::flight::sql::FlightSqlClient; using driver::flight_sql::FlightSqlDriver; -using driver::spi::Connection; +using driver::odbcabstraction::Connection; int main() { FlightSqlDriver driver; const std::shared_ptr &connection = - driver.CreateConnection(driver::spi::V_3); + driver.CreateConnection(driver::odbcabstraction::V_3); std::map properties = { {Connection::HOST, std::string("0.0.0.0")}, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt similarity index 84% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index 558cc2dbcb40d..039bfc55821f4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -17,11 +17,12 @@ include(FindODBC) -add_library(spi connection.cc exceptions.cc) -set_target_properties(spi +include_directories(include) +add_library(odbcabstraction connection.cc exceptions.cc) +set_target_properties(odbcabstraction PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib ) -target_link_libraries(spi ${ODBC_LIBRARIES}) +target_link_libraries(odbcabstraction ${ODBC_LIBRARIES}) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/connection.cc similarity index 91% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/connection.cc index 6c4e0c916ea01..e5f40a71f8076 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/connection.cc @@ -15,10 +15,10 @@ // specific language governing permissions and limitations // under the License. -#include "connection.h" +#include namespace driver { -namespace spi { +namespace odbcabstraction { const std::string Connection::HOST = "host"; const std::string Connection::PORT = "port"; @@ -26,5 +26,5 @@ const std::string Connection::USER = "user"; const std::string Connection::PASSWORD = "password"; const std::string Connection::USE_TLS = "useTls"; -} // namespace spi +} // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc similarity index 92% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc index 26daa725f0dd8..34b1bdd14b5d6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc @@ -15,11 +15,11 @@ // specific language governing permissions and limitations // under the License. -#include "exceptions.h" +#include #include namespace driver { -namespace spi { +namespace odbcabstraction { DriverException::DriverException(std::string message) : message_(std::move(message)) {} @@ -32,5 +32,5 @@ DriverException::what() const throw() { AuthenticationException::AuthenticationException(std::string message) : DriverException(std::move(message)) {} -} // namespace spi +} // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h similarity index 98% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index 4d6de406f0bdf..a118f0996f55f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -25,7 +25,7 @@ #pragma once namespace driver { -namespace spi { +namespace odbcabstraction { class Statement; @@ -89,5 +89,5 @@ class Connection { Connection() = default; }; -} // namespace spi +} // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h similarity index 92% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/driver.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h index 6cc9034868c94..c526ca855cf38 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h @@ -17,13 +17,13 @@ #include -#include "connection.h" +#include #include "types.h" #pragma once namespace driver { -namespace spi { +namespace odbcabstraction { /// \brief High-level representation of an ODBC driver. class Driver { @@ -39,5 +39,5 @@ class Driver { Driver() = default; }; -} // namespace spi +} // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h similarity index 95% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h index be3ab854304d8..df1193979df5f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/exceptions.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h @@ -21,7 +21,7 @@ #include namespace driver { -namespace spi { +namespace odbcabstraction { /// \brief Base for all driver specific exceptions class DriverException : public std::exception { @@ -40,5 +40,5 @@ class AuthenticationException : public DriverException { explicit AuthenticationException(std::string message); }; -} // namespace spi +} // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h similarity index 94% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/types.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index b76a47c1d1303..626c1c26e02a8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/spi/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -18,10 +18,10 @@ #pragma once namespace driver { -namespace spi { +namespace odbcabstraction { /// \brief Supported ODBC versions. enum OdbcVersion { V_2, V_3, V_4 }; -} // namespace spi +} // namespace odbcabstraction } // namespace driver From 74d5ea4445b46a2b4c01a2ccf9dfa9f43ae22a42 Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 13 Jan 2022 15:58:22 -0800 Subject: [PATCH 042/183] Decouple arrow flight connection property names from abstraction interface Move arrow property constant names to the arrow flight implementation instead of being in the public interface headers. --- .../flight_sql/flight_sql_auth_method.cc | 4 +-- .../flight_sql/flight_sql_connection.cc | 8 +++++ .../flight_sql/flight_sql_connection.h | 7 +++++ .../flight_sql/flight_sql_connection_test.cc | 20 ++++++------- .../flightsql-odbc/flight_sql/main.cc | 10 ++++--- .../odbcabstraction/CMakeLists.txt | 5 +++- .../odbcabstraction/connection.cc | 30 ------------------- .../include/odbcabstraction/connection.h | 7 ----- 8 files changed, 37 insertions(+), 54 deletions(-) delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/connection.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 73b2fae298f23..9cb187d679188 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -90,8 +90,8 @@ std::unique_ptr FlightSqlAuthMethod::FromProperties( const std::map &properties) { // Check if should use user-password authentication - const auto &it_user = properties.find(Connection::USER); - const auto &it_password = properties.find(Connection::PASSWORD); + const auto &it_user = properties.find(FlightSqlConnection::USER); + const auto &it_password = properties.find(FlightSqlConnection::PASSWORD); if (it_user != properties.end() || it_password != properties.end()) { const std::string &user = it_user != properties.end() ? boost::get(it_user->second) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 0ad67d232c37e..657799d42acae 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -38,7 +38,15 @@ using driver::odbcabstraction::DriverException; using driver::odbcabstraction::OdbcVersion; using driver::odbcabstraction::Statement; +const std::string FlightSqlConnection::HOST = "host"; +const std::string FlightSqlConnection::PORT = "port"; +const std::string FlightSqlConnection::USER = "user"; +const std::string FlightSqlConnection::PASSWORD = "password"; +const std::string FlightSqlConnection::USE_TLS = "useTls"; + namespace { + // TODO: Add properties for getting the certificates + // TODO: Check if gRPC can use the system truststore, if not copy from Drill inline void ThrowIfNotOK(const Status &status) { if (!status.ok()) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index f0dab0326f44c..d2d57dd85b114 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -26,6 +26,7 @@ namespace driver { namespace flight_sql { class FlightSqlConnection : public odbcabstraction::Connection { + private: std::map attribute_; arrow::flight::FlightCallOptions call_options_; @@ -34,6 +35,12 @@ class FlightSqlConnection : public odbcabstraction::Connection { bool closed_; public: + static const std::string HOST; + static const std::string PORT; + static const std::string USER; + static const std::string PASSWORD; + static const std::string USE_TLS; + explicit FlightSqlConnection(odbcabstraction::OdbcVersion odbc_version); void Connect(const std::map &properties, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index b4858452f03ac..c8ba28eb3007d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -61,12 +61,12 @@ TEST(AttributeTests, GetAttributeWithoutSetting) { TEST(BuildLocationTests, ForTcp) { const Location &actual_location1 = FlightSqlConnection::BuildLocation({ - {Connection::HOST, std::string("localhost")}, - {Connection::PORT, 32010}, + {FlightSqlConnection::HOST, std::string("localhost")}, + {FlightSqlConnection::PORT, 32010}, }); const Location &actual_location2 = FlightSqlConnection::BuildLocation({ - {Connection::HOST, std::string("localhost")}, - {Connection::PORT, 32011}, + {FlightSqlConnection::HOST, std::string("localhost")}, + {FlightSqlConnection::PORT, 32011}, }); Location expected_location; @@ -78,14 +78,14 @@ TEST(BuildLocationTests, ForTcp) { TEST(BuildLocationTests, ForTls) { const Location &actual_location1 = FlightSqlConnection::BuildLocation({ - {Connection::HOST, std::string("localhost")}, - {Connection::PORT, 32010}, - {Connection::USE_TLS, true}, + {FlightSqlConnection::HOST, std::string("localhost")}, + {FlightSqlConnection::PORT, 32010}, + {FlightSqlConnection::USE_TLS, true}, }); const Location &actual_location2 = FlightSqlConnection::BuildLocation({ - {Connection::HOST, std::string("localhost")}, - {Connection::PORT, 32011}, - {Connection::USE_TLS, true}, + {FlightSqlConnection::HOST, std::string("localhost")}, + {FlightSqlConnection::PORT, 32011}, + {FlightSqlConnection::USE_TLS, true}, }); Location expected_location; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 0fcf484c72d6b..1b65b7f3826fb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -19,6 +19,7 @@ #include #include +#include "flight_sql_connection.h" #include using arrow::Status; @@ -27,6 +28,7 @@ using arrow::flight::Location; using arrow::flight::sql::FlightSqlClient; using driver::flight_sql::FlightSqlDriver; +using driver::flight_sql::FlightSqlConnection; using driver::odbcabstraction::Connection; int main() { @@ -36,10 +38,10 @@ int main() { driver.CreateConnection(driver::odbcabstraction::V_3); std::map properties = { - {Connection::HOST, std::string("0.0.0.0")}, - {Connection::PORT, 32010}, - {Connection::USER, std::string("user")}, - {Connection::PASSWORD, std::string("password")}, + {FlightSqlConnection::HOST, std::string("0.0.0.0")}, + {FlightSqlConnection::PORT, 32010}, + {FlightSqlConnection::USER, std::string("user")}, + {FlightSqlConnection::PASSWORD, std::string("password")}, }; std::vector missing_attr; connection->Connect(properties, missing_attr); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index 039bfc55821f4..d7ef830f383e9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -18,7 +18,10 @@ include(FindODBC) include_directories(include) -add_library(odbcabstraction connection.cc exceptions.cc) + +add_library(odbcabstraction + exceptions.cc) + set_target_properties(odbcabstraction PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/connection.cc deleted file mode 100644 index e5f40a71f8076..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/connection.cc +++ /dev/null @@ -1,30 +0,0 @@ -// 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 - -namespace driver { -namespace odbcabstraction { - -const std::string Connection::HOST = "host"; -const std::string Connection::PORT = "port"; -const std::string Connection::USER = "user"; -const std::string Connection::PASSWORD = "password"; -const std::string Connection::USE_TLS = "useTls"; - -} // namespace odbcabstraction -} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index a118f0996f55f..04e7430a74737 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -52,13 +52,6 @@ class Connection { typedef boost::variant Property; typedef boost::variant Info; - static const std::string HOST; - static const std::string PORT; - static const std::string USER; - static const std::string PASSWORD; - static const std::string USE_TLS; - // TODO: Add properties for getting the certificates - // TODO: Check if gRPC can use the system truststore, if not copy from Drill /// \brief Establish the connection. /// \param properties[in] properties used to establish the connection. From b76b4b9ede316e25db916edf2922dd96e1492e89 Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 14 Jan 2022 08:03:17 -0800 Subject: [PATCH 043/183] Make connection property map case-insensitve Make the connection property map case-insensitive since ODBC connection string properties are case-insensitive. Make the map a typedef. --- .../flight_sql/flight_sql_connection.cc | 6 +++--- .../flight_sql/flight_sql_connection.h | 6 +++--- .../include/odbcabstraction/connection.h | 12 +++++++++++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 657799d42acae..a27d6c476b74b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -57,7 +57,7 @@ inline void ThrowIfNotOK(const Status &status) { } // namespace void FlightSqlConnection::Connect( - const std::map &properties, + const ConnPropertyMap &properties, std::vector &missing_attr) { try { Location location = BuildLocation(properties); @@ -97,14 +97,14 @@ FlightCallOptions FlightSqlConnection::BuildCallOptions() { } FlightClientOptions FlightSqlConnection::BuildFlightClientOptions( - const std::map &properties) { + const ConnPropertyMap &properties) { FlightClientOptions options; // TODO: Set up TLS properties return options; } Location FlightSqlConnection::BuildLocation( - const std::map &properties) { + const ConnPropertyMap &properties) { const std::string &host = boost::get(properties.at(HOST)); const int &port = boost::get(properties.at(PORT)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index d2d57dd85b114..163cf146a726c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -43,7 +43,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { explicit FlightSqlConnection(odbcabstraction::OdbcVersion odbc_version); - void Connect(const std::map &properties, + void Connect(const ConnPropertyMap &properties, std::vector &missing_attr) override; void Close() override; @@ -60,12 +60,12 @@ class FlightSqlConnection : public odbcabstraction::Connection { /// \brief Builds a Location used for FlightClient connection. /// \note Visible for testing static arrow::flight::Location - BuildLocation(const std::map &properties); + BuildLocation(const ConnPropertyMap &properties); /// \brief Builds a FlightClientOptions used for FlightClient connection. /// \note Visible for testing static arrow::flight::FlightClientOptions - BuildFlightClientOptions(const std::map &properties); + BuildFlightClientOptions(const ConnPropertyMap &properties); /// \brief Builds a FlightCallOptions used on gRPC calls. /// \note Visible for testing diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index 04e7430a74737..1c532fd35cbbb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -48,15 +49,24 @@ class Connection { QUIET_MODE, // Lookup }; + /// \brief Case insensitive comparator + struct CaseInsensitiveComparator : std::binary_function + { + bool operator() (const std::string & s1, const std::string & s2) const { + return boost::lexicographical_compare(s1, s2, boost::is_iless()); + } + }; + typedef boost::variant Attribute; typedef boost::variant Property; typedef boost::variant Info; + typedef std::map ConnPropertyMap; /// \brief Establish the connection. /// \param properties[in] properties used to establish the connection. /// \param missing_properties[out] vector of missing properties (if any). - virtual void Connect(const std::map &properties, + virtual void Connect(const ConnPropertyMap &properties, std::vector &missing_properties) = 0; /// \brief Close the connection. From 2d6f05673b0623c2911b68e0bc6b6ac2aebe9668 Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 14 Jan 2022 08:39:14 -0800 Subject: [PATCH 044/183] Update AuthMethod to use ConnPropertyMap --- .../flightsql-odbc/flight_sql/flight_sql_auth_method.cc | 2 +- .../flightsql-odbc/flight_sql/flight_sql_auth_method.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 9cb187d679188..bc7da67a6768b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -87,7 +87,7 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { std::unique_ptr FlightSqlAuthMethod::FromProperties( const std::unique_ptr &client, - const std::map &properties) { + const Connection::ConnPropertyMap &properties) { // Check if should use user-password authentication const auto &it_user = properties.find(FlightSqlConnection::USER); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index f557d248a9ed5..5150f68f5557c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -35,7 +35,7 @@ class FlightSqlAuthMethod { static std::unique_ptr FromProperties( const std::unique_ptr &client, - const std::map &properties); + const odbcabstraction::Connection::ConnPropertyMap &properties); protected: FlightSqlAuthMethod() = default; From d5f3d3494f15ce8511e20ef37e2d8441e336b607 Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 14 Jan 2022 08:59:25 -0800 Subject: [PATCH 045/183] Update test app for ConnPropertyMap --- .../flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 1b65b7f3826fb..6302162932df2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -37,7 +37,7 @@ int main() { const std::shared_ptr &connection = driver.CreateConnection(driver::odbcabstraction::V_3); - std::map properties = { + ConnPropertyMap properties = { {FlightSqlConnection::HOST, std::string("0.0.0.0")}, {FlightSqlConnection::PORT, 32010}, {FlightSqlConnection::USER, std::string("user")}, From ff24100827927018200288021062cef578de1bcd Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 14 Jan 2022 09:17:07 -0800 Subject: [PATCH 046/183] Fix typo in test program using ConnPropertyMap --- .../flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 6302162932df2..d3d2cf291b17b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -37,7 +37,7 @@ int main() { const std::shared_ptr &connection = driver.CreateConnection(driver::odbcabstraction::V_3); - ConnPropertyMap properties = { + Connection::ConnPropertyMap properties = { {FlightSqlConnection::HOST, std::string("0.0.0.0")}, {FlightSqlConnection::PORT, 32010}, {FlightSqlConnection::USER, std::string("user")}, From 713af09d032ee648f403b5431484fe0a99dff85a Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 14 Jan 2022 22:04:28 -0800 Subject: [PATCH 047/183] Remove dependency on Connection from Driver Change an include of Connection to a forward declaration on Driver. --- .../odbcabstraction/include/odbcabstraction/driver.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h index c526ca855cf38..cb64509b416e3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h @@ -17,7 +17,6 @@ #include -#include #include "types.h" #pragma once @@ -25,6 +24,8 @@ namespace driver { namespace odbcabstraction { +class Connection; + /// \brief High-level representation of an ODBC driver. class Driver { public: From ff3f9b0e14b915afb21f9fa574ba55ef94b13b94 Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 14 Jan 2022 23:43:25 -0800 Subject: [PATCH 048/183] Use raw pointers for factory functions instead of shared_ptr Avoid ABI issues with shared_ptr and just use raw pointers to make the library easier to integrate. --- .../flightsql-odbc/flight_sql/flight_sql_connection.cc | 2 +- .../flightsql-odbc/flight_sql/flight_sql_connection.h | 2 +- .../flightsql-odbc/flight_sql/flight_sql_driver.cc | 4 ++-- .../flight_sql/include/flight_sql/flight_sql_driver.h | 2 +- .../flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc | 4 ++-- .../odbcabstraction/include/odbcabstraction/connection.h | 2 +- .../odbcabstraction/include/odbcabstraction/driver.h | 4 +--- 7 files changed, 9 insertions(+), 11 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index a27d6c476b74b..dc57b72ff9726 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -127,7 +127,7 @@ void FlightSqlConnection::Close() { closed_ = true; } -std::shared_ptr FlightSqlConnection::CreateStatement() { +Statement* FlightSqlConnection::CreateStatement() { throw DriverException("CreateStatement not implemented"); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 163cf146a726c..b672e0be9fdc0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -48,7 +48,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { void Close() override; - std::shared_ptr CreateStatement() override; + odbcabstraction::Statement* CreateStatement() override; void SetAttribute(AttributeId attribute, const Attribute &value) override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index 4bbc627223fc1..c5c8631bc238b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -24,9 +24,9 @@ namespace flight_sql { using odbcabstraction::Connection; using odbcabstraction::OdbcVersion; -std::shared_ptr +Connection* FlightSqlDriver::CreateConnection(OdbcVersion odbc_version) { - return std::make_shared(odbc_version); + return new FlightSqlConnection(odbc_version); } } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h index 506fd5c3fff04..4fedc9c36f594 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h @@ -24,7 +24,7 @@ namespace flight_sql { class FlightSqlDriver : public odbcabstraction::Driver { public: - std::shared_ptr + odbcabstraction::Connection* CreateConnection(odbcabstraction::OdbcVersion odbc_version) override; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index d3d2cf291b17b..4265e8869d0dc 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -34,8 +34,8 @@ using driver::odbcabstraction::Connection; int main() { FlightSqlDriver driver; - const std::shared_ptr &connection = - driver.CreateConnection(driver::odbcabstraction::V_3); + std::shared_ptr connection( + driver.CreateConnection(driver::odbcabstraction::V_3)); Connection::ConnPropertyMap properties = { {FlightSqlConnection::HOST, std::string("0.0.0.0")}, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index 1c532fd35cbbb..df913771afba4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -73,7 +73,7 @@ class Connection { virtual void Close() = 0; /// \brief Create a statement. - virtual std::shared_ptr CreateStatement() = 0; + virtual Statement* CreateStatement() = 0; /// \brief Set a connection attribute (may be called at any time). /// \param attribute[in] Which attribute to set. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h index cb64509b416e3..03048cf3bf9a7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h @@ -15,8 +15,6 @@ // specific language governing permissions and limitations // under the License. -#include - #include "types.h" #pragma once @@ -33,7 +31,7 @@ class Driver { /// \brief Create a connection using given ODBC version. /// \param odbc_version ODBC version to be used. - virtual std::shared_ptr + virtual Connection* CreateConnection(OdbcVersion odbc_version) = 0; protected: From 94cc7d707661bd991ffbb3f6824c915c9fb885ad Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 14 Jan 2022 23:50:23 -0800 Subject: [PATCH 049/183] Revert "Use raw pointers for factory functions instead of shared_ptr" This reverts commit ff3f9b0e14b915afb21f9fa574ba55ef94b13b94. --- .../flightsql-odbc/flight_sql/flight_sql_connection.cc | 2 +- .../flightsql-odbc/flight_sql/flight_sql_connection.h | 2 +- .../flightsql-odbc/flight_sql/flight_sql_driver.cc | 4 ++-- .../flight_sql/include/flight_sql/flight_sql_driver.h | 2 +- .../flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc | 4 ++-- .../odbcabstraction/include/odbcabstraction/connection.h | 2 +- .../odbcabstraction/include/odbcabstraction/driver.h | 4 +++- 7 files changed, 11 insertions(+), 9 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index dc57b72ff9726..a27d6c476b74b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -127,7 +127,7 @@ void FlightSqlConnection::Close() { closed_ = true; } -Statement* FlightSqlConnection::CreateStatement() { +std::shared_ptr FlightSqlConnection::CreateStatement() { throw DriverException("CreateStatement not implemented"); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index b672e0be9fdc0..163cf146a726c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -48,7 +48,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { void Close() override; - odbcabstraction::Statement* CreateStatement() override; + std::shared_ptr CreateStatement() override; void SetAttribute(AttributeId attribute, const Attribute &value) override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index c5c8631bc238b..4bbc627223fc1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -24,9 +24,9 @@ namespace flight_sql { using odbcabstraction::Connection; using odbcabstraction::OdbcVersion; -Connection* +std::shared_ptr FlightSqlDriver::CreateConnection(OdbcVersion odbc_version) { - return new FlightSqlConnection(odbc_version); + return std::make_shared(odbc_version); } } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h index 4fedc9c36f594..506fd5c3fff04 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h @@ -24,7 +24,7 @@ namespace flight_sql { class FlightSqlDriver : public odbcabstraction::Driver { public: - odbcabstraction::Connection* + std::shared_ptr CreateConnection(odbcabstraction::OdbcVersion odbc_version) override; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 4265e8869d0dc..d3d2cf291b17b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -34,8 +34,8 @@ using driver::odbcabstraction::Connection; int main() { FlightSqlDriver driver; - std::shared_ptr connection( - driver.CreateConnection(driver::odbcabstraction::V_3)); + const std::shared_ptr &connection = + driver.CreateConnection(driver::odbcabstraction::V_3); Connection::ConnPropertyMap properties = { {FlightSqlConnection::HOST, std::string("0.0.0.0")}, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index df913771afba4..1c532fd35cbbb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -73,7 +73,7 @@ class Connection { virtual void Close() = 0; /// \brief Create a statement. - virtual Statement* CreateStatement() = 0; + virtual std::shared_ptr CreateStatement() = 0; /// \brief Set a connection attribute (may be called at any time). /// \param attribute[in] Which attribute to set. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h index 03048cf3bf9a7..cb64509b416e3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h @@ -15,6 +15,8 @@ // specific language governing permissions and limitations // under the License. +#include + #include "types.h" #pragma once @@ -31,7 +33,7 @@ class Driver { /// \brief Create a connection using given ODBC version. /// \param odbc_version ODBC version to be used. - virtual Connection* + virtual std::shared_ptr CreateConnection(OdbcVersion odbc_version) = 0; protected: From b7810fdffe862959d637c719a6dc9b8c547a3bf9 Mon Sep 17 00:00:00 2001 From: James Duong Date: Sat, 15 Jan 2022 03:05:35 -0800 Subject: [PATCH 050/183] Track missing properties during the connection --- .../flight_sql/flight_sql_connection.cc | 34 +++++++++++++++---- .../flight_sql/flight_sql_connection.h | 4 +-- .../flight_sql/flight_sql_connection_test.cc | 10 +++--- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index a27d6c476b74b..f229fde0c1902 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -20,6 +20,7 @@ #include #include "flight_sql_auth_method.h" #include +#include #include namespace driver { @@ -54,14 +55,23 @@ inline void ThrowIfNotOK(const Status &status) { } } +Connection::ConnPropertyMap::const_iterator TrackMissingRequiredProperty(const std::string& property, + const Connection::ConnPropertyMap &properties, std::vector &missing_attr) { + Connection::ConnPropertyMap::const_iterator prop_iter = properties.find(property); + if (properties.end() == prop_iter) { + missing_attr.push_back(property); + } + return prop_iter; +} + } // namespace void FlightSqlConnection::Connect( const ConnPropertyMap &properties, std::vector &missing_attr) { try { - Location location = BuildLocation(properties); - FlightClientOptions client_options = BuildFlightClientOptions(properties); + Location location = BuildLocation(properties, missing_attr); + FlightClientOptions client_options = BuildFlightClientOptions(properties, missing_attr); std::unique_ptr flight_client; ThrowIfNotOK( @@ -97,16 +107,28 @@ FlightCallOptions FlightSqlConnection::BuildCallOptions() { } FlightClientOptions FlightSqlConnection::BuildFlightClientOptions( - const ConnPropertyMap &properties) { + const ConnPropertyMap &properties, std::vector &missing_attr) { FlightClientOptions options; // TODO: Set up TLS properties return options; } Location FlightSqlConnection::BuildLocation( - const ConnPropertyMap &properties) { - const std::string &host = boost::get(properties.at(HOST)); - const int &port = boost::get(properties.at(PORT)); + const ConnPropertyMap &properties, std::vector &missing_attr) { + const auto& host_iter = TrackMissingRequiredProperty( + HOST, properties, missing_attr); + + const auto& port_iter = TrackMissingRequiredProperty( + PORT, properties, missing_attr); + + if (!missing_attr.empty()) { + std::string missing_attr_str = std::string("Missing required properties: ") + + boost::algorithm::join(missing_attr, ", "); + throw DriverException(missing_attr_str); + } + + const std::string &host = boost::get(host_iter->second); + const int &port = boost::get(port_iter->second); Location location; const auto &it_use_tls = properties.find(USE_TLS); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 163cf146a726c..8545b2e2ac2e8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -60,12 +60,12 @@ class FlightSqlConnection : public odbcabstraction::Connection { /// \brief Builds a Location used for FlightClient connection. /// \note Visible for testing static arrow::flight::Location - BuildLocation(const ConnPropertyMap &properties); + BuildLocation(const ConnPropertyMap &properties, std::vector &missing_attr); /// \brief Builds a FlightClientOptions used for FlightClient connection. /// \note Visible for testing static arrow::flight::FlightClientOptions - BuildFlightClientOptions(const ConnPropertyMap &properties); + BuildFlightClientOptions(const ConnPropertyMap &properties, std::vector &missing_attr); /// \brief Builds a FlightCallOptions used on gRPC calls. /// \note Visible for testing diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index c8ba28eb3007d..785277380b0eb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -60,14 +60,15 @@ TEST(AttributeTests, GetAttributeWithoutSetting) { } TEST(BuildLocationTests, ForTcp) { + std::vector missing_attr; const Location &actual_location1 = FlightSqlConnection::BuildLocation({ {FlightSqlConnection::HOST, std::string("localhost")}, {FlightSqlConnection::PORT, 32010}, - }); + }, missing_attr); const Location &actual_location2 = FlightSqlConnection::BuildLocation({ {FlightSqlConnection::HOST, std::string("localhost")}, {FlightSqlConnection::PORT, 32011}, - }); + }, missing_attr); Location expected_location; ASSERT_TRUE( @@ -77,16 +78,17 @@ TEST(BuildLocationTests, ForTcp) { } TEST(BuildLocationTests, ForTls) { + std::vector missing_attr; const Location &actual_location1 = FlightSqlConnection::BuildLocation({ {FlightSqlConnection::HOST, std::string("localhost")}, {FlightSqlConnection::PORT, 32010}, {FlightSqlConnection::USE_TLS, true}, - }); + }, missing_attr); const Location &actual_location2 = FlightSqlConnection::BuildLocation({ {FlightSqlConnection::HOST, std::string("localhost")}, {FlightSqlConnection::PORT, 32011}, {FlightSqlConnection::USE_TLS, true}, - }); + }, missing_attr); Location expected_location; ASSERT_TRUE( From f6f9e716057ebb5cf54b84c0923f031b2d3d070a Mon Sep 17 00:00:00 2001 From: James Duong Date: Sat, 15 Jan 2022 03:24:20 -0800 Subject: [PATCH 051/183] Change ConnPropertyMap to always hold strings Remove use of boost::variant as property values and just hold data as string. Data coming off the connection string will always be string. The implementation is responsible for converting the string to a stronger type if needed (for Arrow, boost::lexical_cast is used). --- .../flight_sql/flight_sql_connection.cc | 7 ++++--- .../flight_sql/flight_sql_connection_test.cc | 12 ++++++------ .../flightsql-odbc/flight_sql/main.cc | 2 +- .../include/odbcabstraction/connection.h | 3 ++- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index f229fde0c1902..61409b3c29c16 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -19,6 +19,7 @@ #include #include "flight_sql_auth_method.h" +#include #include #include #include @@ -127,12 +128,12 @@ Location FlightSqlConnection::BuildLocation( throw DriverException(missing_attr_str); } - const std::string &host = boost::get(host_iter->second); - const int &port = boost::get(port_iter->second); + const std::string &host = host_iter->second; + const int &port = boost::lexical_cast(port_iter->second); Location location; const auto &it_use_tls = properties.find(USE_TLS); - if (it_use_tls != properties.end() && boost::get(it_use_tls->second)) { + if (it_use_tls != properties.end() && boost::lexical_cast(it_use_tls->second)) { ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); } else { ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 785277380b0eb..5f2ce08a57639 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -63,11 +63,11 @@ TEST(BuildLocationTests, ForTcp) { std::vector missing_attr; const Location &actual_location1 = FlightSqlConnection::BuildLocation({ {FlightSqlConnection::HOST, std::string("localhost")}, - {FlightSqlConnection::PORT, 32010}, + {FlightSqlConnection::PORT, std::string("32010")}, }, missing_attr); const Location &actual_location2 = FlightSqlConnection::BuildLocation({ {FlightSqlConnection::HOST, std::string("localhost")}, - {FlightSqlConnection::PORT, 32011}, + {FlightSqlConnection::PORT, std::string("32011")}, }, missing_attr); Location expected_location; @@ -81,13 +81,13 @@ TEST(BuildLocationTests, ForTls) { std::vector missing_attr; const Location &actual_location1 = FlightSqlConnection::BuildLocation({ {FlightSqlConnection::HOST, std::string("localhost")}, - {FlightSqlConnection::PORT, 32010}, - {FlightSqlConnection::USE_TLS, true}, + {FlightSqlConnection::PORT, std::string("32010")}, + {FlightSqlConnection::USE_TLS, std::string("1")}, }, missing_attr); const Location &actual_location2 = FlightSqlConnection::BuildLocation({ {FlightSqlConnection::HOST, std::string("localhost")}, - {FlightSqlConnection::PORT, 32011}, - {FlightSqlConnection::USE_TLS, true}, + {FlightSqlConnection::PORT, std::string("32011")}, + {FlightSqlConnection::USE_TLS, std::string("1")}, }, missing_attr); Location expected_location; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index d3d2cf291b17b..953a9a4f43226 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -39,7 +39,7 @@ int main() { Connection::ConnPropertyMap properties = { {FlightSqlConnection::HOST, std::string("0.0.0.0")}, - {FlightSqlConnection::PORT, 32010}, + {FlightSqlConnection::PORT, std::string("32010")}, {FlightSqlConnection::USER, std::string("user")}, {FlightSqlConnection::PASSWORD, std::string("password")}, }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index 1c532fd35cbbb..21737944cf2b8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -58,10 +58,11 @@ class Connection { }; typedef boost::variant Attribute; - typedef boost::variant Property; + typedef std::string Property; typedef boost::variant Info; typedef std::map ConnPropertyMap; + /// \brief Establish the connection. /// \param properties[in] properties used to establish the connection. From 18bb25944227ed6e148b3efe0b953114e4f9dc91 Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 17 Jan 2022 09:04:07 -0800 Subject: [PATCH 052/183] Add comment about case-insensititivity. Add note that ConnPropertyMap is case insensitive since ODBC keys are case-insensitive. --- .../odbcabstraction/include/odbcabstraction/connection.h | 1 + 1 file changed, 1 insertion(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index 21737944cf2b8..5dcfc5922dad0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -60,6 +60,7 @@ class Connection { typedef boost::variant Attribute; typedef std::string Property; typedef boost::variant Info; + // ConnPropertyMap is case-insensitive for keys. typedef std::map ConnPropertyMap; From 44204371af62bd44fe55bef4e679f10a61a6020d Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Wed, 19 Jan 2022 14:43:37 -0300 Subject: [PATCH 053/183] Define Statement interface for ODBC abstraction This defines `statement.h` for the ODBC abstraction layer. The statement interface covers methods for: - Setting/getting statement attributes (for SQLSetStmtAttr and SQLGetStmtAttr) - Execute a query - Prepare a query - Getting tables (for SQLTables, branching for ODBC 2.x or 3.x) - Getting columns (for SQLColumns, branching for ODBC 2.x or 3.x) - Getting type info (for SQLGetTypeInfo) Change-Id: I28230fedf7ae4129bb04d31685bc86e4c9630441 --- .../odbcabstraction/exceptions.cc | 5 +- .../include/odbcabstraction/connection.h | 13 +- .../include/odbcabstraction/statement.h | 193 ++++++++++++++++++ 3 files changed, 200 insertions(+), 11 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc index 34b1bdd14b5d6..9bed126ea09ca 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc @@ -24,10 +24,7 @@ namespace odbcabstraction { DriverException::DriverException(std::string message) : message_(std::move(message)) {} -const char * -DriverException::what() const throw() { - return message_.c_str(); -} +const char *DriverException::what() const throw() { return message_.c_str(); } AuthenticationException::AuthenticationException(std::string message) : DriverException(std::move(message)) {} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index 5dcfc5922dad0..fefd3e8718a71 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -15,9 +15,9 @@ // specific language governing permissions and limitations // under the License. +#include #include #include -#include #include #include @@ -50,9 +50,9 @@ class Connection { }; /// \brief Case insensitive comparator - struct CaseInsensitiveComparator : std::binary_function - { - bool operator() (const std::string & s1, const std::string & s2) const { + struct CaseInsensitiveComparator + : std::binary_function { + bool operator()(const std::string &s1, const std::string &s2) const { return boost::lexicographical_compare(s1, s2, boost::is_iless()); } }; @@ -61,9 +61,8 @@ class Connection { typedef std::string Property; typedef boost::variant Info; // ConnPropertyMap is case-insensitive for keys. - typedef std::map ConnPropertyMap; - - + typedef std::map + ConnPropertyMap; /// \brief Establish the connection. /// \param properties[in] properties used to establish the connection. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h new file mode 100644 index 0000000000000..40b6ce6ba5d6e --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h @@ -0,0 +1,193 @@ +// 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 + +#pragma once + +namespace driver { +namespace odbcabstraction { + +using boost::optional; + +class ResultSet; +class ResultSetMetadata; + +class Statement { +public: + /** + * Statement attributes that can be called at anytime. + */ + // TODO: Document attributes + enum StatementAttributeId { + MAX_LENGTH, + MAX_ROWS, + METADATA_ID, + NOSCAN, + QUERY_TIMEOUT, + }; + + typedef boost::variant Attribute; + + /** + * Set a statement attribute (may be called at any time) + * + * NOTE: Meant to be bound with SQLSetStmtAttr. + * + * @param attribute Attribute identifier to set. + * @param value Value to be associated with the attribute. + */ + virtual void SetAttribute(StatementAttributeId attribute, + const Attribute &value) = 0; + + /** + * Retrieve a statement attribute. + * + * NOTE: Meant to be bound with SQLGetStmtAttr. + * + * @param attribute Attribute identifier to be retrieved. + * @return Value associated with the attribute. + */ + virtual optional + GetAttribute(Statement::StatementAttributeId attribute) = 0; + + /** + * Prepares the statement. + * Returns ResultSetMetadata if query returns a result set, + * otherwise it returns `boost::none`. + * + * @param query The SQL query to prepare. + */ + virtual boost::optional> + Prepare(const std::string &query) = 0; + + /** + * Execute the prepared statement. + * + * NOTE: Must call `Prepare(const std::string &query)` before, otherwise it + * will throw an exception. + * + * @returns true if the first result is a ResultSet object; + * false if it is an update count or there are no results. + */ + virtual bool ExecutePrepared() = 0; + + /** + * Execute the statement if it is prepared or not. + * + * @param query The SQL query to execute. + * @returns true if the first result is a ResultSet object; + * false if it is an update count or there are no results. + */ + virtual bool Execute(const std::string &query) = 0; + + /** + * Returns the current result as a ResultSet object. + */ + virtual std::shared_ptr GetResultSet() = 0; + + /** + * Retrieves the current result as an update count; + * if the result is a ResultSet object or there are no more results, -1 is + * returned. + */ + virtual long GetUpdateCount() = 0; + + /** + * Returns the list of table, catalog, or schema names, and table types, + * stored in a specific data source. The driver returns the information as a + * result set. + * + * NOTE: This is meant to be used by ODBC 2.x binding. + * + * @param catalog_name The catalog name. + * @param schema_name The schema name. + * @param table_name The table name. + * @param table_type The table type. + */ + virtual std::shared_ptr + GetTables_V2(const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, + const std::string *table_type) = 0; + + /** + * Returns the list of table, catalog, or schema names, and table types, + * stored in a specific data source. The driver returns the information as a + * result set. + * + * NOTE: This is meant to be used by ODBC 3.x binding. + * + * @param catalog_name The catalog name. + * @param schema_name The schema name. + * @param table_name The table name. + * @param table_type The table type. + */ + virtual std::shared_ptr + GetTables_V3(const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, + const std::string *table_type) = 0; + + /** + * Returns the list of column names in specified tables. The driver returns + * this information as a result set.. + * + * NOTE: This is meant to be used by ODBC 2.x binding. + * + * @param catalog_name The catalog name. + * @param schema_name The schema name. + * @param table_name The table name. + * @param column_name The column name. + */ + virtual std::shared_ptr + GetColumns_V2(const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, + const std::string *column_name) = 0; + + /** + * Returns the list of column names in specified tables. The driver returns + * this information as a result set.. + * + * NOTE: This is meant to be used by ODBC 3.x binding. + * + * @param catalog_name The catalog name. + * @param schema_name The schema name. + * @param table_name The table name. + * @param column_name The column name. + */ + virtual std::shared_ptr + GetColumns_V3(const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, + const std::string *column_name) = 0; + + /** + * Returns information about data types supported by the data source. The + * driver returns the information in the form of an SQL result set. The data + * types are intended for use in Data Definition Language (DDL) statements. + * + * Accepts ODBC 2.x or 3.x data types as input. + * Reports results according to which ODBC version is set on Driver. + * + * @param dataType The SQL data type. + */ + virtual std::shared_ptr GetTypeInfo(int dataType) = 0; +}; + +} // namespace odbcabstraction +} // namespace driver From 9e7f7f2c81a696858880a6d7226f218257c55691 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Thu, 20 Jan 2022 16:27:30 -0300 Subject: [PATCH 054/183] Refactor docs from java pattern to doxygen format Change-Id: I8b057ab40b5511acdc738dc2e7bb18a794c2fd2e --- .../include/odbcabstraction/statement.h | 204 ++++++++---------- 1 file changed, 89 insertions(+), 115 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h index 40b6ce6ba5d6e..7c0ae20c10e4c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h @@ -28,14 +28,14 @@ namespace odbcabstraction { using boost::optional; class ResultSet; + class ResultSetMetadata; +/// \brief High-level representation of an ODBC statement. class Statement { public: - /** - * Statement attributes that can be called at anytime. - */ - // TODO: Document attributes + /// \brief Statement attributes that can be called at anytime. + ////TODO: Document attributes enum StatementAttributeId { MAX_LENGTH, MAX_ROWS, @@ -46,147 +46,121 @@ class Statement { typedef boost::variant Attribute; - /** - * Set a statement attribute (may be called at any time) - * - * NOTE: Meant to be bound with SQLSetStmtAttr. - * - * @param attribute Attribute identifier to set. - * @param value Value to be associated with the attribute. - */ + /// \brief Set a statement attribute (may be called at any time) + /// + ///NOTE: Meant to be bound with SQLSetStmtAttr. + /// + /// \param attribute Attribute identifier to set. + /// \param value Value to be associated with the attribute. virtual void SetAttribute(StatementAttributeId attribute, const Attribute &value) = 0; - /** - * Retrieve a statement attribute. - * - * NOTE: Meant to be bound with SQLGetStmtAttr. - * - * @param attribute Attribute identifier to be retrieved. - * @return Value associated with the attribute. - */ - virtual optional + /// \brief Retrieve a statement attribute. + /// + /// NOTE: Meant to be bound with SQLGetStmtAttr. + /// + /// \param attribute Attribute identifier to be retrieved. + /// \return Value associated with the attribute. + virtual optional GetAttribute(Statement::StatementAttributeId attribute) = 0; - /** - * Prepares the statement. - * Returns ResultSetMetadata if query returns a result set, - * otherwise it returns `boost::none`. - * - * @param query The SQL query to prepare. - */ - virtual boost::optional> + /// \brief Prepares the statement. + /// Returns ResultSetMetadata if query returns a result set, + /// otherwise it returns `boost::none`. + /// \param query The SQL query to prepare. + virtual boost::optional > Prepare(const std::string &query) = 0; - /** - * Execute the prepared statement. - * - * NOTE: Must call `Prepare(const std::string &query)` before, otherwise it - * will throw an exception. - * - * @returns true if the first result is a ResultSet object; - * false if it is an update count or there are no results. - */ + /// \brief Execute the prepared statement. + /// + /// NOTE: Must call `Prepare(const std::string &query)` before, otherwise it + /// will throw an exception. + /// + /// \returns true if the first result is a ResultSet object; + /// false if it is an update count or there are no results. virtual bool ExecutePrepared() = 0; - /** - * Execute the statement if it is prepared or not. - * - * @param query The SQL query to execute. - * @returns true if the first result is a ResultSet object; - * false if it is an update count or there are no results. - */ + /// \brief Execute the statement if it is prepared or not. + /// \param query The SQL query to execute. + /// \returns true if the first result is a ResultSet object; + /// false if it is an update count or there are no results. virtual bool Execute(const std::string &query) = 0; - /** - * Returns the current result as a ResultSet object. - */ - virtual std::shared_ptr GetResultSet() = 0; + /// \brief Returns the current result as a ResultSet object. + virtual std::shared_ptr GetResultSet() = 0; - /** - * Retrieves the current result as an update count; - * if the result is a ResultSet object or there are no more results, -1 is - * returned. - */ + /// \brief Retrieves the current result as an update count; + /// if the result is a ResultSet object or there are no more results, -1 is + /// returned. virtual long GetUpdateCount() = 0; - /** - * Returns the list of table, catalog, or schema names, and table types, - * stored in a specific data source. The driver returns the information as a - * result set. - * - * NOTE: This is meant to be used by ODBC 2.x binding. - * - * @param catalog_name The catalog name. - * @param schema_name The schema name. - * @param table_name The table name. - * @param table_type The table type. - */ - virtual std::shared_ptr + /// \brief Returns the list of table, catalog, or schema names, and table types, + /// stored in a specific data source. The driver returns the information as a + /// result set. + /// + ///NOTE: This is meant to be used by ODBC 2.x binding. + /// + /// \param catalog_name The catalog name. + /// \param schema_name The schema name. + /// \param table_name The table name. + /// \param table_type The table type. + virtual std::shared_ptr GetTables_V2(const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *table_type) = 0; - /** - * Returns the list of table, catalog, or schema names, and table types, - * stored in a specific data source. The driver returns the information as a - * result set. - * - * NOTE: This is meant to be used by ODBC 3.x binding. - * - * @param catalog_name The catalog name. - * @param schema_name The schema name. - * @param table_name The table name. - * @param table_type The table type. - */ - virtual std::shared_ptr + /// \brief Returns the list of table, catalog, or schema names, and table types, + /// stored in a specific data source. The driver returns the information as a + /// result set. + /// + /// NOTE: This is meant to be used by ODBC 3.x binding. + /// + /// \param catalog_name The catalog name. + /// \param schema_name The schema name. + /// \param table_name The table name. + /// \param table_type The table type. + virtual std::shared_ptr GetTables_V3(const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *table_type) = 0; - /** - * Returns the list of column names in specified tables. The driver returns - * this information as a result set.. - * - * NOTE: This is meant to be used by ODBC 2.x binding. - * - * @param catalog_name The catalog name. - * @param schema_name The schema name. - * @param table_name The table name. - * @param column_name The column name. - */ - virtual std::shared_ptr + /// \brief Returns the list of column names in specified tables. The driver returns + /// this information as a result set.. + /// + /// NOTE: This is meant to be used by ODBC 2.x binding. + /// + /// \param catalog_name The catalog name. + /// \param schema_name The schema name. + /// \param table_name The table name. + /// \param column_name The column name. + virtual std::shared_ptr GetColumns_V2(const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *column_name) = 0; - /** - * Returns the list of column names in specified tables. The driver returns - * this information as a result set.. - * - * NOTE: This is meant to be used by ODBC 3.x binding. - * - * @param catalog_name The catalog name. - * @param schema_name The schema name. - * @param table_name The table name. - * @param column_name The column name. - */ - virtual std::shared_ptr + /// \brief Returns the list of column names in specified tables. The driver returns + /// this information as a result set.. + /// + /// NOTE: This is meant to be used by ODBC 3.x binding. + /// + /// \param catalog_name The catalog name. + /// \param schema_name The schema name. + /// \param table_name The table name. + /// \param column_name The column name. + virtual std::shared_ptr GetColumns_V3(const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *column_name) = 0; - /** - * Returns information about data types supported by the data source. The - * driver returns the information in the form of an SQL result set. The data - * types are intended for use in Data Definition Language (DDL) statements. - * - * Accepts ODBC 2.x or 3.x data types as input. - * Reports results according to which ODBC version is set on Driver. - * - * @param dataType The SQL data type. - */ - virtual std::shared_ptr GetTypeInfo(int dataType) = 0; + /// \brief Returns information about data types supported by the data source. The + /// driver returns the information in the form of an SQL result set. The data + /// types are intended for use in Data Definition Language (DDL) statements. + /// + /// Accepts ODBC 2.x or 3.x data types as input. + /// Reports results according to which ODBC version is set on Driver. + /// + /// \param dataType The SQL data type. + virtual std::shared_ptr GetTypeInfo(int dataType) = 0; }; } // namespace odbcabstraction From 16ea637b9eb8cdbb78c299d4e4c523816c5267b1 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Wed, 19 Jan 2022 14:49:13 -0300 Subject: [PATCH 055/183] Define ResultSet interface for ODBC abstraction This defines the ResultSet interface for the ODBC abstraction layer. Based on discussions between me and James we decided to follow a pattern similar to ODBC's `SQLBindCol` and `SQLFetch`, but for multiple rows (batch) in order to keep the interface efficient by reducing the virtual method calls and also hope to facilitate when implement bulk methods (ie. bulk conversion) Change-Id: I5e4c9de4cbd012f3745ae1e7600256dedb8f3c39 --- .../include/odbcabstraction/result_set.h | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h new file mode 100644 index 0000000000000..8adfa19589bf1 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h @@ -0,0 +1,97 @@ +// 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 + +#pragma once + +namespace driver { +namespace odbcabstraction { + +class ResultSetMetadata; + +enum DataType { + UNKNOWN_TYPE = SQL_UNKNOWN_TYPE, + CHAR = SQL_CHAR, + NUMERIC = SQL_NUMERIC, + DECIMAL = SQL_DECIMAL, + INTEGER = SQL_INTEGER, + SMALLINT = SQL_SMALLINT, + FLOAT = SQL_FLOAT, + REAL = SQL_REAL, + DOUBLE = SQL_DOUBLE, + DATETIME = SQL_DATETIME, + VARCHAR = SQL_VARCHAR, +}; + +class ResultSet { +public: + /// \brief Returns metadata for this ResultSet. + virtual std::shared_ptr GetMetadata() = 0; + + /// \brief Closes ResultSet, releasing any resources allocated by it. + virtual void Close() = 0; + + /// \brief Binds a column with a result buffer. The buffer will be filled with + /// up to `GetMaxBatchSize()` values. + /// + /// \param column Column number to be bound with (starts from 1). + /// \param target_type Target data type expected by client. + /// \param precision Column's precision + /// \param scale Column's scale + /// \param buffer Target buffer to be filled with column values. + /// \param buffer_length Target buffer length. + /// \param strlen_buffer Buffer that holds the length of each value contained + /// on target buffer. + /// \param strlen_buffer_len strlen_buffer's length. + virtual void BindColumn(int column, DataType target_type, int precision, + int scale, void *buffer, size_t buffer_length, + size_t *strlen_buffer, size_t strlen_buffer_len) = 0; + + /// \brief Fetches next rows from ResultSet and load values on buffers + /// previously bound with `BindColumn`. + /// + /// The parameters `buffer` and `strlen_buffer` passed to `BindColumn()` + /// should have capacity to accommodate the rows requested, otherwise data + /// will be truncated. + /// + /// \param rows The maximum number of rows to be fetched. + /// \returns The number of rows fetched. + virtual size_t Move(size_t rows) = 0; + + /// \brief Populates `buffer` with the value on current row for given column. + /// If the value doesn't fit the buffer this method returns true and + /// subsequent calls will fetch the rest of data. + /// + /// \param column Column number to be fetched. + /// \param target_type Target data type expected by client. + /// \param precision Column's precision + /// \param scale Column's scale + /// \param buffer Target buffer to be populated. + /// \param buffer_length Target buffer length. + /// \param strlen_buffer Buffer that holds the length of value being fetched. + /// \returns true if there is more data to fetch from the current cell; + /// false if the whole value was already fetched. + virtual bool GetData(int column, DataType target_type, int precision, + int scale, void *buffer, size_t buffer_length, + size_t *strlen_buffer) = 0; +}; + +} // namespace odbcabstraction +} // namespace driver From 80dde1c6a55f66259d079828041ee6a7320e478a Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Thu, 20 Jan 2022 18:03:18 -0300 Subject: [PATCH 056/183] Fix code style issues on statement.h Change-Id: I1d3a4a5473d50db7f3fa8a1b6fc05abd5b7b475c --- .../include/odbcabstraction/statement.h | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h index 7c0ae20c10e4c..dc31471172fa6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h @@ -48,7 +48,7 @@ class Statement { /// \brief Set a statement attribute (may be called at any time) /// - ///NOTE: Meant to be bound with SQLSetStmtAttr. + /// NOTE: Meant to be bound with SQLSetStmtAttr. /// /// \param attribute Attribute identifier to set. /// \param value Value to be associated with the attribute. @@ -61,14 +61,14 @@ class Statement { /// /// \param attribute Attribute identifier to be retrieved. /// \return Value associated with the attribute. - virtual optional + virtual optional GetAttribute(Statement::StatementAttributeId attribute) = 0; /// \brief Prepares the statement. /// Returns ResultSetMetadata if query returns a result set, /// otherwise it returns `boost::none`. /// \param query The SQL query to prepare. - virtual boost::optional > + virtual boost::optional> Prepare(const std::string &query) = 0; /// \brief Execute the prepared statement. @@ -87,31 +87,31 @@ class Statement { virtual bool Execute(const std::string &query) = 0; /// \brief Returns the current result as a ResultSet object. - virtual std::shared_ptr GetResultSet() = 0; + virtual std::shared_ptr GetResultSet() = 0; /// \brief Retrieves the current result as an update count; /// if the result is a ResultSet object or there are no more results, -1 is /// returned. virtual long GetUpdateCount() = 0; - /// \brief Returns the list of table, catalog, or schema names, and table types, - /// stored in a specific data source. The driver returns the information as a - /// result set. + /// \brief Returns the list of table, catalog, or schema names, and table + /// types, stored in a specific data source. The driver returns the + /// information as a result set. /// - ///NOTE: This is meant to be used by ODBC 2.x binding. + /// NOTE: This is meant to be used by ODBC 2.x binding. /// /// \param catalog_name The catalog name. /// \param schema_name The schema name. /// \param table_name The table name. /// \param table_type The table type. - virtual std::shared_ptr + virtual std::shared_ptr GetTables_V2(const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *table_type) = 0; - /// \brief Returns the list of table, catalog, or schema names, and table types, - /// stored in a specific data source. The driver returns the information as a - /// result set. + /// \brief Returns the list of table, catalog, or schema names, and table + /// types, stored in a specific data source. The driver returns the + /// information as a result set. /// /// NOTE: This is meant to be used by ODBC 3.x binding. /// @@ -119,13 +119,13 @@ class Statement { /// \param schema_name The schema name. /// \param table_name The table name. /// \param table_type The table type. - virtual std::shared_ptr + virtual std::shared_ptr GetTables_V3(const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *table_type) = 0; - /// \brief Returns the list of column names in specified tables. The driver returns - /// this information as a result set.. + /// \brief Returns the list of column names in specified tables. The driver + /// returns this information as a result set.. /// /// NOTE: This is meant to be used by ODBC 2.x binding. /// @@ -133,13 +133,13 @@ class Statement { /// \param schema_name The schema name. /// \param table_name The table name. /// \param column_name The column name. - virtual std::shared_ptr + virtual std::shared_ptr GetColumns_V2(const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *column_name) = 0; - /// \brief Returns the list of column names in specified tables. The driver returns - /// this information as a result set.. + /// \brief Returns the list of column names in specified tables. The driver + /// returns this information as a result set.. /// /// NOTE: This is meant to be used by ODBC 3.x binding. /// @@ -147,20 +147,21 @@ class Statement { /// \param schema_name The schema name. /// \param table_name The table name. /// \param column_name The column name. - virtual std::shared_ptr + virtual std::shared_ptr GetColumns_V3(const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *column_name) = 0; - /// \brief Returns information about data types supported by the data source. The - /// driver returns the information in the form of an SQL result set. The data - /// types are intended for use in Data Definition Language (DDL) statements. + /// \brief Returns information about data types supported by the data source. + /// The driver returns the information in the form of an SQL result set. The + /// data types are intended for use in Data Definition Language (DDL) + /// statements. /// /// Accepts ODBC 2.x or 3.x data types as input. /// Reports results according to which ODBC version is set on Driver. /// /// \param dataType The SQL data type. - virtual std::shared_ptr GetTypeInfo(int dataType) = 0; + virtual std::shared_ptr GetTypeInfo(int dataType) = 0; }; } // namespace odbcabstraction From 35ce807508e727bcd1be3c2ee55cf6c5a6f58cdf Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 21 Jan 2022 23:17:31 -0800 Subject: [PATCH 057/183] Support basic query execution - Add FlightSqlStatement and implement enough of the Statement interface to support executing queries. - Fix bugs persisting auth information in the connection. - Propagate call_options from the connection to the statement. - Add the ClientCookieHandler to persist state information. Change-Id: Id4f99a27436e81e31fca6250d21adab5241202de --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 3 +- .../flight_sql/flight_sql_connection.cc | 66 ++++---- .../flight_sql/flight_sql_connection.h | 10 +- .../flight_sql/flight_sql_connection_test.cc | 52 ++++--- .../flight_sql/flight_sql_statement.cc | 143 ++++++++++++++++++ .../flight_sql/flight_sql_statement.h | 76 ++++++++++ .../include/odbcabstraction/statement.h | 2 + 7 files changed, 299 insertions(+), 53 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 7b04d2cf39846..29c9a157c420b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -84,9 +84,10 @@ find_package(gRPC 1.36 CONFIG REQUIRED) enable_testing() set(ARROW_ODBC_SPI_SOURCES + flight_sql_auth_method.cc flight_sql_driver.cc flight_sql_connection.cc - flight_sql_auth_method.cc + flight_sql_statement.cc ) set(ARROW_ODBC_SPI_THIRDPARTY_LIBS diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 61409b3c29c16..cc211d6f4123c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -17,12 +17,14 @@ #include "flight_sql_connection.h" -#include #include "flight_sql_auth_method.h" +#include "flight_sql_statement.h" +#include +#include #include #include -#include #include +#include namespace driver { namespace flight_sql { @@ -47,8 +49,8 @@ const std::string FlightSqlConnection::PASSWORD = "password"; const std::string FlightSqlConnection::USE_TLS = "useTls"; namespace { - // TODO: Add properties for getting the certificates - // TODO: Check if gRPC can use the system truststore, if not copy from Drill +// TODO: Add properties for getting the certificates +// TODO: Check if gRPC can use the system truststore, if not copy from Drill inline void ThrowIfNotOK(const Status &status) { if (!status.ok()) { @@ -56,9 +58,12 @@ inline void ThrowIfNotOK(const Status &status) { } } -Connection::ConnPropertyMap::const_iterator TrackMissingRequiredProperty(const std::string& property, - const Connection::ConnPropertyMap &properties, std::vector &missing_attr) { - Connection::ConnPropertyMap::const_iterator prop_iter = properties.find(property); +Connection::ConnPropertyMap::const_iterator +TrackMissingRequiredProperty(const std::string &property, + const Connection::ConnPropertyMap &properties, + std::vector &missing_attr) { + Connection::ConnPropertyMap::const_iterator prop_iter = + properties.find(property); if (properties.end() == prop_iter) { missing_attr.push_back(property); } @@ -67,12 +72,12 @@ Connection::ConnPropertyMap::const_iterator TrackMissingRequiredProperty(const s } // namespace -void FlightSqlConnection::Connect( - const ConnPropertyMap &properties, - std::vector &missing_attr) { +void FlightSqlConnection::Connect(const ConnPropertyMap &properties, + std::vector &missing_attr) { try { Location location = BuildLocation(properties, missing_attr); - FlightClientOptions client_options = BuildFlightClientOptions(properties, missing_attr); + FlightClientOptions client_options = + BuildFlightClientOptions(properties, missing_attr); std::unique_ptr flight_client; ThrowIfNotOK( @@ -85,7 +90,7 @@ void FlightSqlConnection::Connect( sql_client_.reset(new FlightSqlClient(std::move(flight_client))); SetAttribute(CONNECTION_DEAD, false); - call_options_ = BuildCallOptions(); + PopulateCallOptionsFromAttributes(); } catch (...) { SetAttribute(CONNECTION_DEAD, true); sql_client_.reset(); @@ -94,37 +99,42 @@ void FlightSqlConnection::Connect( } } -FlightCallOptions FlightSqlConnection::BuildCallOptions() { +const FlightCallOptions & +FlightSqlConnection::PopulateCallOptionsFromAttributes() { // Set CONNECTION_TIMEOUT attribute - FlightCallOptions call_options; const boost::optional &connection_timeout = GetAttribute(CONNECTION_TIMEOUT); if (connection_timeout.has_value()) { - call_options.timeout = + call_options_.timeout = TimeoutDuration{boost::get(connection_timeout.value())}; } - return call_options; + return call_options_; } FlightClientOptions FlightSqlConnection::BuildFlightClientOptions( const ConnPropertyMap &properties, std::vector &missing_attr) { FlightClientOptions options; + // Persist state information using cookies if the FlightProducer supports it. + options.middleware.push_back(arrow::flight::GetCookieFactory()); + // TODO: Set up TLS properties - return options; + return std::move(options); } -Location FlightSqlConnection::BuildLocation( - const ConnPropertyMap &properties, std::vector &missing_attr) { - const auto& host_iter = TrackMissingRequiredProperty( - HOST, properties, missing_attr); +Location +FlightSqlConnection::BuildLocation(const ConnPropertyMap &properties, + std::vector &missing_attr) { + const auto &host_iter = + TrackMissingRequiredProperty(HOST, properties, missing_attr); - const auto& port_iter = TrackMissingRequiredProperty( - PORT, properties, missing_attr); + const auto &port_iter = + TrackMissingRequiredProperty(PORT, properties, missing_attr); if (!missing_attr.empty()) { - std::string missing_attr_str = std::string("Missing required properties: ") - + boost::algorithm::join(missing_attr, ", "); + std::string missing_attr_str = + std::string("Missing required properties: ") + + boost::algorithm::join(missing_attr, ", "); throw DriverException(missing_attr_str); } @@ -133,7 +143,8 @@ Location FlightSqlConnection::BuildLocation( Location location; const auto &it_use_tls = properties.find(USE_TLS); - if (it_use_tls != properties.end() && boost::lexical_cast(it_use_tls->second)) { + if (it_use_tls != properties.end() && + boost::lexical_cast(it_use_tls->second)) { ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); } else { ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); @@ -151,7 +162,8 @@ void FlightSqlConnection::Close() { } std::shared_ptr FlightSqlConnection::CreateStatement() { - throw DriverException("CreateStatement not implemented"); + return std::shared_ptr( + new FlightSqlStatement(*sql_client_, call_options_)); } void FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 8545b2e2ac2e8..78a1f6c65a27a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -40,7 +40,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { static const std::string USER; static const std::string PASSWORD; static const std::string USE_TLS; - + explicit FlightSqlConnection(odbcabstraction::OdbcVersion odbc_version); void Connect(const ConnPropertyMap &properties, @@ -60,16 +60,18 @@ class FlightSqlConnection : public odbcabstraction::Connection { /// \brief Builds a Location used for FlightClient connection. /// \note Visible for testing static arrow::flight::Location - BuildLocation(const ConnPropertyMap &properties, std::vector &missing_attr); + BuildLocation(const ConnPropertyMap &properties, + std::vector &missing_attr); /// \brief Builds a FlightClientOptions used for FlightClient connection. /// \note Visible for testing static arrow::flight::FlightClientOptions - BuildFlightClientOptions(const ConnPropertyMap &properties, std::vector &missing_attr); + BuildFlightClientOptions(const ConnPropertyMap &properties, + std::vector &missing_attr); /// \brief Builds a FlightCallOptions used on gRPC calls. /// \note Visible for testing - arrow::flight::FlightCallOptions BuildCallOptions(); + const arrow::flight::FlightCallOptions &PopulateCallOptionsFromAttributes(); }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 5f2ce08a57639..435fcff0450ab 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -61,14 +61,18 @@ TEST(AttributeTests, GetAttributeWithoutSetting) { TEST(BuildLocationTests, ForTcp) { std::vector missing_attr; - const Location &actual_location1 = FlightSqlConnection::BuildLocation({ - {FlightSqlConnection::HOST, std::string("localhost")}, - {FlightSqlConnection::PORT, std::string("32010")}, - }, missing_attr); - const Location &actual_location2 = FlightSqlConnection::BuildLocation({ - {FlightSqlConnection::HOST, std::string("localhost")}, - {FlightSqlConnection::PORT, std::string("32011")}, - }, missing_attr); + const Location &actual_location1 = FlightSqlConnection::BuildLocation( + { + {FlightSqlConnection::HOST, std::string("localhost")}, + {FlightSqlConnection::PORT, std::string("32010")}, + }, + missing_attr); + const Location &actual_location2 = FlightSqlConnection::BuildLocation( + { + {FlightSqlConnection::HOST, std::string("localhost")}, + {FlightSqlConnection::PORT, std::string("32011")}, + }, + missing_attr); Location expected_location; ASSERT_TRUE( @@ -79,16 +83,20 @@ TEST(BuildLocationTests, ForTcp) { TEST(BuildLocationTests, ForTls) { std::vector missing_attr; - const Location &actual_location1 = FlightSqlConnection::BuildLocation({ - {FlightSqlConnection::HOST, std::string("localhost")}, - {FlightSqlConnection::PORT, std::string("32010")}, - {FlightSqlConnection::USE_TLS, std::string("1")}, - }, missing_attr); - const Location &actual_location2 = FlightSqlConnection::BuildLocation({ - {FlightSqlConnection::HOST, std::string("localhost")}, - {FlightSqlConnection::PORT, std::string("32011")}, - {FlightSqlConnection::USE_TLS, std::string("1")}, - }, missing_attr); + const Location &actual_location1 = FlightSqlConnection::BuildLocation( + { + {FlightSqlConnection::HOST, std::string("localhost")}, + {FlightSqlConnection::PORT, std::string("32010")}, + {FlightSqlConnection::USE_TLS, std::string("1")}, + }, + missing_attr); + const Location &actual_location2 = FlightSqlConnection::BuildLocation( + { + {FlightSqlConnection::HOST, std::string("localhost")}, + {FlightSqlConnection::PORT, std::string("32011")}, + {FlightSqlConnection::USE_TLS, std::string("1")}, + }, + missing_attr); Location expected_location; ASSERT_TRUE( @@ -97,14 +105,16 @@ TEST(BuildLocationTests, ForTls) { ASSERT_NE(expected_location, actual_location2); } -TEST(BuildCallOptionsTest, ConnectionTimeout) { +TEST(PopulateCallOptionsTest, ConnectionTimeout) { FlightSqlConnection connection(odbcabstraction::V_3); // Expect default timeout to be -1 - ASSERT_EQ(TimeoutDuration{-1.0}, connection.BuildCallOptions().timeout); + ASSERT_EQ(TimeoutDuration{-1.0}, + connection.PopulateCallOptionsFromAttributes().timeout); connection.SetAttribute(Connection::CONNECTION_TIMEOUT, 10.0); - ASSERT_EQ(TimeoutDuration{10.0}, connection.BuildCallOptions().timeout); + ASSERT_EQ(TimeoutDuration{10.0}, + connection.PopulateCallOptionsFromAttributes().timeout); } } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc new file mode 100644 index 0000000000000..8c6089dbdbb98 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -0,0 +1,143 @@ +// 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 "flight_sql_statement.h" + +#include +#include +#include +#include + +namespace driver { +namespace flight_sql { + +using arrow::Result; +using arrow::Status; +using arrow::flight::FlightCallOptions; +using arrow::flight::FlightClientOptions; +using arrow::flight::FlightInfo; +using arrow::flight::Location; +using arrow::flight::TimeoutDuration; +using arrow::flight::sql::FlightSqlClient; +using arrow::flight::sql::PreparedStatement; +using driver::odbcabstraction::DriverException; +using driver::odbcabstraction::ResultSet; +using driver::odbcabstraction::ResultSetMetadata; +using driver::odbcabstraction::Statement; + +namespace { +inline void ThrowIfNotOK(const Status &status) { + if (!status.ok()) { + throw DriverException(status.ToString()); + } +} +} // namespace + +FlightSqlStatement::FlightSqlStatement(FlightSqlClient &sql_client, + FlightCallOptions call_options) + : sql_client_(sql_client), call_options_(call_options) {} + +void FlightSqlStatement::SetAttribute(StatementAttributeId attribute, + const Attribute &value) { + attribute_[attribute] = value; +} + +boost::optional +FlightSqlStatement::GetAttribute(StatementAttributeId attribute) { + const auto &it = attribute_.find(attribute); + return boost::make_optional(it != attribute_.end(), it->second); +} + +boost::optional> +FlightSqlStatement::Prepare(const std::string &query) { + if (prepared_statement_.get() != nullptr) { + prepared_statement_->Close(); + prepared_statement_.reset(); + } + + Result> result = + sql_client_.Prepare(call_options_, query); + ThrowIfNotOK(result.status()); + + prepared_statement_ = *result; + + // TODO: Use the prepared statement to populate ResultSetMetaData. + return boost::optional>(); +} + +bool FlightSqlStatement::ExecutePrepared() { + assert(prepared_statement_.get() != nullptr); + + Result> result = prepared_statement_->Execute(); + ThrowIfNotOK(result.status()); + + // TODO: make use of the returned FlightInfo to populate ResultSetMetaData nd + // ResultSet. + return true; +} + +bool FlightSqlStatement::Execute(const std::string &query) { + if (prepared_statement_.get() != nullptr) { + prepared_statement_->Close(); + prepared_statement_.reset(); + } + + Result> result = + sql_client_.Execute(call_options_, query); + ThrowIfNotOK(result.status()); + + // TODO: make use of the returned FlightInfo to populate ResultSetMetaData nd + // ResultSet. + return true; +} + +std::shared_ptr FlightSqlStatement::GetResultSet() { + return current_result_; +} + +long FlightSqlStatement::GetUpdateCount() { return -1; } + +std::shared_ptr FlightSqlStatement::GetTables_V2( + const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, const std::string *table_type) { + return current_result_; +} + +std::shared_ptr FlightSqlStatement::GetTables_V3( + const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, const std::string *table_type) { + return current_result_; +} + +std::shared_ptr FlightSqlStatement::GetColumns_V2( + const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, const std::string *column_name) { + return current_result_; +} + +std::shared_ptr FlightSqlStatement::GetColumns_V3( + const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, const std::string *column_name) { + return current_result_; +} + +std::shared_ptr FlightSqlStatement::GetTypeInfo(int dataType) { + return current_result_; +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h new file mode 100644 index 0000000000000..9efcb0055745a --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h @@ -0,0 +1,76 @@ +// 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. + +#pragma once + +#include "arrow/flight/sql/client.h" +#include + +#include +#include + +namespace driver { +namespace flight_sql { + +class FlightSqlStatement : public odbcabstraction::Statement { + +private: + std::map attribute_; + arrow::flight::FlightCallOptions call_options_; + arrow::flight::sql::FlightSqlClient &sql_client_; + std::shared_ptr current_result_; + std::shared_ptr prepared_statement_; + +public: + FlightSqlStatement(arrow::flight::sql::FlightSqlClient &sql_client, + arrow::flight::FlightCallOptions call_options); + + void SetAttribute(StatementAttributeId attribute, const Attribute &value); + + boost::optional GetAttribute(StatementAttributeId attribute); + + boost::optional> + Prepare(const std::string &query); + + bool ExecutePrepared(); + + bool Execute(const std::string &query); + + std::shared_ptr GetResultSet(); + + long GetUpdateCount(); + + std::shared_ptr + GetTables_V2(const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, const std::string *table_type); + + std::shared_ptr + GetTables_V3(const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, const std::string *table_type); + + std::shared_ptr + GetColumns_V2(const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, const std::string *column_name); + + std::shared_ptr + GetColumns_V3(const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, const std::string *column_name); + + std::shared_ptr GetTypeInfo(int dataType); +}; +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h index dc31471172fa6..e46914e1ce3e0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h @@ -34,6 +34,8 @@ class ResultSetMetadata; /// \brief High-level representation of an ODBC statement. class Statement { public: + virtual ~Statement() = default; + /// \brief Statement attributes that can be called at anytime. ////TODO: Document attributes enum StatementAttributeId { From 28997d57fbc86f0ea05c0ae7c9f72ff1293fc405 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Thu, 20 Jan 2022 16:13:17 -0300 Subject: [PATCH 058/183] Add ResultSetMetadata interface to odbc abstraction layer Change-Id: Ibc441ac2ddf9554b3a6a2b6d34b03324b9a0272a --- .../include/odbcabstraction/connection.h | 3 + .../include/odbcabstraction/driver.h | 3 + .../include/odbcabstraction/result_set.h | 21 +- .../odbcabstraction/result_set_metadata.h | 186 ++++++++++++++++++ .../include/odbcabstraction/statement.h | 3 + .../include/odbcabstraction/types.h | 36 ++++ 6 files changed, 238 insertions(+), 14 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set_metadata.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index fefd3e8718a71..0d3e8d811c301 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -32,6 +32,9 @@ class Statement; /// \brief High-level representation of an ODBC connection. class Connection { +protected: + Connection() = default; + public: virtual ~Connection() = default; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h index cb64509b416e3..e7002bc740889 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h @@ -28,6 +28,9 @@ class Connection; /// \brief High-level representation of an ODBC driver. class Driver { +protected: + Driver() = default; + public: virtual ~Driver() = default; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h index 8adfa19589bf1..616d3cd15a127 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h @@ -19,6 +19,8 @@ #include #include +#include + #pragma once namespace driver { @@ -26,22 +28,13 @@ namespace odbcabstraction { class ResultSetMetadata; -enum DataType { - UNKNOWN_TYPE = SQL_UNKNOWN_TYPE, - CHAR = SQL_CHAR, - NUMERIC = SQL_NUMERIC, - DECIMAL = SQL_DECIMAL, - INTEGER = SQL_INTEGER, - SMALLINT = SQL_SMALLINT, - FLOAT = SQL_FLOAT, - REAL = SQL_REAL, - DOUBLE = SQL_DOUBLE, - DATETIME = SQL_DATETIME, - VARCHAR = SQL_VARCHAR, -}; - class ResultSet { +protected: + ResultSet() = default; + public: + virtual ~ResultSet() = default; + /// \brief Returns metadata for this ResultSet. virtual std::shared_ptr GetMetadata() = 0; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set_metadata.h new file mode 100644 index 0000000000000..006ff388b6860 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set_metadata.h @@ -0,0 +1,186 @@ +// 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. + +#pragma once + +#include +#include + +namespace driver { +namespace odbcabstraction { + +/// \brief High Level representation of the ResultSetMetadata from ODBC. +class ResultSetMetadata { +protected: + ResultSetMetadata() = default; + +public: + virtual ~ResultSetMetadata() = default; + + /// \brief It returns the total amount of the columns in the ResultSet. + /// \return the amount of columns. + virtual size_t GetColumnCount() = 0; + + /// \brief It retrieves the name of a specific column. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the column name. + virtual std::string GetColumnName(int column_position) = 0; + + /// \brief It retrieves the size of a specific column. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the column size. + virtual size_t GetPrecision(int column_position) = 0; + + /// \brief It retrieves the total of number of decimal digits. + /// \param column_position[in] the position of the column, starting from 1. + /// \return amount of decimal digits. + virtual size_t GetScale(int column_position) = 0; + + /// \brief It retrieves the SQL_DATA_TYPE of the column. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the SQL_DATA_TYPE + virtual DataType GetDataType(int column_position) = 0; + + /// \brief It returns a boolean value indicating if the column can have + /// null values. + /// \param column_position[in] the position of the column, starting from 1. + /// \return true if column is nullable. + virtual Nullability IsNullable(int column_position) = 0; + + /// \brief It returns the Schema name for a specific column. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the Schema name for given column. + virtual std::string GetSchemaName(int column_position) = 0; + + /// \brief It returns the Catalog Name for a specific column. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the catalog name for given column. + virtual std::string GetCatalogName(int column_position) = 0; + + /// \brief It returns the Table Name for a specific column. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the Table name for given column. + virtual std::string GetTableName(int column_position) = 0; + + /// \brief It retrieves the column label. + /// \param column_position[in] the position of the column, starting from 1. + /// \return column label. + virtual std::string GetColumnLabel(int column_position) = 0; + + /// \brief It retrieves the designated column's normal maximum width in + /// characters. + /// \param column_position[in] the position of the column, starting from 1. + /// \return column normal maximum width. + virtual size_t GetColumnDisplaySize(int column_position) = 0; + + /// \brief It retrieves the base name for the column. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the base column name. + virtual std::string GetBaseColumnName(int column_position) = 0; + + /// \brief It retrieves the base table name that contains the column. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the base table name. + virtual std::string GetBaseTableName(int column_position) = 0; + + /// \brief It retrieves the concise data type. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the concise data type. + virtual std::string GetConciseType(int column_position) = 0; + + /// \brief It retrieves the maximum or the actual character length + /// of a character string or binary data type. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the maximum length + virtual size_t GetLength(int column_position) = 0; + + /// \brief It retrieves the character or characters that the driver uses + /// as prefix for literal values. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the prefix character(s). + virtual std::string GetLiteralPrefix(int column_position) = 0; + + /// \brief It retrieves the character or characters that the driver uses + /// as prefix for literal values. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the suffix character(s). + virtual std::string GetLiteralSuffix(int column_position) = 0; + + /// \brief It retrieves the local type name for a specific column. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the local type name. + virtual std::string GetLocalTypeName(int column_position) = 0; + + /// \brief It returns the column name alias. If it has no alias + /// it returns the column name. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the column name alias. + virtual std::string GetName(int column_position) = 0; + + /// \brief It returns a numeric value to indicate if the data + /// is an approximate or exact numeric data type. + /// \param column_position[in] the position of the column, starting from 1. + virtual size_t GetNumPrecRadix(int column_position) = 0; + + /// \brief It returns the length in bytes from a string or binary data. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the length in bytes. + virtual size_t GetOctetLength(int column_position) = 0; + + /// \brief It returns the data type as a string. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the data type string. + virtual std::string GetTypeName(int column_position) = 0; + + /// \brief It returns a numeric values indicate the updatability of the + /// column. + /// \param column_position[in] the position of the column, starting from 1. + /// \return the updatability of the column. + virtual Updatability GetUpdatable(int column_position) = 0; + + /// \brief It returns a boolean value indicating if the column is + /// autoincrementing. + /// \param column_position[in] the position of the column, starting from 1. + /// \return boolean values if column is auto incremental. + virtual bool IsAutoUnique(int column_position) = 0; + + /// \brief It returns a boolean value indicating if the column is + /// case sensitive. + /// \param column_position[in] the position of the column, starting from 1. + /// \return boolean values if column is case sensitive. + virtual bool IsCaseSensitive(int column_position) = 0; + + /// \brief It returns a boolean value indicating if the column can be used + /// in where clauses. + /// \param column_position[in] the position of the column, starting from 1. + /// \return boolean values if column can be used in where clauses. + virtual Searchability IsSearchable(int column_position) = 0; + + /// \brief It checks if a numeric column is signed or unsigned. + /// \param column_position[in] the position of the column, starting from 1. + /// \return check if the column is signed or not. + virtual bool IsUnsigned(int column_position) = 0; + + /// \brief It check if the columns has fixed precision and a nonzero + /// scale. + /// \param column_position[in] the position of the column, starting from 1. + /// \return if column has a fixed precision and non zero scale. + virtual bool IsFixedPrecScale(int column_position) = 0; +}; + +} // namespace odbcabstraction +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h index e46914e1ce3e0..650d40afe3b6d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h @@ -33,6 +33,9 @@ class ResultSetMetadata; /// \brief High-level representation of an ODBC statement. class Statement { +protected: + Statement() = default; + public: virtual ~Statement() = default; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 626c1c26e02a8..d57a7fad43c9a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -17,11 +17,47 @@ #pragma once +#include +#include + namespace driver { namespace odbcabstraction { /// \brief Supported ODBC versions. enum OdbcVersion { V_2, V_3, V_4 }; +enum DataType { + UNKNOWN_TYPE = SQL_UNKNOWN_TYPE, + CHAR = SQL_CHAR, + NUMERIC = SQL_NUMERIC, + DECIMAL = SQL_DECIMAL, + INTEGER = SQL_INTEGER, + SMALLINT = SQL_SMALLINT, + FLOAT = SQL_FLOAT, + REAL = SQL_REAL, + DOUBLE = SQL_DOUBLE, + DATETIME = SQL_DATETIME, + VARCHAR = SQL_VARCHAR, +}; + +enum Nullability { + NULLABILITY_NO_NULLS = SQL_NO_NULLS, + NULLABILITY_NULLABLE = SQL_NULLABLE, + NULLABILITY_UNKNOWN = SQL_NULLABLE_UNKNOWN, +}; + +enum Searchability { + SEARCHABILITY_NONE = SQL_PRED_NONE, + SEARCHABILITY_LIKE_ONLY = SQL_LIKE_ONLY, + SEARCHABILITY_ALL_EXPECT_LIKE = SQL_ALL_EXCEPT_LIKE, + SEARCHABILITY_ALL = SQL_SEARCHABLE, +}; + +enum Updatability { + UPDATABILITY_READONLY = SQL_ATTR_READONLY, + UPDATABILITY_WRITE = SQL_ATTR_WRITE, + UPDATABILITY_READWRITE_UNKNOWN = SQL_ATTR_READWRITE_UNKNOWN, +}; + } // namespace odbcabstraction } // namespace driver From 288782020ca68f3002a6e047341b91b42a8e05fc Mon Sep 17 00:00:00 2001 From: James Duong Date: Tue, 25 Jan 2022 12:39:19 -0800 Subject: [PATCH 059/183] Fix build issues - Remove duplicated constructor definitions in interfaces. - Remove ODBC header dependencies because some of the symbols get defined in Arrow headers. - Use the odbcabstraction sub-directory when referencing public headers. Change-Id: Ic297011af8ff75ddd3d6896c5aa05c0a3bd5ba43 --- .../include/odbcabstraction/connection.h | 5 +- .../include/odbcabstraction/driver.h | 5 +- .../include/odbcabstraction/result_set.h | 1 - .../include/odbcabstraction/types.h | 46 +++++++++---------- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index 0d3e8d811c301..8bc57a0611ce1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -21,7 +21,7 @@ #include #include -#include "types.h" +#include #pragma once @@ -91,9 +91,6 @@ class Connection { /// \brief Retrieves info from the database (see ODBC's SQLGetInfo). virtual Info GetInfo(uint16_t info_type) = 0; - -protected: - Connection() = default; }; } // namespace odbcabstraction diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h index e7002bc740889..9d23e77980b5e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h @@ -17,7 +17,7 @@ #include -#include "types.h" +#include #pragma once @@ -38,9 +38,6 @@ class Driver { /// \param odbc_version ODBC version to be used. virtual std::shared_ptr CreateConnection(OdbcVersion odbc_version) = 0; - -protected: - Driver() = default; }; } // namespace odbcabstraction diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h index 616d3cd15a127..af5983631b74d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h @@ -17,7 +17,6 @@ #include #include -#include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index d57a7fad43c9a..573320cb930af 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -17,46 +17,44 @@ #pragma once -#include -#include - namespace driver { namespace odbcabstraction { /// \brief Supported ODBC versions. enum OdbcVersion { V_2, V_3, V_4 }; +// Based on ODBC sql.h definitions. enum DataType { - UNKNOWN_TYPE = SQL_UNKNOWN_TYPE, - CHAR = SQL_CHAR, - NUMERIC = SQL_NUMERIC, - DECIMAL = SQL_DECIMAL, - INTEGER = SQL_INTEGER, - SMALLINT = SQL_SMALLINT, - FLOAT = SQL_FLOAT, - REAL = SQL_REAL, - DOUBLE = SQL_DOUBLE, - DATETIME = SQL_DATETIME, - VARCHAR = SQL_VARCHAR, + UNKNOWN_TYPE = 0, + CHAR = 1, + NUMERIC = 2, + DECIMAL = 3, + INTEGER = 4, + SMALLINT = 5, + FLOAT = 6, + REAL = 7, + DOUBLE = 8, + DATETIME = 9, + VARCHAR = 12, }; enum Nullability { - NULLABILITY_NO_NULLS = SQL_NO_NULLS, - NULLABILITY_NULLABLE = SQL_NULLABLE, - NULLABILITY_UNKNOWN = SQL_NULLABLE_UNKNOWN, + NULLABILITY_NO_NULLS = 0, + NULLABILITY_NULLABLE = 1, + NULLABILITY_UNKNOWN = 2, }; enum Searchability { - SEARCHABILITY_NONE = SQL_PRED_NONE, - SEARCHABILITY_LIKE_ONLY = SQL_LIKE_ONLY, - SEARCHABILITY_ALL_EXPECT_LIKE = SQL_ALL_EXCEPT_LIKE, - SEARCHABILITY_ALL = SQL_SEARCHABLE, + SEARCHABILITY_NONE = 0, + SEARCHABILITY_LIKE_ONLY = 1, + SEARCHABILITY_ALL_EXPECT_LIKE = 2, + SEARCHABILITY_ALL = 3, }; enum Updatability { - UPDATABILITY_READONLY = SQL_ATTR_READONLY, - UPDATABILITY_WRITE = SQL_ATTR_WRITE, - UPDATABILITY_READWRITE_UNKNOWN = SQL_ATTR_READWRITE_UNKNOWN, + UPDATABILITY_READONLY = 0, + UPDATABILITY_WRITE = 1, + UPDATABILITY_READWRITE_UNKNOWN = 2, }; } // namespace odbcabstraction From 5ce57a319ea48347bb01ca58c0ae75a30fb90a43 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Thu, 20 Jan 2022 18:17:00 -0300 Subject: [PATCH 060/183] Define Accessor interface for ODBC abstraction Change-Id: I8a0eac87e3a5513cb2244381c7759b29a0c8c3fb --- .../odbcabstraction/columnar_result_set.h | 177 ++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/columnar_result_set.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/columnar_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/columnar_result_set.h new file mode 100644 index 0000000000000..ff25e686e1860 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/columnar_result_set.h @@ -0,0 +1,177 @@ +// 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 + +#pragma once + +namespace driver { +namespace odbcabstraction { + +/// \brief Accessor interface meant to provide a way of populating data of a +/// single column to buffers bound by `ColumnarResultSet::BindColumn`. +class Accessor { +public: + /// \brief Populates next cells + virtual size_t Move(size_t cells) = 0; +}; + +/// \brief Accessor CRTP base class, meant to enable efficient calls to +/// specialized `Move_*` methods for each possible target data type without +/// relying on virtual method calls. +template +class TypedAccessor : public Accessor { + size_t Move(size_t cells) override { + if (TARGET_TYPE == CHAR) { + return Move_CHAR(cells); + } else if (TARGET_TYPE == NUMERIC) { + return Move_NUMERIC(cells); + } else if (TARGET_TYPE == DECIMAL) { + return Move_DECIMAL(cells); + } else if (TARGET_TYPE == INTEGER) { + return Move_INTEGER(cells); + } else if (TARGET_TYPE == SMALLINT) { + return Move_SMALLINT(cells); + } else if (TARGET_TYPE == FLOAT) { + return Move_FLOAT(cells); + } else if (TARGET_TYPE == REAL) { + return Move_REAL(cells); + } else if (TARGET_TYPE == DOUBLE) { + return Move_DOUBLE(cells); + } else if (TARGET_TYPE == DATETIME) { + return Move_DATETIME(cells); + } else if (TARGET_TYPE == VARCHAR) { + return Move_VARCHAR(cells); + } + } + + /// \brief Populates bound buffers with next cells as CHAR values. + size_t Move_CHAR(size_t cells) { + return static_cast(this)->Move_CHAR(cells); + } + + /// \brief Populates bound buffers with next cells as NUMERIC values. + size_t Move_NUMERIC(size_t cells) { + return static_cast(this)->Move_NUMERIC(cells); + } + + /// \brief Populates bound buffers with next cells as DECIMAL values. + size_t Move_DECIMAL(size_t cells) { + return static_cast(this)->Move_DECIMAL(cells); + } + + /// \brief Populates bound buffers with next cells as INTEGER values. + size_t Move_INTEGER(size_t cells) { + return static_cast(this)->Move_INTEGER(cells); + } + + /// \brief Populates bound buffers with next cells as SMALLINT values. + size_t Move_SMALLINT(size_t cells) { + return static_cast(this)->Move_SMALLINT(cells); + } + + /// \brief Populates bound buffers with next cells as FLOAT values. + size_t Move_FLOAT(size_t cells) { + return static_cast(this)->Move_FLOAT(cells); + } + + /// \brief Populates bound buffers with next cells as REAL values. + size_t Move_REAL(size_t cells) { + return static_cast(this)->Move_REAL(cells); + } + + /// \brief Populates bound buffers with next cells as DOUBLE values. + size_t Move_DOUBLE(size_t cells) { + return static_cast(this)->Move_DOUBLE(cells); + } + + /// \brief Populates bound buffers with next cells as DATETIME values. + size_t Move_DATETIME(size_t cells) { + return static_cast(this)->Move_DATETIME(cells); + } + + /// \brief Populates bound buffers with next cells as VARCHAR values. + size_t Move_VARCHAR(size_t cells) { + return static_cast(this)->Move_VARCHAR(cells); + } +}; + +/// \brief ResultSet specialized for retrieving data in columnar format. +/// This requires a AccessorFactory instance for creating specialized column +/// accessors for each column bound by calling `BindColumn`. +class ColumnarResultSet : public ResultSet { +private: + std::shared_ptr metadata_; + std::vector> accessors_; + +protected: + ColumnarResultSet(std::shared_ptr metadata) + : metadata_(std::move(metadata)), accessors_(metadata->GetColumnCount()) { + } + + /// \brief Creates a Accessor for given column and target data type bound to + /// given buffers. + virtual std::unique_ptr + CreateAccessor(int column, DataType target_type, int precision, int scale, + void *buffer, size_t buffer_length, size_t *strlen_buffer, + size_t strlen_buffer_len) = 0; + +public: + std::shared_ptr GetMetadata() override { + return std::move(metadata_); + } + + void BindColumn(int column, DataType target_type, int precision, int scale, + void *buffer, size_t buffer_length, size_t *strlen_buffer, + size_t strlen_buffer_len) override { + if (buffer == nullptr) { + accessors_[column] = nullptr; + return; + } + accessors_[column] = + CreateAccessor(column, target_type, precision, scale, buffer, + buffer_length, strlen_buffer, strlen_buffer_len); + } + + size_t Move(size_t rows) override { + size_t fetched_rows = -1; + for (auto it = accessors_.begin(); it != accessors_.end(); *it++) { + // There can be unbound columns. + if (*it == nullptr) + continue; + + size_t accessor_rows = (*it)->Move(rows); + if (fetched_rows == -1) { + // Stores the number of rows moved on the first bound column, expecting + // that all columns move the same number of rows. + fetched_rows = accessor_rows; + } else if (accessor_rows != fetched_rows) { + throw DriverException( + "Expected the same number of rows for all columns"); + } + } + return fetched_rows; + } +}; + +} // namespace odbcabstraction +} // namespace driver From 6671aa1570b76bdb4deec7c8d832f72910cf0dbf Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Thu, 27 Jan 2022 20:17:29 -0300 Subject: [PATCH 061/183] Implement minimal types on ResultSetMetadata Also add stub ResultSet implementation that just holds the metadata. Change-Id: Ib2213ea9111fa087058096428d987f52d52f2af8 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 3 +- .../flight_sql/flight_sql_auth_method.cc | 2 +- .../flight_sql/flight_sql_auth_method.h | 2 +- .../flight_sql/flight_sql_driver.cc | 2 +- .../flight_sql/flight_sql_result_set.h | 67 +++++ .../flight_sql_result_set_metadata.cc | 238 ++++++++++++++++++ .../flight_sql_result_set_metadata.h | 89 +++++++ .../flight_sql/flight_sql_statement.cc | 53 ++-- .../flight_sql/flight_sql_statement.h | 5 +- .../flightsql-odbc/flight_sql/main.cc | 10 +- .../include/odbcabstraction/types.h | 10 + 11 files changed, 457 insertions(+), 24 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 29c9a157c420b..cda12c8c8083f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -85,8 +85,9 @@ enable_testing() set(ARROW_ODBC_SPI_SOURCES flight_sql_auth_method.cc - flight_sql_driver.cc flight_sql_connection.cc + flight_sql_driver.cc + flight_sql_result_set_metadata.cc flight_sql_statement.cc ) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index bc7da67a6768b..af5f2f91e3feb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -17,8 +17,8 @@ #include "flight_sql_auth_method.h" -#include #include "flight_sql_connection.h" +#include #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index 5150f68f5557c..0d897b7dfdda5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -17,11 +17,11 @@ #pragma once -#include #include "flight_sql_connection.h" #include #include #include +#include namespace driver { namespace flight_sql { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index 4bbc627223fc1..49f18b4211406 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -15,8 +15,8 @@ // specific language governing permissions and limitations // under the License. -#include #include "flight_sql_connection.h" +#include namespace driver { namespace flight_sql { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h new file mode 100644 index 0000000000000..cd1012403891f --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -0,0 +1,67 @@ +// 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 + +#pragma once + +namespace driver { +namespace odbcabstraction { +class ResultSetMetadata; +} +} // namespace driver + +namespace driver { +namespace flight_sql { +class FlightSqlResultSet : public odbcabstraction::ResultSet { +private: + std::shared_ptr metadata_; + +public: + explicit FlightSqlResultSet( + std::shared_ptr metadata) + : metadata_(metadata) {} + +public: + virtual ~FlightSqlResultSet() = default; + + virtual std::shared_ptr GetMetadata() { + return metadata_; + }; + + virtual void Close() {} + + virtual void BindColumn(int column, odbcabstraction::DataType target_type, + int precision, int scale, void *buffer, + size_t buffer_length, size_t *strlen_buffer, + size_t strlen_buffer_len) {} + + virtual size_t Move(size_t rows) { return 0; } + + virtual bool GetData(int column, odbcabstraction::DataType target_type, + int precision, int scale, void *buffer, + size_t buffer_length, size_t *strlen_buffer) { + return false; + }; +}; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc new file mode 100644 index 0000000000000..bc9fa16c7167a --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -0,0 +1,238 @@ +// 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 "flight_sql_result_set_metadata.h" +#include "arrow/util/key_value_metadata.h" + +#include +#include + +namespace driver { +namespace flight_sql { + +using arrow::DataType; +using arrow::Field; + +size_t FlightSqlResultSetMetadata::GetColumnCount() { + return schema->num_fields(); +} + +std::string FlightSqlResultSetMetadata::GetColumnName(int column_position) { + return schema->field(column_position - 1)->name(); +} + +std::string FlightSqlResultSetMetadata::GetName(int column_position) { + // TODO Get column alias from column metadata + return schema->field(column_position - 1)->name(); +} + +size_t FlightSqlResultSetMetadata::GetPrecision(int column_position) { + // TODO Implement after the PR from column metadata is merged + return 0; +} + +size_t FlightSqlResultSetMetadata::GetScale(int column_position) { + // TODO Implement after the PR from column metadata is merged + return 0; +} + +driver::odbcabstraction::DataType +FlightSqlResultSetMetadata::GetDataType(int column_position) { + const std::shared_ptr &field = schema->field(column_position - 1); + const std::shared_ptr &type = field->type(); + + switch (type->id()) { + case arrow::Type::BOOL: + return odbcabstraction::BIT; + case arrow::Type::UINT8: + case arrow::Type::INT8: + return odbcabstraction::TINYINT; + case arrow::Type::UINT16: + case arrow::Type::INT16: + return odbcabstraction::SMALLINT; + case arrow::Type::UINT32: + case arrow::Type::INT32: + return odbcabstraction::INTEGER; + case arrow::Type::UINT64: + case arrow::Type::INT64: + return odbcabstraction::BIGINT; + case arrow::Type::HALF_FLOAT: + case arrow::Type::FLOAT: + return odbcabstraction::FLOAT; + case arrow::Type::DOUBLE: + return odbcabstraction::DOUBLE; + case arrow::Type::BINARY: + case arrow::Type::FIXED_SIZE_BINARY: + case arrow::Type::LARGE_BINARY: + return odbcabstraction::BINARY; + case arrow::Type::STRING: + case arrow::Type::LARGE_STRING: + return odbcabstraction::VARCHAR; + case arrow::Type::DATE32: + case arrow::Type::DATE64: + case arrow::Type::TIMESTAMP: + return odbcabstraction::DATETIME; + case arrow::Type::DECIMAL128: + case arrow::Type::DECIMAL256: + return odbcabstraction::DECIMAL; + case arrow::Type::TIME32: + case arrow::Type::TIME64: + return odbcabstraction::TIME; + + // TODO: Handle remaining types. + case arrow::Type::INTERVAL_MONTHS: + case arrow::Type::INTERVAL_DAY_TIME: + case arrow::Type::INTERVAL_MONTH_DAY_NANO: + case arrow::Type::LIST: + case arrow::Type::STRUCT: + case arrow::Type::SPARSE_UNION: + case arrow::Type::DENSE_UNION: + case arrow::Type::DICTIONARY: + case arrow::Type::MAP: + case arrow::Type::EXTENSION: + case arrow::Type::FIXED_SIZE_LIST: + case arrow::Type::DURATION: + case arrow::Type::LARGE_LIST: + case arrow::Type::MAX_ID: + case arrow::Type::NA: + break; + } + + throw driver::odbcabstraction::DriverException("Unsupported data type: " + + type->ToString()); +} + +driver::odbcabstraction::Nullability +FlightSqlResultSetMetadata::IsNullable(int column_position) { + // TODO Implement after the PR from column metadata is merged + return odbcabstraction::NULLABILITY_NO_NULLS; +} + +std::string FlightSqlResultSetMetadata::GetSchemaName(int column_position) { + // TODO Implement after the PR from column metadata is merged + return ""; +} + +std::string FlightSqlResultSetMetadata::GetCatalogName(int column_position) { + // TODO Implement after the PR from column metadata is merged + return ""; +} + +std::string FlightSqlResultSetMetadata::GetTableName(int column_position) { + // TODO Implement after the PR from column metadata is merged + return ""; +} + +std::string FlightSqlResultSetMetadata::GetColumnLabel(int column_position) { + // TODO Implement after the PR from column metadata is merged + return ""; +} + +size_t FlightSqlResultSetMetadata::GetColumnDisplaySize( + // TODO Implement after the PR from column metadata is merged + int column_position) { + return 0; +} + +std::string FlightSqlResultSetMetadata::GetBaseColumnName(int column_position) { + // TODO Implement after the PR from column metadata is merged + return ""; +} + +std::string FlightSqlResultSetMetadata::GetBaseTableName(int column_position) { + // TODO Implement after the PR from column metadata is merged + return ""; +} + +std::string FlightSqlResultSetMetadata::GetConciseType(int column_position) { + // TODO Implement after the PR from column metadata is merged + return ""; +} + +size_t FlightSqlResultSetMetadata::GetLength(int column_position) { + // TODO Implement after the PR from column metadata is merged + return 0; +} + +std::string FlightSqlResultSetMetadata::GetLiteralPrefix(int column_position) { + // TODO Implement after the PR from column metadata is merged + return ""; +} + +std::string FlightSqlResultSetMetadata::GetLiteralSuffix(int column_position) { + // TODO Implement after the PR from column metadata is merged + return ""; +} + +std::string FlightSqlResultSetMetadata::GetLocalTypeName(int column_position) { + // TODO Implement after the PR from column metadata is merged + return ""; +} + +size_t FlightSqlResultSetMetadata::GetNumPrecRadix(int column_position) { + // TODO Implement after the PR from column metadata is merged + return 0; +} + +size_t FlightSqlResultSetMetadata::GetOctetLength(int column_position) { + // TODO Implement after the PR from column metadata is merged + return 0; +} + +std::string FlightSqlResultSetMetadata::GetTypeName(int column_position) { + // TODO Implement after the PR from column metadata is merged + return ""; +} + +driver::odbcabstraction::Updatability +FlightSqlResultSetMetadata::GetUpdatable(int column_position) { + // TODO Implement after the PR from column metadata is merged + return odbcabstraction::UPDATABILITY_READWRITE_UNKNOWN; +} + +bool FlightSqlResultSetMetadata::IsAutoUnique(int column_position) { + // TODO Implement after the PR from column metadata is merged + return false; +} + +bool FlightSqlResultSetMetadata::IsCaseSensitive(int column_position) { + // TODO Implement after the PR from column metadata is merged + return false; +} + +driver::odbcabstraction::Searchability +FlightSqlResultSetMetadata::IsSearchable(int column_position) { + // TODO Implement after the PR from column metadata is merged + return odbcabstraction::SEARCHABILITY_NONE; +} + +bool FlightSqlResultSetMetadata::IsUnsigned(int column_position) { + // TODO Implement after the PR from column metadata is merged + return false; +} + +bool FlightSqlResultSetMetadata::IsFixedPrecScale(int column_position) { + // TODO Implement after the PR from column metadata is merged + return false; +} + +FlightSqlResultSetMetadata::FlightSqlResultSetMetadata( + std::shared_ptr schema) + : schema(std::move(schema)) {} + +} // namespace flight_sql +} // namespace driver \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h new file mode 100644 index 0000000000000..e7ffc760bac9c --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h @@ -0,0 +1,89 @@ +// 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. + +#pragma once + +#include +#include + +namespace driver { +namespace flight_sql { +class FlightSqlResultSetMetadata : public odbcabstraction::ResultSetMetadata { +private: + std::shared_ptr schema; + +public: + explicit FlightSqlResultSetMetadata(std::shared_ptr schema); + + size_t GetColumnCount() override; + + std::string GetColumnName(int column_position) override; + + size_t GetPrecision(int column_position) override; + + size_t GetScale(int column_position) override; + + odbcabstraction::DataType GetDataType(int column_position) override; + + odbcabstraction::Nullability IsNullable(int column_position) override; + + std::string GetSchemaName(int column_position) override; + + std::string GetCatalogName(int column_position) override; + + std::string GetTableName(int column_position) override; + + std::string GetColumnLabel(int column_position) override; + + size_t GetColumnDisplaySize(int column_position) override; + + std::string GetBaseColumnName(int column_position) override; + + std::string GetBaseTableName(int column_position) override; + + std::string GetConciseType(int column_position) override; + + size_t GetLength(int column_position) override; + + std::string GetLiteralPrefix(int column_position) override; + + std::string GetLiteralSuffix(int column_position) override; + + std::string GetLocalTypeName(int column_position) override; + + std::string GetName(int column_position) override; + + size_t GetNumPrecRadix(int column_position) override; + + size_t GetOctetLength(int column_position) override; + + std::string GetTypeName(int column_position) override; + + odbcabstraction::Updatability GetUpdatable(int column_position) override; + + bool IsAutoUnique(int column_position) override; + + bool IsCaseSensitive(int column_position) override; + + odbcabstraction::Searchability IsSearchable(int column_position) override; + + bool IsUnsigned(int column_position) override; + + bool IsFixedPrecScale(int column_position) override; +}; +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index 8c6089dbdbb98..f2511faad467d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -16,10 +16,10 @@ // under the License. #include "flight_sql_statement.h" +#include "flight_sql_result_set.h" +#include "flight_sql_result_set_metadata.h" -#include #include -#include #include namespace driver { @@ -45,6 +45,16 @@ inline void ThrowIfNotOK(const Status &status) { throw DriverException(status.ToString()); } } + +std::shared_ptr +CreateResultSetMetaData(const std::shared_ptr &flight_info) { + std::shared_ptr schema; + arrow::ipc::DictionaryMemo dict_memo; + + ThrowIfNotOK(flight_info->GetSchema(&dict_memo, &schema)); + + return std::make_shared(schema); +} } // namespace FlightSqlStatement::FlightSqlStatement(FlightSqlClient &sql_client, @@ -65,7 +75,7 @@ FlightSqlStatement::GetAttribute(StatementAttributeId attribute) { boost::optional> FlightSqlStatement::Prepare(const std::string &query) { if (prepared_statement_.get() != nullptr) { - prepared_statement_->Close(); + ThrowIfNotOK(prepared_statement_->Close()); prepared_statement_.reset(); } @@ -75,8 +85,11 @@ FlightSqlStatement::Prepare(const std::string &query) { prepared_statement_ = *result; - // TODO: Use the prepared statement to populate ResultSetMetaData. - return boost::optional>(); + const auto &result_set_metadata = + std::make_shared( + prepared_statement_->dataset_schema()); + return boost::optional>( + result_set_metadata); } bool FlightSqlStatement::ExecutePrepared() { @@ -85,14 +98,17 @@ bool FlightSqlStatement::ExecutePrepared() { Result> result = prepared_statement_->Execute(); ThrowIfNotOK(result.status()); - // TODO: make use of the returned FlightInfo to populate ResultSetMetaData nd - // ResultSet. + current_result_set_metadata_ = CreateResultSetMetaData(result.ValueOrDie()); + + // TODO: make use of the returned FlightInfo to populate ResultSet. + current_result_set_ = std::shared_ptr( + new FlightSqlResultSet(current_result_set_metadata_)); return true; } bool FlightSqlStatement::Execute(const std::string &query) { - if (prepared_statement_.get() != nullptr) { - prepared_statement_->Close(); + if (prepared_statement_ != nullptr) { + ThrowIfNotOK(prepared_statement_->Close()); prepared_statement_.reset(); } @@ -100,13 +116,16 @@ bool FlightSqlStatement::Execute(const std::string &query) { sql_client_.Execute(call_options_, query); ThrowIfNotOK(result.status()); - // TODO: make use of the returned FlightInfo to populate ResultSetMetaData nd - // ResultSet. + current_result_set_metadata_ = CreateResultSetMetaData(result.ValueOrDie()); + + // TODO: make use of the returned FlightInfo to populate ResultSet. + current_result_set_ = std::shared_ptr( + new FlightSqlResultSet(current_result_set_metadata_)); return true; } std::shared_ptr FlightSqlStatement::GetResultSet() { - return current_result_; + return current_result_set_; } long FlightSqlStatement::GetUpdateCount() { return -1; } @@ -114,29 +133,29 @@ long FlightSqlStatement::GetUpdateCount() { return -1; } std::shared_ptr FlightSqlStatement::GetTables_V2( const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *table_type) { - return current_result_; + return current_result_set_; } std::shared_ptr FlightSqlStatement::GetTables_V3( const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *table_type) { - return current_result_; + return current_result_set_; } std::shared_ptr FlightSqlStatement::GetColumns_V2( const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *column_name) { - return current_result_; + return current_result_set_; } std::shared_ptr FlightSqlStatement::GetColumns_V3( const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *column_name) { - return current_result_; + return current_result_set_; } std::shared_ptr FlightSqlStatement::GetTypeInfo(int dataType) { - return current_result_; + return current_result_set_; } } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h index 9efcb0055745a..0b5216f58c908 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h @@ -22,6 +22,7 @@ #include #include +#include namespace driver { namespace flight_sql { @@ -32,7 +33,9 @@ class FlightSqlStatement : public odbcabstraction::Statement { std::map attribute_; arrow::flight::FlightCallOptions call_options_; arrow::flight::sql::FlightSqlClient &sql_client_; - std::shared_ptr current_result_; + std::shared_ptr current_result_set_; + std::shared_ptr + current_result_set_metadata_; std::shared_ptr prepared_statement_; public: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 953a9a4f43226..6e5a34ad48ea2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -17,19 +17,25 @@ #include +#include "flight_sql_connection.h" +#include "flight_sql_result_set_metadata.h" +#include "flight_sql_statement.h" + #include #include -#include "flight_sql_connection.h" #include +#include using arrow::Status; using arrow::flight::FlightClient; using arrow::flight::Location; using arrow::flight::sql::FlightSqlClient; -using driver::flight_sql::FlightSqlDriver; using driver::flight_sql::FlightSqlConnection; +using driver::flight_sql::FlightSqlDriver; using driver::odbcabstraction::Connection; +using driver::odbcabstraction::ResultSetMetadata; +using driver::odbcabstraction::Statement; int main() { FlightSqlDriver driver; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 573320cb930af..28f3c037de85e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -35,7 +35,17 @@ enum DataType { REAL = 7, DOUBLE = 8, DATETIME = 9, + DATE = 91, + TIME = 92, + TIMESTAMP = 93, VARCHAR = 12, + LONGVARCHAR = -1, + BINARY = -2, + VARBINARY = -3, + LONGVARBINARY = -4, + BIGINT = -5, + TINYINT = -6, + BIT = -7, }; enum Nullability { From 62bc6689241f90511a0db47c0384fa528026418d Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Thu, 27 Jan 2022 20:17:29 -0300 Subject: [PATCH 062/183] Implement Flight SQL result set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implements ResultSet interface for Flight SQL. Current implementation addresses: - Access to Arrow’s String array and some basic conversions - Releasing Arrow resources when closing - BindColumn support for multiple rows - GetData support + repeated calls to get more data Change-Id: I9f0ba05ff2c0052d4a13a84d306007f674bb9a02 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 5 +- .../flight_sql/accessors/common.h | 82 +++++++ .../flight_sql/accessors/main.h | 73 ++++++ .../accessors/primitive_array_accessor.h | 224 +++++++++++++++++ .../accessors/string_array_accessor.h | 183 ++++++++++++++ .../flight_sql/accessors/types.h | 61 +++++ .../flight_sql/flight_sql_connection.cc | 4 + .../flight_sql/flight_sql_result_set.cc | 226 ++++++++++++++++++ .../flight_sql/flight_sql_result_set.h | 103 +++++--- .../flight_sql_result_set_accessors.cc | 110 +++++++++ .../flight_sql_result_set_accessors.h | 32 +++ .../flight_sql_result_set_metadata.cc | 29 +-- .../flight_sql_result_set_metadata.h | 2 +- .../flight_sql/flight_sql_statement.cc | 19 +- .../flightsql-odbc/flight_sql/main.cc | 119 ++++++++- .../flightsql-odbc/flight_sql/utils.h | 33 +++ .../odbcabstraction/columnar_result_set.h | 177 -------------- .../include/odbcabstraction/result_set.h | 9 +- .../odbcabstraction/result_set_metadata.h | 2 +- .../include/odbcabstraction/types.h | 81 +++++-- 20 files changed, 1305 insertions(+), 269 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/columnar_result_set.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index cda12c8c8083f..ae12deb8d7c67 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -87,9 +87,10 @@ set(ARROW_ODBC_SPI_SOURCES flight_sql_auth_method.cc flight_sql_connection.cc flight_sql_driver.cc + flight_sql_result_set.cc + flight_sql_result_set_accessors.cc flight_sql_result_set_metadata.cc - flight_sql_statement.cc -) + flight_sql_statement.cc) set(ARROW_ODBC_SPI_THIRDPARTY_LIBS arrow_flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h new file mode 100644 index 0000000000000..f6937b3650c29 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h @@ -0,0 +1,82 @@ +// 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. + +#pragma once + +#include "types.h" +#include +#include +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +template +inline size_t CopyFromArrayValuesToBinding(FlightSqlResultSet *result_set, + ColumnBinding *binding, + int64_t starting_row, size_t cells) { + const std::shared_ptr &array = + result_set->GetArrayForColumn(binding->column) + ->Slice(starting_row, static_cast(cells)); + auto *typed_array = reinterpret_cast(array.get()); + ssize_t element_size = sizeof(typename ARRAY_TYPE::value_type); + + for (int64_t i = 0; i < cells; ++i) { + if (array->IsNull(i)) { + binding->strlen_buffer[i] = NULL_DATA; + } else { + binding->strlen_buffer[i] = element_size; + } + } + + const auto *values = typed_array->raw_values(); + size_t value_length = std::min(static_cast(typed_array->length()), + binding->buffer_length); + memcpy(binding->buffer, values, element_size * value_length); + + return cells; +} + +inline void MoveToCharBuffer(ColumnBinding *binding, Array *array, int64_t i, + int64_t value_offset) { + const std::shared_ptr &scalar = array->GetScalar(i).ValueOrDie(); + const std::shared_ptr &utf8_scalar = + internal::checked_pointer_cast( + scalar->CastTo(utf8()).ValueOrDie()); + + const uint8_t *value = utf8_scalar->value->data(); + + size_t value_length = + std::min(static_cast(utf8_scalar->value->size() - value_offset), + binding->buffer_length); + + char *char_buffer = static_cast(binding->buffer); + memcpy(&char_buffer[i * binding->buffer_length], value + value_offset, + value_length); + if (value_length + 1 < binding->buffer_length) { + char_buffer[i * binding->buffer_length + value_length] = '\0'; + } + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = utf8_scalar->value->size() + 1; + } +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h new file mode 100644 index 0000000000000..65f9fad3e975e --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h @@ -0,0 +1,73 @@ +// 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. + +#pragma once + +#include "../flight_sql_result_set.h" +#include "types.h" +#include +#include + +namespace driver { +namespace flight_sql { + +using arrow::Array; +using odbcabstraction::CDataType; + +template +class FlightSqlAccessor : public Accessor { +public: + CDataType GetTargetType() override { return TARGET_TYPE; } + + size_t GetColumnarData(FlightSqlResultSet *result_set, ColumnBinding *binding, + int64_t starting_row, size_t cells, + int64_t value_offset) override { + const std::shared_ptr &array = + result_set->GetArrayForColumn(binding->column) + ->Slice(starting_row, cells); + for (int64_t i = 0; i < cells; ++i) { + if (array->IsNull(i)) { + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = odbcabstraction::NULL_DATA; + } else { + // TODO: Report error when data is null bor strlen_buffer is nullptr + } + continue; + } + + MoveSingleCell(binding, reinterpret_cast(array.get()), i, + value_offset); + } + + return cells; + } + +private: + inline void MoveSingleCell(ColumnBinding *binding, ARROW_ARRAY *array, + int64_t i, int64_t value_offset) { + std::stringstream ss; + ss << "Unknown type conversion from " << typeid(ARROW_ARRAY).name() + << " to target C type " << TARGET_TYPE; + throw odbcabstraction::DriverException(ss.str()); + } +}; + +} // namespace flight_sql +} // namespace driver + +#include "primitive_array_accessor.h" +#include "string_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h new file mode 100644 index 0000000000000..1e101aca774d7 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h @@ -0,0 +1,224 @@ +// 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. + +#pragma once + +#include "common.h" +#include "types.h" +#include +#include +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +/* + * Int64Array + */ + +template <> +inline size_t FlightSqlAccessor::GetColumnarData( + FlightSqlResultSet *result_set, ColumnBinding *binding, + int64_t starting_row, size_t cells, int64_t value_offset) { + return CopyFromArrayValuesToBinding(result_set, binding, + starting_row, cells); +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, Int64Array *array, int64_t i, + int64_t value_offset) { + MoveToCharBuffer(binding, array, i, value_offset); +} + +/* + * UInt64Array + */ + +template <> +inline size_t +FlightSqlAccessor::GetColumnarData( + FlightSqlResultSet *result_set, ColumnBinding *binding, + int64_t starting_row, size_t cells, int64_t value_offset) { + return CopyFromArrayValuesToBinding(result_set, binding, + starting_row, cells); +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, UInt64Array *array, int64_t i, + int64_t value_offset) { + MoveToCharBuffer(binding, array, i, value_offset); +} + +/* + * Int32Array + */ + +template <> +inline size_t FlightSqlAccessor::GetColumnarData( + FlightSqlResultSet *result_set, ColumnBinding *binding, + int64_t starting_row, size_t cells, int64_t value_offset) { + return CopyFromArrayValuesToBinding(result_set, binding, + starting_row, cells); +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, Int32Array *array, int64_t i, + int64_t value_offset) { + MoveToCharBuffer(binding, array, i, value_offset); +} + +/* + * UInt32Array + */ + +template <> +inline size_t FlightSqlAccessor::GetColumnarData( + FlightSqlResultSet *result_set, ColumnBinding *binding, + int64_t starting_row, size_t cells, int64_t value_offset) { + return CopyFromArrayValuesToBinding(result_set, binding, + starting_row, cells); +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, UInt32Array *array, int64_t i, + int64_t value_offset) { + MoveToCharBuffer(binding, array, i, value_offset); +} + +/* + * Int16Array + */ + +template <> +inline size_t FlightSqlAccessor::GetColumnarData( + FlightSqlResultSet *result_set, ColumnBinding *binding, + int64_t starting_row, size_t cells, int64_t value_offset) { + return CopyFromArrayValuesToBinding(result_set, binding, + starting_row, cells); +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, Int16Array *array, int64_t i, + int64_t value_offset) { + MoveToCharBuffer(binding, array, i, value_offset); +} + +/* + * UInt16Array + */ + +template <> +inline size_t FlightSqlAccessor::GetColumnarData( + FlightSqlResultSet *result_set, ColumnBinding *binding, + int64_t starting_row, size_t cells, int64_t value_offset) { + return CopyFromArrayValuesToBinding(result_set, binding, + starting_row, cells); +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, UInt16Array *array, int64_t i, + int64_t value_offset) { + MoveToCharBuffer(binding, array, i, value_offset); +} + +/* + * Int8Array + */ + +template <> +inline size_t FlightSqlAccessor::GetColumnarData( + FlightSqlResultSet *result_set, ColumnBinding *binding, + int64_t starting_row, size_t cells, int64_t value_offset) { + return CopyFromArrayValuesToBinding(result_set, binding, + starting_row, cells); +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, Int8Array *array, int64_t i, int64_t value_offset) { + MoveToCharBuffer(binding, array, i, value_offset); +} + +/* + * UInt8Array + */ + +template <> +inline size_t +FlightSqlAccessor::GetColumnarData( + FlightSqlResultSet *result_set, ColumnBinding *binding, + int64_t starting_row, size_t cells, int64_t value_offset) { + return CopyFromArrayValuesToBinding(result_set, binding, + starting_row, cells); +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, UInt8Array *array, int64_t i, + int64_t value_offset) { + MoveToCharBuffer(binding, array, i, value_offset); +} + +/* + * FloatArray + */ + +template <> +inline size_t FlightSqlAccessor::GetColumnarData( + FlightSqlResultSet *result_set, ColumnBinding *binding, + int64_t starting_row, size_t cells, int64_t value_offset) { + return CopyFromArrayValuesToBinding(result_set, binding, + starting_row, cells); +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, FloatArray *array, int64_t i, + int64_t value_offset) { + MoveToCharBuffer(binding, array, i, value_offset); +} + +/* + * DoubleArray + */ + +template <> +inline size_t FlightSqlAccessor::GetColumnarData( + FlightSqlResultSet *result_set, ColumnBinding *binding, + int64_t starting_row, size_t cells, int64_t value_offset) { + return CopyFromArrayValuesToBinding(result_set, binding, + starting_row, cells); +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, DoubleArray *array, int64_t i, + int64_t value_offset) { + MoveToCharBuffer(binding, array, i, value_offset); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h new file mode 100644 index 0000000000000..8d89f349c001a --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h @@ -0,0 +1,183 @@ +// 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. + +#pragma once + +#include "types.h" +#include +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, StringArray *array, int64_t i, + int64_t value_offset) { + // TODO: Handle truncation + size_t value_length = + std::min(static_cast(array->value_length(i) - value_offset), + binding->buffer_length); + const char *value = array->Value(i).data(); + + char *char_buffer = static_cast(binding->buffer); + memcpy(&char_buffer[i * binding->buffer_length], value + value_offset, + value_length); + if (value_length + 1 < binding->buffer_length) { + char_buffer[i * binding->buffer_length + value_length] = '\0'; + } + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = array->value_length(i) + 1; + } +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, StringArray *array, int64_t i, + int64_t value_offset) { + char *end; + static_cast(binding->buffer)[i] = + strtoll(array->GetView(i).data(), &end, 10); + if (*end) { + // TODO: Report error + } + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = sizeof(int64_t); + } +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, StringArray *array, int64_t i, + int64_t value_offset) { + char *end; + static_cast(binding->buffer)[i] = + strtoull(array->GetView(i).data(), &end, 10); + if (*end) { + // TODO: Report error + } + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = sizeof(uint64_t); + } +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, StringArray *array, int64_t i, + int64_t value_offset) { + char *end; + static_cast(binding->buffer)[i] = + strtol(array->GetView(i).data(), &end, 10); + if (*end) { + // TODO: Report error + } + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = sizeof(int32_t); + } +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, StringArray *array, int64_t i, + int64_t value_offset) { + char *end; + static_cast(binding->buffer)[i] = + strtoul(array->GetView(i).data(), &end, 10); + if (*end) { + // TODO: Report error + } + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = sizeof(int32_t); + } +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, StringArray *array, int64_t i, + int64_t value_offset) { + char *end; + static_cast(binding->buffer)[i] = + strtol(array->GetView(i).data(), &end, 10); + if (*end) { + // TODO: Report error + } + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = sizeof(int16_t); + } +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, StringArray *array, int64_t i, + int64_t value_offset) { + char *end; + static_cast(binding->buffer)[i] = + strtoul(array->GetView(i).data(), &end, 10); + if (*end) { + // TODO: Report error + } + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = sizeof(uint16_t); + } +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, StringArray *array, int64_t i, + int64_t value_offset) { + char *end; + static_cast(binding->buffer)[i] = + strtol(array->GetView(i).data(), &end, 10); + if (*end) { + // TODO: Report error + } + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = sizeof(int8_t); + } +} + +template <> +inline void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, StringArray *array, int64_t i, + int64_t value_offset) { + char *end; + static_cast(binding->buffer)[i] = + strtoul(array->GetView(i).data(), &end, 10); + if (*end) { + // TODO: Report error + } + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = sizeof(uint8_t); + } +} + +// TODO: Add other data type conversions + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h new file mode 100644 index 0000000000000..62876a6c84010 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h @@ -0,0 +1,61 @@ +// 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. + +#pragma once + +#include +#include +#include +#include + +namespace driver { +namespace flight_sql { + +using odbcabstraction::CDataType; + +struct ColumnBinding { + void *buffer; + ssize_t *strlen_buffer; + size_t buffer_length; + CDataType target_type; + int column; + int precision; + int scale; + + ColumnBinding(int column, CDataType target_type, int precision, int scale, + void *buffer, size_t buffer_length, ssize_t *strlen_buffer) + : column(column), target_type(target_type), precision(precision), + scale(scale), buffer(buffer), buffer_length(buffer_length), + strlen_buffer(strlen_buffer) {} +}; + +/// \brief Accessor interface meant to provide a way of populating data of a +/// single column to buffers bound by `ColumnarResultSet::BindColumn`. +class Accessor { +public: + virtual ~Accessor() = default; + + virtual CDataType GetTargetType() = 0; + + /// \brief Populates next cells + virtual size_t GetColumnarData(FlightSqlResultSet *result_set, + ColumnBinding *binding, int64_t starting_row, + size_t cells, int64_t value_offset) = 0; +}; + +} // namespace flight_sql +} // namespace driver \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index cc211d6f4123c..f2d108546c73a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -79,6 +79,10 @@ void FlightSqlConnection::Connect(const ConnPropertyMap &properties, FlightClientOptions client_options = BuildFlightClientOptions(properties, missing_attr); + const std::shared_ptr + &cookie_factory = arrow::flight::GetCookieFactory(); + client_options.middleware.push_back(cookie_factory); + std::unique_ptr flight_client; ThrowIfNotOK( FlightClient::Connect(location, client_options, &flight_client)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc new file mode 100644 index 0000000000000..8de76c8e50067 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -0,0 +1,226 @@ +// 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 "flight_sql_result_set.h" + +#include +#include +#include +#include + +#include "flight_sql_result_set_accessors.h" +#include "flight_sql_result_set_metadata.h" +#include "utils.h" + +namespace driver { +namespace flight_sql { + +using arrow::Array; +using arrow::RecordBatch; +using arrow::Scalar; +using arrow::Status; +using arrow::flight::FlightEndpoint; +using arrow::flight::FlightStreamChunk; +using arrow::flight::FlightStreamReader; +using odbcabstraction::CDataType; +using odbcabstraction::DriverException; + +FlightStreamChunkIterator::FlightStreamChunkIterator( + FlightSqlClient &flight_sql_client, + const flight::FlightCallOptions &call_options, + const std::shared_ptr &flight_info) + : closed_(false) { + const std::vector &vector = flight_info->endpoints(); + + stream_readers_.reserve(vector.size()); + for (int i = 0; i < vector.size(); ++i) { + auto result = flight_sql_client.DoGet(call_options, vector[0].ticket); + ThrowIfNotOK(result.status()); + stream_readers_.push_back(std::move(result.ValueOrDie())); + } + + stream_readers_it_ = stream_readers_.begin(); +} + +FlightStreamChunkIterator::~FlightStreamChunkIterator() { Close(); } + +bool FlightStreamChunkIterator::GetNext(FlightStreamChunk *chunk) { + chunk->data = nullptr; + while (stream_readers_it_ != stream_readers_.end()) { + ThrowIfNotOK((*stream_readers_it_)->Next(chunk)); + if (chunk->data != nullptr) { + return true; + } + stream_readers_it_++; + } + return false; +} + +void FlightStreamChunkIterator::Close() { + if (closed_) { + return; + } + for (const auto &item : stream_readers_) { + item->Cancel(); + } + closed_ = true; +} + +FlightSqlResultSet::FlightSqlResultSet( + std::shared_ptr metadata, + FlightSqlClient &flight_sql_client, + const arrow::flight::FlightCallOptions &call_options, + const std::shared_ptr &flight_info) + : metadata_(std::move(metadata)), binding_(metadata->GetColumnCount()), + accessors_(metadata->GetColumnCount()), + get_data_offsets_(metadata->GetColumnCount(), 0), current_row_(0), + num_binding_(0), + chunk_iterator_(flight_sql_client, call_options, flight_info) { + current_chunk_.data = nullptr; + + ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema_)); +} + +size_t FlightSqlResultSet::Move(size_t rows) { + // Consider it might be the first call to Move() and current_chunk is not + // populated yet + assert(rows > 0); + if (current_chunk_.data == nullptr) { + if (!chunk_iterator_.GetNext(¤t_chunk_)) { + return 0; + } + } + + // Reset GetData value offsets. + if (num_binding_ != get_data_offsets_.size()) { + std::fill(get_data_offsets_.begin(), get_data_offsets_.end(), 0); + } + + size_t fetched_rows = 0; + while (fetched_rows < rows) { + size_t batch_rows = current_chunk_.data->num_rows(); + size_t rows_to_fetch = + std::min(static_cast(rows - fetched_rows), + static_cast(batch_rows - current_row_)); + + if (rows_to_fetch == 0) { + if (!chunk_iterator_.GetNext(¤t_chunk_)) { + break; + } + current_row_ = 0; + continue; + } + + for (auto it = binding_.begin(); it != binding_.end(); *it++) { + // There can be unbound columns. + ColumnBinding *binding = (*it).get(); + if (binding == nullptr) + continue; + + Accessor *accessor = accessors_[binding->column - 1].get(); + size_t accessor_rows = accessor->GetColumnarData( + this, binding, current_row_, rows_to_fetch, 0); + + if (rows_to_fetch != accessor_rows) { + throw DriverException( + "Expected the same number of rows for all columns"); + } + } + + current_row_ += rows_to_fetch; + fetched_rows += rows_to_fetch; + } + + return fetched_rows; +} + +void FlightSqlResultSet::Close() { + chunk_iterator_.Close(); + current_chunk_.data = nullptr; +} + +bool FlightSqlResultSet::GetData(int column, CDataType target_type, + int precision, int scale, void *buffer, + size_t buffer_length, ssize_t *strlen_buffer) { + ColumnBinding binding(column, target_type, precision, scale, buffer, + buffer_length, strlen_buffer); + + Accessor *accessor = accessors_[column - 1].get(); + if (accessor == nullptr || accessor->GetTargetType() != target_type) { + accessors_[column - 1] = CreateAccessorForColumn(column, target_type); + accessor = accessors_[column - 1].get(); + } + + int64_t *value_offset = &get_data_offsets_[column - 1]; + + // Note: current_row_ is always positioned at the index _after_ the one we are + // on after calling Move(). So if we want to get data from the _last_ row + // fetched, we need to subtract one from the current row. + accessor->GetColumnarData(this, &binding, current_row_ - 1, 1, *value_offset); + + if (strlen_buffer) { + bool has_more = *value_offset + buffer_length <= strlen_buffer[0]; + *value_offset += buffer_length; + return has_more; + } else { + return false; + } +} + +std::shared_ptr +FlightSqlResultSet::GetArrayForColumn(int column) { + std::shared_ptr result = current_chunk_.data->column(column - 1); + return result; +} + +std::shared_ptr FlightSqlResultSet::GetMetadata() { + return metadata_; +} + +void FlightSqlResultSet::BindColumn(int column, CDataType target_type, + int precision, int scale, void *buffer, + size_t buffer_length, + ssize_t *strlen_buffer) { + if (buffer == nullptr) { + if (accessors_[column - 1] != nullptr) { + num_binding_--; + } + binding_[column - 1].reset(); + accessors_[column - 1].reset(); + return; + } + + binding_[column - 1].reset(new ColumnBinding(column, target_type, precision, + scale, buffer, buffer_length, + strlen_buffer)); + if (accessors_[column - 1] == nullptr) { + num_binding_++; + } + accessors_[column - 1] = CreateAccessorForColumn(column, target_type); +} + +std::unique_ptr +FlightSqlResultSet::CreateAccessorForColumn(int column, CDataType target_type) { + const std::shared_ptr &source_type = + schema_->field(column - 1)->type(); + return CreateAccessor(*source_type, target_type); +} + +FlightSqlResultSet::~FlightSqlResultSet() = default; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index cd1012403891f..bbb72549988c3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -15,53 +15,92 @@ // specific language governing permissions and limitations // under the License. -#include -#include - -#include -#include - #pragma once -namespace driver { -namespace odbcabstraction { -class ResultSetMetadata; -} -} // namespace driver +#include +#include +#include +#include +#include namespace driver { namespace flight_sql { -class FlightSqlResultSet : public odbcabstraction::ResultSet { + +using arrow::Array; +using arrow::RecordBatch; +using arrow::Schema; +using arrow::Status; +using arrow::flight::FlightEndpoint; +using arrow::flight::FlightInfo; +using arrow::flight::FlightStreamChunk; +using arrow::flight::FlightStreamReader; +using arrow::flight::sql::FlightSqlClient; +using odbcabstraction::CDataType; +using odbcabstraction::DriverException; +using odbcabstraction::ResultSet; +using odbcabstraction::ResultSetMetadata; + +class Accessor; +struct ColumnBinding; + +class FlightStreamChunkIterator { private: - std::shared_ptr metadata_; + std::vector> stream_readers_; + std::vector>::iterator stream_readers_it_; + bool closed_; public: - explicit FlightSqlResultSet( - std::shared_ptr metadata) - : metadata_(metadata) {} + FlightStreamChunkIterator( + FlightSqlClient &flight_sql_client, + const arrow::flight::FlightCallOptions &call_options, + const std::shared_ptr &flight_info); + + ~FlightStreamChunkIterator(); + + bool GetNext(FlightStreamChunk *chunk); + + void Close(); +}; + +class FlightSqlResultSet : public ResultSet { +private: + std::vector> accessors_; + std::vector get_data_offsets_; + std::vector> binding_; + int num_binding_; + std::shared_ptr metadata_; + + int64_t current_row_; + FlightStreamChunkIterator chunk_iterator_; + FlightStreamChunk current_chunk_; + std::shared_ptr schema_; + + std::unique_ptr CreateAccessorForColumn(int column, + CDataType target_type); public: - virtual ~FlightSqlResultSet() = default; + ~FlightSqlResultSet() override; - virtual std::shared_ptr GetMetadata() { - return metadata_; - }; + FlightSqlResultSet(std::shared_ptr metadata, + FlightSqlClient &flight_sql_client, + const arrow::flight::FlightCallOptions &call_options, + const std::shared_ptr &flight_info); - virtual void Close() {} + void Close() override; - virtual void BindColumn(int column, odbcabstraction::DataType target_type, - int precision, int scale, void *buffer, - size_t buffer_length, size_t *strlen_buffer, - size_t strlen_buffer_len) {} + bool GetData(int column, CDataType target_type, int precision, int scale, + void *buffer, size_t buffer_length, + ssize_t *strlen_buffer) override; - virtual size_t Move(size_t rows) { return 0; } + size_t Move(size_t rows) override; - virtual bool GetData(int column, odbcabstraction::DataType target_type, - int precision, int scale, void *buffer, - size_t buffer_length, size_t *strlen_buffer) { - return false; - }; -}; + std::shared_ptr GetArrayForColumn(int column); + std::shared_ptr GetMetadata() override; + + void BindColumn(int column, CDataType target_type, int precision, int scale, + void *buffer, size_t buffer_length, + ssize_t *strlen_buffer) override; +}; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc new file mode 100644 index 0000000000000..850e92225172e --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -0,0 +1,110 @@ +// 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 "flight_sql_result_set_accessors.h" + +namespace driver { +namespace flight_sql { + +template +inline std::unique_ptr +CreateAccessor(const arrow::DataType &source_type) { +#define ONE_CASE(ARROW_TYPE) \ + case arrow::ARROW_TYPE##Type::type_id: \ + return std::unique_ptr( \ + new FlightSqlAccessor()); + + switch (source_type.id()) { + ONE_CASE(Boolean) + ONE_CASE(UInt8) + ONE_CASE(Int8) + ONE_CASE(UInt16) + ONE_CASE(Int16) + ONE_CASE(UInt32) + ONE_CASE(Int32) + ONE_CASE(UInt64) + ONE_CASE(Int64) + ONE_CASE(HalfFloat) + ONE_CASE(Float) + ONE_CASE(Double) + ONE_CASE(String) + ONE_CASE(Binary) + ONE_CASE(FixedSizeBinary) + ONE_CASE(Date32) + ONE_CASE(Date64) + ONE_CASE(Timestamp) + ONE_CASE(Time32) + ONE_CASE(Time64) + // ONE_CASE(IntervalMonths) + // ONE_CASE(IntervalDayTime) + ONE_CASE(Decimal128) + ONE_CASE(Decimal256) + ONE_CASE(List) + ONE_CASE(Struct) + ONE_CASE(SparseUnion) + ONE_CASE(DenseUnion) + ONE_CASE(Dictionary) + ONE_CASE(Map) + // ONE_CASE(Extension) + ONE_CASE(FixedSizeList) + ONE_CASE(Duration) + ONE_CASE(LargeString) + ONE_CASE(LargeBinary) + ONE_CASE(LargeList) + // ONE_CASE(IntervalMonthDayNano) + // ONE_CASE(MaxId) + default: + break; + } +#undef ONE_CASE + + throw odbcabstraction::DriverException("Unreachable"); +} + +std::unique_ptr +CreateAccessor(const arrow::DataType &source_type, + odbcabstraction::CDataType target_type) { + +#define CASE_FOR_TYPE(TARGET_TYPE) \ + case TARGET_TYPE: \ + return CreateAccessor(source_type); + + // TODO: Maybe use something like BOOST_PP_SEQ_ENUM? Would like not to have + // all types mentioned one by one. + switch (target_type) { + CASE_FOR_TYPE(CDataType_CHAR) + CASE_FOR_TYPE(CDataType_WCHAR) + CASE_FOR_TYPE(CDataType_SSHORT) + CASE_FOR_TYPE(CDataType_USHORT) + CASE_FOR_TYPE(CDataType_SLONG) + CASE_FOR_TYPE(CDataType_ULONG) + CASE_FOR_TYPE(CDataType_FLOAT) + CASE_FOR_TYPE(CDataType_DOUBLE) + CASE_FOR_TYPE(CDataType_BIT) + CASE_FOR_TYPE(CDataType_STINYINT) + CASE_FOR_TYPE(CDataType_UTINYINT) + CASE_FOR_TYPE(CDataType_SBIGINT) + CASE_FOR_TYPE(CDataType_UBIGINT) + CASE_FOR_TYPE(CDataType_BINARY) + } +#undef CASE_FOR_TYPE + + throw odbcabstraction::DriverException("Unreachable"); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h new file mode 100644 index 0000000000000..78ae7276f7023 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h @@ -0,0 +1,32 @@ +// 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. + +#pragma once + +#include "accessors/main.h" + +namespace driver { +namespace flight_sql { + +class FlightSqlResultSet; + +std::unique_ptr +CreateAccessor(const arrow::DataType &source_type, + odbcabstraction::CDataType target_type); + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index bc9fa16c7167a..b4d258acbbde0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -24,6 +24,7 @@ namespace driver { namespace flight_sql { +using namespace odbcabstraction; using arrow::DataType; using arrow::Field; @@ -50,48 +51,48 @@ size_t FlightSqlResultSetMetadata::GetScale(int column_position) { return 0; } -driver::odbcabstraction::DataType -FlightSqlResultSetMetadata::GetDataType(int column_position) { +SqlDataType FlightSqlResultSetMetadata::GetDataType(int column_position) { const std::shared_ptr &field = schema->field(column_position - 1); const std::shared_ptr &type = field->type(); switch (type->id()) { case arrow::Type::BOOL: - return odbcabstraction::BIT; + return SqlDataType_BIT; case arrow::Type::UINT8: case arrow::Type::INT8: - return odbcabstraction::TINYINT; + return SqlDataType_TINYINT; case arrow::Type::UINT16: case arrow::Type::INT16: - return odbcabstraction::SMALLINT; + return SqlDataType_SMALLINT; case arrow::Type::UINT32: case arrow::Type::INT32: - return odbcabstraction::INTEGER; + return SqlDataType_INTEGER; case arrow::Type::UINT64: case arrow::Type::INT64: - return odbcabstraction::BIGINT; + return SqlDataType_BIGINT; case arrow::Type::HALF_FLOAT: case arrow::Type::FLOAT: - return odbcabstraction::FLOAT; + return SqlDataType_FLOAT; case arrow::Type::DOUBLE: - return odbcabstraction::DOUBLE; + return SqlDataType_DOUBLE; case arrow::Type::BINARY: case arrow::Type::FIXED_SIZE_BINARY: case arrow::Type::LARGE_BINARY: - return odbcabstraction::BINARY; + return SqlDataType_BINARY; case arrow::Type::STRING: case arrow::Type::LARGE_STRING: - return odbcabstraction::VARCHAR; + return SqlDataType_VARCHAR; case arrow::Type::DATE32: case arrow::Type::DATE64: + return SqlDataType_TYPE_DATE; case arrow::Type::TIMESTAMP: - return odbcabstraction::DATETIME; + return SqlDataType_TYPE_TIMESTAMP; case arrow::Type::DECIMAL128: case arrow::Type::DECIMAL256: - return odbcabstraction::DECIMAL; + return SqlDataType_DECIMAL; case arrow::Type::TIME32: case arrow::Type::TIME64: - return odbcabstraction::TIME; + return SqlDataType_TYPE_TIME; // TODO: Handle remaining types. case arrow::Type::INTERVAL_MONTHS: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h index e7ffc760bac9c..8ee5d265f529d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h @@ -37,7 +37,7 @@ class FlightSqlResultSetMetadata : public odbcabstraction::ResultSetMetadata { size_t GetScale(int column_position) override; - odbcabstraction::DataType GetDataType(int column_position) override; + odbcabstraction::SqlDataType GetDataType(int column_position) override; odbcabstraction::Nullability IsNullable(int column_position) override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index f2511faad467d..8ff32ffb84ab3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -18,6 +18,7 @@ #include "flight_sql_statement.h" #include "flight_sql_result_set.h" #include "flight_sql_result_set_metadata.h" +#include "utils.h" #include #include @@ -40,12 +41,6 @@ using driver::odbcabstraction::ResultSetMetadata; using driver::odbcabstraction::Statement; namespace { -inline void ThrowIfNotOK(const Status &status) { - if (!status.ok()) { - throw DriverException(status.ToString()); - } -} - std::shared_ptr CreateResultSetMetaData(const std::shared_ptr &flight_info) { std::shared_ptr schema; @@ -99,10 +94,10 @@ bool FlightSqlStatement::ExecutePrepared() { ThrowIfNotOK(result.status()); current_result_set_metadata_ = CreateResultSetMetaData(result.ValueOrDie()); + current_result_set_ = std::make_shared( + current_result_set_metadata_, sql_client_, call_options_, + result.ValueOrDie()); - // TODO: make use of the returned FlightInfo to populate ResultSet. - current_result_set_ = std::shared_ptr( - new FlightSqlResultSet(current_result_set_metadata_)); return true; } @@ -117,10 +112,10 @@ bool FlightSqlStatement::Execute(const std::string &query) { ThrowIfNotOK(result.status()); current_result_set_metadata_ = CreateResultSetMetaData(result.ValueOrDie()); + current_result_set_ = std::make_shared( + current_result_set_metadata_, sql_client_, call_options_, + result.ValueOrDie()); - // TODO: make use of the returned FlightInfo to populate ResultSet. - current_result_set_ = std::shared_ptr( - new FlightSqlResultSet(current_result_set_metadata_)); return true; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 6e5a34ad48ea2..83d1529c3f8a0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -18,6 +18,7 @@ #include #include "flight_sql_connection.h" +#include "flight_sql_result_set.h" #include "flight_sql_result_set_metadata.h" #include "flight_sql_statement.h" @@ -34,9 +35,119 @@ using arrow::flight::sql::FlightSqlClient; using driver::flight_sql::FlightSqlConnection; using driver::flight_sql::FlightSqlDriver; using driver::odbcabstraction::Connection; +using driver::odbcabstraction::ResultSet; using driver::odbcabstraction::ResultSetMetadata; using driver::odbcabstraction::Statement; +void TestBindColumn(const std::shared_ptr &connection) { + const std::shared_ptr &statement = connection->CreateStatement(); + statement->Execute( + "SELECT IncidntNum, Category FROM \"@dremio\".Test LIMIT 10"); + + const std::shared_ptr &result_set = statement->GetResultSet(); + + int batch_size = 100; + int max_strlen = 1000; + + char IncidntNum[batch_size][max_strlen]; + ssize_t IncidntNum_length[batch_size]; + + char Category[batch_size][max_strlen]; + ssize_t Category_length[batch_size]; + + result_set->BindColumn(1, driver::odbcabstraction::CDataType_CHAR, 0, 0, + IncidntNum, max_strlen, IncidntNum_length); + result_set->BindColumn(2, driver::odbcabstraction::CDataType_CHAR, 0, 0, + Category, max_strlen, Category_length); + + size_t total = 0; + while (true) { + size_t fetched_rows = result_set->Move(batch_size); + std::cout << "Fetched " << fetched_rows << " rows." << std::endl; + + total += fetched_rows; + std::cout << "Total:" << total << std::endl; + + for (int i = 0; i < fetched_rows; ++i) { + std::cout << "Row[" << i << "] IncidntNum: '" << IncidntNum[i] + << "', Category: '" << Category[i] << "'" << std::endl; + } + + if (fetched_rows < batch_size) + break; + } +} + +void TestGetData(const std::shared_ptr &connection) { + const std::shared_ptr &statement = connection->CreateStatement(); + statement->Execute( + "SELECT IncidntNum, Category FROM \"@dremio\".Test LIMIT 10"); + + const std::shared_ptr &result_set = statement->GetResultSet(); + + while (result_set->Move(1) == 1) { + int buffer_length = 1024; + char result[buffer_length]; + ssize_t result_length; + result_set->GetData(1, driver::odbcabstraction::CDataType_CHAR, 0, 0, + result, buffer_length, &result_length); + std::cout << result << std::endl; + } +} + +void TestBindColumnBigInt(const std::shared_ptr &connection) { + const std::shared_ptr &statement = connection->CreateStatement(); + statement->Execute( + "SELECT IncidntNum, CAST(\"IncidntNum\" AS DOUBLE) / 100 AS " + "double_field, Category\n" + "FROM (\n" + " SELECT CONVERT_TO_INTEGER(IncidntNum, 1, 1, 0) AS IncidntNum, " + "Category\n" + " FROM (\n" + " SELECT IncidntNum, Category FROM \"@dremio\".Test LIMIT 10\n" + " ) nested_0\n" + ") nested_0"); + + const std::shared_ptr &result_set = statement->GetResultSet(); + + int batch_size = 100; + int max_strlen = 1000; + + char IncidntNum[batch_size][max_strlen]; + ssize_t IncidntNum_length[batch_size]; + + double double_field[batch_size]; + ssize_t double_field_length[batch_size]; + + char Category[batch_size][max_strlen]; + ssize_t Category_length[batch_size]; + + result_set->BindColumn(1, driver::odbcabstraction::CDataType_CHAR, 0, 0, + IncidntNum, max_strlen, IncidntNum_length); + result_set->BindColumn(2, driver::odbcabstraction::CDataType_DOUBLE, 0, 0, + double_field, max_strlen, double_field_length); + result_set->BindColumn(3, driver::odbcabstraction::CDataType_CHAR, 0, 0, + Category, max_strlen, Category_length); + + size_t total = 0; + while (true) { + size_t fetched_rows = result_set->Move(batch_size); + std::cout << "Fetched " << fetched_rows << " rows." << std::endl; + + total += fetched_rows; + std::cout << "Total:" << total << std::endl; + + for (int i = 0; i < fetched_rows; ++i) { + std::cout << "Row[" << i << "] IncidntNum: '" << IncidntNum[i] << "', " + << "double_field: '" << double_field[i] << "', " + << "Category: '" << Category[i] << "'" << std::endl; + } + + if (fetched_rows < batch_size) + break; + } +} + int main() { FlightSqlDriver driver; @@ -46,12 +157,16 @@ int main() { Connection::ConnPropertyMap properties = { {FlightSqlConnection::HOST, std::string("0.0.0.0")}, {FlightSqlConnection::PORT, std::string("32010")}, - {FlightSqlConnection::USER, std::string("user")}, - {FlightSqlConnection::PASSWORD, std::string("password")}, + {FlightSqlConnection::USER, std::string("dremio")}, + {FlightSqlConnection::PASSWORD, std::string("dremio123")}, }; std::vector missing_attr; connection->Connect(properties, missing_attr); + TestBindColumnBigInt(connection); + // TestBindColumn(connection); + // TestGetData(connection); + connection->Close(); return 0; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h new file mode 100644 index 0000000000000..7c74613efc225 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -0,0 +1,33 @@ +// 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. + +#pragma once + +#include +#include + +namespace driver { +namespace flight_sql { + +inline void ThrowIfNotOK(const arrow::Status &status) { + if (!status.ok()) { + throw odbcabstraction::DriverException(status.ToString()); + } +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/columnar_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/columnar_result_set.h deleted file mode 100644 index ff25e686e1860..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/columnar_result_set.h +++ /dev/null @@ -1,177 +0,0 @@ -// 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 - -#pragma once - -namespace driver { -namespace odbcabstraction { - -/// \brief Accessor interface meant to provide a way of populating data of a -/// single column to buffers bound by `ColumnarResultSet::BindColumn`. -class Accessor { -public: - /// \brief Populates next cells - virtual size_t Move(size_t cells) = 0; -}; - -/// \brief Accessor CRTP base class, meant to enable efficient calls to -/// specialized `Move_*` methods for each possible target data type without -/// relying on virtual method calls. -template -class TypedAccessor : public Accessor { - size_t Move(size_t cells) override { - if (TARGET_TYPE == CHAR) { - return Move_CHAR(cells); - } else if (TARGET_TYPE == NUMERIC) { - return Move_NUMERIC(cells); - } else if (TARGET_TYPE == DECIMAL) { - return Move_DECIMAL(cells); - } else if (TARGET_TYPE == INTEGER) { - return Move_INTEGER(cells); - } else if (TARGET_TYPE == SMALLINT) { - return Move_SMALLINT(cells); - } else if (TARGET_TYPE == FLOAT) { - return Move_FLOAT(cells); - } else if (TARGET_TYPE == REAL) { - return Move_REAL(cells); - } else if (TARGET_TYPE == DOUBLE) { - return Move_DOUBLE(cells); - } else if (TARGET_TYPE == DATETIME) { - return Move_DATETIME(cells); - } else if (TARGET_TYPE == VARCHAR) { - return Move_VARCHAR(cells); - } - } - - /// \brief Populates bound buffers with next cells as CHAR values. - size_t Move_CHAR(size_t cells) { - return static_cast(this)->Move_CHAR(cells); - } - - /// \brief Populates bound buffers with next cells as NUMERIC values. - size_t Move_NUMERIC(size_t cells) { - return static_cast(this)->Move_NUMERIC(cells); - } - - /// \brief Populates bound buffers with next cells as DECIMAL values. - size_t Move_DECIMAL(size_t cells) { - return static_cast(this)->Move_DECIMAL(cells); - } - - /// \brief Populates bound buffers with next cells as INTEGER values. - size_t Move_INTEGER(size_t cells) { - return static_cast(this)->Move_INTEGER(cells); - } - - /// \brief Populates bound buffers with next cells as SMALLINT values. - size_t Move_SMALLINT(size_t cells) { - return static_cast(this)->Move_SMALLINT(cells); - } - - /// \brief Populates bound buffers with next cells as FLOAT values. - size_t Move_FLOAT(size_t cells) { - return static_cast(this)->Move_FLOAT(cells); - } - - /// \brief Populates bound buffers with next cells as REAL values. - size_t Move_REAL(size_t cells) { - return static_cast(this)->Move_REAL(cells); - } - - /// \brief Populates bound buffers with next cells as DOUBLE values. - size_t Move_DOUBLE(size_t cells) { - return static_cast(this)->Move_DOUBLE(cells); - } - - /// \brief Populates bound buffers with next cells as DATETIME values. - size_t Move_DATETIME(size_t cells) { - return static_cast(this)->Move_DATETIME(cells); - } - - /// \brief Populates bound buffers with next cells as VARCHAR values. - size_t Move_VARCHAR(size_t cells) { - return static_cast(this)->Move_VARCHAR(cells); - } -}; - -/// \brief ResultSet specialized for retrieving data in columnar format. -/// This requires a AccessorFactory instance for creating specialized column -/// accessors for each column bound by calling `BindColumn`. -class ColumnarResultSet : public ResultSet { -private: - std::shared_ptr metadata_; - std::vector> accessors_; - -protected: - ColumnarResultSet(std::shared_ptr metadata) - : metadata_(std::move(metadata)), accessors_(metadata->GetColumnCount()) { - } - - /// \brief Creates a Accessor for given column and target data type bound to - /// given buffers. - virtual std::unique_ptr - CreateAccessor(int column, DataType target_type, int precision, int scale, - void *buffer, size_t buffer_length, size_t *strlen_buffer, - size_t strlen_buffer_len) = 0; - -public: - std::shared_ptr GetMetadata() override { - return std::move(metadata_); - } - - void BindColumn(int column, DataType target_type, int precision, int scale, - void *buffer, size_t buffer_length, size_t *strlen_buffer, - size_t strlen_buffer_len) override { - if (buffer == nullptr) { - accessors_[column] = nullptr; - return; - } - accessors_[column] = - CreateAccessor(column, target_type, precision, scale, buffer, - buffer_length, strlen_buffer, strlen_buffer_len); - } - - size_t Move(size_t rows) override { - size_t fetched_rows = -1; - for (auto it = accessors_.begin(); it != accessors_.end(); *it++) { - // There can be unbound columns. - if (*it == nullptr) - continue; - - size_t accessor_rows = (*it)->Move(rows); - if (fetched_rows == -1) { - // Stores the number of rows moved on the first bound column, expecting - // that all columns move the same number of rows. - fetched_rows = accessor_rows; - } else if (accessor_rows != fetched_rows) { - throw DriverException( - "Expected the same number of rows for all columns"); - } - } - return fetched_rows; - } -}; - -} // namespace odbcabstraction -} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h index af5983631b74d..f6e722bd84f71 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h @@ -51,10 +51,9 @@ class ResultSet { /// \param buffer_length Target buffer length. /// \param strlen_buffer Buffer that holds the length of each value contained /// on target buffer. - /// \param strlen_buffer_len strlen_buffer's length. - virtual void BindColumn(int column, DataType target_type, int precision, + virtual void BindColumn(int column, CDataType target_type, int precision, int scale, void *buffer, size_t buffer_length, - size_t *strlen_buffer, size_t strlen_buffer_len) = 0; + ssize_t *strlen_buffer) = 0; /// \brief Fetches next rows from ResultSet and load values on buffers /// previously bound with `BindColumn`. @@ -80,9 +79,9 @@ class ResultSet { /// \param strlen_buffer Buffer that holds the length of value being fetched. /// \returns true if there is more data to fetch from the current cell; /// false if the whole value was already fetched. - virtual bool GetData(int column, DataType target_type, int precision, + virtual bool GetData(int column, CDataType target_type, int precision, int scale, void *buffer, size_t buffer_length, - size_t *strlen_buffer) = 0; + ssize_t *strlen_buffer) = 0; }; } // namespace odbcabstraction diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set_metadata.h index 006ff388b6860..fdb104247d58c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set_metadata.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set_metadata.h @@ -53,7 +53,7 @@ class ResultSetMetadata { /// \brief It retrieves the SQL_DATA_TYPE of the column. /// \param column_position[in] the position of the column, starting from 1. /// \return the SQL_DATA_TYPE - virtual DataType GetDataType(int column_position) = 0; + virtual SqlDataType GetDataType(int column_position) = 0; /// \brief It returns a boolean value indicating if the column can have /// null values. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 28f3c037de85e..5e5cbad44d8d2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -23,29 +23,62 @@ namespace odbcabstraction { /// \brief Supported ODBC versions. enum OdbcVersion { V_2, V_3, V_4 }; -// Based on ODBC sql.h definitions. -enum DataType { - UNKNOWN_TYPE = 0, - CHAR = 1, - NUMERIC = 2, - DECIMAL = 3, - INTEGER = 4, - SMALLINT = 5, - FLOAT = 6, - REAL = 7, - DOUBLE = 8, - DATETIME = 9, - DATE = 91, - TIME = 92, - TIMESTAMP = 93, - VARCHAR = 12, - LONGVARCHAR = -1, - BINARY = -2, - VARBINARY = -3, - LONGVARBINARY = -4, - BIGINT = -5, - TINYINT = -6, - BIT = -7, +// Based on ODBC sql.h and sqlext.h definitions. +enum SqlDataType { + SqlDataType_CHAR = 1, + SqlDataType_VARCHAR = 12, + SqlDataType_LONGVARCHAR = (-1), + SqlDataType_WCHAR = (-8), + SqlDataType_WVARCHAR = (-9), + SqlDataType_WLONGVARCHAR = (-10), + SqlDataType_DECIMAL = 3, + SqlDataType_NUMERIC = 2, + SqlDataType_SMALLINT = 5, + SqlDataType_INTEGER = 4, + SqlDataType_REAL = 7, + SqlDataType_FLOAT = 6, + SqlDataType_DOUBLE = 8, + SqlDataType_BIT = (-7), + SqlDataType_TINYINT = (-6), + SqlDataType_BIGINT = (-5), + SqlDataType_BINARY = (-2), + SqlDataType_VARBINARY = (-3), + SqlDataType_LONGVARBINARY = (-4), + SqlDataType_TYPE_DATE = 91, + SqlDataType_TYPE_TIME = 92, + SqlDataType_TYPE_TIMESTAMP = 93, + SqlDataType_INTERVAL_MONTH = (100 + 2), + SqlDataType_INTERVAL_YEAR = (100 + 1), + SqlDataType_INTERVAL_YEAR_TO_MONTH = (100 + 7), + SqlDataType_INTERVAL_DAY = (100 + 3), + SqlDataType_INTERVAL_HOUR = (100 + 4), + SqlDataType_INTERVAL_MINUTE = (100 + 5), + SqlDataType_INTERVAL_SECOND = (100 + 6), + SqlDataType_INTERVAL_DAY_TO_HOUR = (100 + 8), + SqlDataType_INTERVAL_DAY_TO_MINUTE = (100 + 9), + SqlDataType_INTERVAL_DAY_TO_SECOND = (100 + 10), + SqlDataType_INTERVAL_HOUR_TO_MINUTE = (100 + 11), + SqlDataType_INTERVAL_HOUR_TO_SECOND = (100 + 12), + SqlDataType_INTERVAL_MINUTE_TO_SECOND = (100 + 13), + SqlDataType_GUID = (-11), +}; + +// Based on ODBC sql.h and sqlext.h definitions. +enum CDataType { + CDataType_CHAR = 1, + CDataType_WCHAR = -8, + CDataType_SSHORT = (5 + (-20)), + CDataType_USHORT = (5 + (-22)), + CDataType_SLONG = (4 + (-20)), + CDataType_ULONG = (4 + (-22)), + CDataType_FLOAT = 7, + CDataType_DOUBLE = 8, + CDataType_BIT = -7, + CDataType_STINYINT = ((-6) + (-20)), + CDataType_UTINYINT = ((-6) + (-22)), + CDataType_SBIGINT = ((-5) + (-20)), + CDataType_UBIGINT = ((-5) + (-22)), + CDataType_BINARY = (-2), }; enum Nullability { @@ -67,5 +100,7 @@ enum Updatability { UPDATABILITY_READWRITE_UNKNOWN = 2, }; +constexpr int NULL_DATA = -1; + } // namespace odbcabstraction } // namespace driver From 3e4f56e5b1be2cb60ed683efee6e5b20384cb52f Mon Sep 17 00:00:00 2001 From: James Duong Date: Wed, 23 Feb 2022 17:01:54 -0800 Subject: [PATCH 063/183] Remove double-definition of building arrow compute Remove extraneous macro to disable arrow compute when arrow compute is needed. Change-Id: Ia39161ba98d98e702b0b69baa34cceddc61b7e35 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index ae12deb8d7c67..242b5a0714df5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -31,7 +31,6 @@ set(ARROW_CMAKE_ARGS -DARROW_FLIGHT=ON -DARROW_FLIGHT_SQL=ON -DARROW_IPC=ON - -DARROW_COMPUTE=OFF -DARROW_BUILD_SHARED=OFF -DARROW_BUILD_STATIC=ON -DARROW_COMPUTE=ON From 8f5e67e800e1fda36df85ed150f75c509d071353 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 22 Feb 2022 16:08:35 -0300 Subject: [PATCH 064/183] Add Arrow compute to simplify Accessors This enables using Arrow Compute to efficiently cast Arrow arrays and also removes much data conversion work that would be needed otherwise. Change-Id: Ic03c88f3555419307fd3492e989a1154f9c7b471 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 6 +- .../flight_sql/accessors/common.h | 17 +- .../flight_sql/accessors/main.h | 52 ------- .../accessors/primitive_array_accessor.h | 71 ++++----- .../accessors/string_array_accessor.h | 132 +--------------- .../accessors/string_array_accessor_test.cc | 85 ++++++++++ .../flight_sql/accessors/types.h | 43 ++++-- .../flight_sql/flight_sql_result_set.cc | 120 +++++---------- .../flight_sql/flight_sql_result_set.h | 88 +++++++---- .../flight_sql_result_set_accessors.cc | 14 +- .../flight_sql_result_set_accessors.h | 7 +- .../flight_sql_result_set_column.cc | 145 ++++++++++++++++++ .../flight_sql/flight_sql_result_set_column.h | 63 ++++++++ .../flight_sql_stream_chunk_iterator.cc | 68 ++++++++ .../flight_sql_stream_chunk_iterator.h | 51 ++++++ 15 files changed, 601 insertions(+), 361 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 242b5a0714df5..549f1eaa4b8e5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -88,8 +88,11 @@ set(ARROW_ODBC_SPI_SOURCES flight_sql_driver.cc flight_sql_result_set.cc flight_sql_result_set_accessors.cc + flight_sql_result_set_column.cc flight_sql_result_set_metadata.cc - flight_sql_statement.cc) + flight_sql_statement.cc + flight_sql_stream_chunk_iterator.cc +) set(ARROW_ODBC_SPI_THIRDPARTY_LIBS arrow_flight_sql @@ -127,6 +130,7 @@ target_link_libraries(arrow_odbc_spi_impl_cli arrow_odbc_spi_impl) # Unit tests set(ARROW_ODBC_SPI_TEST_SOURCES + accessors/string_array_accessor_test.cc flight_sql_connection_test.cc ) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h index f6937b3650c29..7a74bd82def8a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h @@ -29,16 +29,13 @@ using namespace arrow; using namespace odbcabstraction; template -inline size_t CopyFromArrayValuesToBinding(FlightSqlResultSet *result_set, - ColumnBinding *binding, - int64_t starting_row, size_t cells) { - const std::shared_ptr &array = - result_set->GetArrayForColumn(binding->column) - ->Slice(starting_row, static_cast(cells)); +inline size_t CopyFromArrayValuesToBinding(const std::shared_ptr &array, + ColumnBinding *binding) { auto *typed_array = reinterpret_cast(array.get()); ssize_t element_size = sizeof(typename ARRAY_TYPE::value_type); - for (int64_t i = 0; i < cells; ++i) { + int64_t length = array->length(); + for (int64_t i = 0; i < length; ++i) { if (array->IsNull(i)) { binding->strlen_buffer[i] = NULL_DATA; } else { @@ -47,11 +44,11 @@ inline size_t CopyFromArrayValuesToBinding(FlightSqlResultSet *result_set, } const auto *values = typed_array->raw_values(); - size_t value_length = std::min(static_cast(typed_array->length()), - binding->buffer_length); + size_t value_length = + std::min(static_cast(length), binding->buffer_length); memcpy(binding->buffer, values, element_size * value_length); - return cells; + return length; } inline void MoveToCharBuffer(ColumnBinding *binding, Array *array, int64_t i, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h index 65f9fad3e975e..e7496ff4d2fdd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h @@ -17,57 +17,5 @@ #pragma once -#include "../flight_sql_result_set.h" -#include "types.h" -#include -#include - -namespace driver { -namespace flight_sql { - -using arrow::Array; -using odbcabstraction::CDataType; - -template -class FlightSqlAccessor : public Accessor { -public: - CDataType GetTargetType() override { return TARGET_TYPE; } - - size_t GetColumnarData(FlightSqlResultSet *result_set, ColumnBinding *binding, - int64_t starting_row, size_t cells, - int64_t value_offset) override { - const std::shared_ptr &array = - result_set->GetArrayForColumn(binding->column) - ->Slice(starting_row, cells); - for (int64_t i = 0; i < cells; ++i) { - if (array->IsNull(i)) { - if (binding->strlen_buffer) { - binding->strlen_buffer[i] = odbcabstraction::NULL_DATA; - } else { - // TODO: Report error when data is null bor strlen_buffer is nullptr - } - continue; - } - - MoveSingleCell(binding, reinterpret_cast(array.get()), i, - value_offset); - } - - return cells; - } - -private: - inline void MoveSingleCell(ColumnBinding *binding, ARROW_ARRAY *array, - int64_t i, int64_t value_offset) { - std::stringstream ss; - ss << "Unknown type conversion from " << typeid(ARROW_ARRAY).name() - << " to target C type " << TARGET_TYPE; - throw odbcabstraction::DriverException(ss.str()); - } -}; - -} // namespace flight_sql -} // namespace driver - #include "primitive_array_accessor.h" #include "string_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h index 1e101aca774d7..e47a6fce4077d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h @@ -17,6 +17,7 @@ #pragma once +#include "../flight_sql_result_set.h" #include "common.h" #include "types.h" #include @@ -35,10 +36,9 @@ using namespace odbcabstraction; template <> inline size_t FlightSqlAccessor::GetColumnarData( - FlightSqlResultSet *result_set, ColumnBinding *binding, - int64_t starting_row, size_t cells, int64_t value_offset) { - return CopyFromArrayValuesToBinding(result_set, binding, - starting_row, cells); + const std::shared_ptr &sliced_array, ColumnBinding *binding, + int64_t value_offset) { + return CopyFromArrayValuesToBinding(sliced_array, binding); } template <> @@ -55,10 +55,9 @@ inline void FlightSqlAccessor::MoveSingleCell( template <> inline size_t FlightSqlAccessor::GetColumnarData( - FlightSqlResultSet *result_set, ColumnBinding *binding, - int64_t starting_row, size_t cells, int64_t value_offset) { - return CopyFromArrayValuesToBinding(result_set, binding, - starting_row, cells); + const std::shared_ptr &sliced_array, ColumnBinding *binding, + int64_t value_offset) { + return CopyFromArrayValuesToBinding(sliced_array, binding); } template <> @@ -74,10 +73,9 @@ inline void FlightSqlAccessor::MoveSingleCell( template <> inline size_t FlightSqlAccessor::GetColumnarData( - FlightSqlResultSet *result_set, ColumnBinding *binding, - int64_t starting_row, size_t cells, int64_t value_offset) { - return CopyFromArrayValuesToBinding(result_set, binding, - starting_row, cells); + const std::shared_ptr &sliced_array, ColumnBinding *binding, + int64_t value_offset) { + return CopyFromArrayValuesToBinding(sliced_array, binding); } template <> @@ -93,10 +91,9 @@ inline void FlightSqlAccessor::MoveSingleCell( template <> inline size_t FlightSqlAccessor::GetColumnarData( - FlightSqlResultSet *result_set, ColumnBinding *binding, - int64_t starting_row, size_t cells, int64_t value_offset) { - return CopyFromArrayValuesToBinding(result_set, binding, - starting_row, cells); + const std::shared_ptr &sliced_array, ColumnBinding *binding, + int64_t value_offset) { + return CopyFromArrayValuesToBinding(sliced_array, binding); } template <> @@ -112,10 +109,9 @@ inline void FlightSqlAccessor::MoveSingleCell( template <> inline size_t FlightSqlAccessor::GetColumnarData( - FlightSqlResultSet *result_set, ColumnBinding *binding, - int64_t starting_row, size_t cells, int64_t value_offset) { - return CopyFromArrayValuesToBinding(result_set, binding, - starting_row, cells); + const std::shared_ptr &sliced_array, ColumnBinding *binding, + int64_t value_offset) { + return CopyFromArrayValuesToBinding(sliced_array, binding); } template <> @@ -131,10 +127,9 @@ inline void FlightSqlAccessor::MoveSingleCell( template <> inline size_t FlightSqlAccessor::GetColumnarData( - FlightSqlResultSet *result_set, ColumnBinding *binding, - int64_t starting_row, size_t cells, int64_t value_offset) { - return CopyFromArrayValuesToBinding(result_set, binding, - starting_row, cells); + const std::shared_ptr &sliced_array, ColumnBinding *binding, + int64_t value_offset) { + return CopyFromArrayValuesToBinding(sliced_array, binding); } template <> @@ -150,10 +145,9 @@ inline void FlightSqlAccessor::MoveSingleCell( template <> inline size_t FlightSqlAccessor::GetColumnarData( - FlightSqlResultSet *result_set, ColumnBinding *binding, - int64_t starting_row, size_t cells, int64_t value_offset) { - return CopyFromArrayValuesToBinding(result_set, binding, - starting_row, cells); + const std::shared_ptr &sliced_array, ColumnBinding *binding, + int64_t value_offset) { + return CopyFromArrayValuesToBinding(sliced_array, binding); } template <> @@ -169,10 +163,9 @@ inline void FlightSqlAccessor::MoveSingleCell( template <> inline size_t FlightSqlAccessor::GetColumnarData( - FlightSqlResultSet *result_set, ColumnBinding *binding, - int64_t starting_row, size_t cells, int64_t value_offset) { - return CopyFromArrayValuesToBinding(result_set, binding, - starting_row, cells); + const std::shared_ptr &sliced_array, ColumnBinding *binding, + int64_t value_offset) { + return CopyFromArrayValuesToBinding(sliced_array, binding); } template <> @@ -188,10 +181,9 @@ inline void FlightSqlAccessor::MoveSingleCell( template <> inline size_t FlightSqlAccessor::GetColumnarData( - FlightSqlResultSet *result_set, ColumnBinding *binding, - int64_t starting_row, size_t cells, int64_t value_offset) { - return CopyFromArrayValuesToBinding(result_set, binding, - starting_row, cells); + const std::shared_ptr &sliced_array, ColumnBinding *binding, + int64_t value_offset) { + return CopyFromArrayValuesToBinding(sliced_array, binding); } template <> @@ -207,10 +199,9 @@ inline void FlightSqlAccessor::MoveSingleCell( template <> inline size_t FlightSqlAccessor::GetColumnarData( - FlightSqlResultSet *result_set, ColumnBinding *binding, - int64_t starting_row, size_t cells, int64_t value_offset) { - return CopyFromArrayValuesToBinding(result_set, binding, - starting_row, cells); + const std::shared_ptr &sliced_array, ColumnBinding *binding, + int64_t value_offset) { + return CopyFromArrayValuesToBinding(sliced_array, binding); } template <> diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h index 8d89f349c001a..69e2a8f5bb0eb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h @@ -17,8 +17,10 @@ #pragma once +#include "arrow/type_fwd.h" #include "types.h" #include +#include #include namespace driver { @@ -49,135 +51,5 @@ inline void FlightSqlAccessor::MoveSingleCell( } } -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset) { - char *end; - static_cast(binding->buffer)[i] = - strtoll(array->GetView(i).data(), &end, 10); - if (*end) { - // TODO: Report error - } - - if (binding->strlen_buffer) { - binding->strlen_buffer[i] = sizeof(int64_t); - } -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset) { - char *end; - static_cast(binding->buffer)[i] = - strtoull(array->GetView(i).data(), &end, 10); - if (*end) { - // TODO: Report error - } - - if (binding->strlen_buffer) { - binding->strlen_buffer[i] = sizeof(uint64_t); - } -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset) { - char *end; - static_cast(binding->buffer)[i] = - strtol(array->GetView(i).data(), &end, 10); - if (*end) { - // TODO: Report error - } - - if (binding->strlen_buffer) { - binding->strlen_buffer[i] = sizeof(int32_t); - } -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset) { - char *end; - static_cast(binding->buffer)[i] = - strtoul(array->GetView(i).data(), &end, 10); - if (*end) { - // TODO: Report error - } - - if (binding->strlen_buffer) { - binding->strlen_buffer[i] = sizeof(int32_t); - } -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset) { - char *end; - static_cast(binding->buffer)[i] = - strtol(array->GetView(i).data(), &end, 10); - if (*end) { - // TODO: Report error - } - - if (binding->strlen_buffer) { - binding->strlen_buffer[i] = sizeof(int16_t); - } -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset) { - char *end; - static_cast(binding->buffer)[i] = - strtoul(array->GetView(i).data(), &end, 10); - if (*end) { - // TODO: Report error - } - - if (binding->strlen_buffer) { - binding->strlen_buffer[i] = sizeof(uint16_t); - } -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset) { - char *end; - static_cast(binding->buffer)[i] = - strtol(array->GetView(i).data(), &end, 10); - if (*end) { - // TODO: Report error - } - - if (binding->strlen_buffer) { - binding->strlen_buffer[i] = sizeof(int8_t); - } -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset) { - char *end; - static_cast(binding->buffer)[i] = - strtoul(array->GetView(i).data(), &end, 10); - if (*end) { - // TODO: Report error - } - - if (binding->strlen_buffer) { - binding->strlen_buffer[i] = sizeof(uint8_t); - } -} - -// TODO: Add other data type conversions - } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc new file mode 100644 index 0000000000000..6d8796998d546 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc @@ -0,0 +1,85 @@ +// 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 "arrow/testing/gtest_util.h" +#include "string_array_accessor.h" +#include "gtest/gtest.h" + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +TEST(StringArrayAccessor, Test_CDataType_CHAR_Basic) { + std::vector values = {"foo", "barx", "baz123"}; + std::shared_ptr array; + ArrayFromVector(values, &array); + + FlightSqlAccessor accessor(array.get()); + + size_t max_strlen = 64; + char buffer[values.size() * max_strlen]; + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(1, CDataType_CHAR, 0, 0, buffer, max_strlen, + strlen_buffer); + + ASSERT_EQ(values.size(), + accessor.GetColumnarData(&binding, 0, values.size(), 0)); + + for (int i = 0; i < values.size(); ++i) { + ASSERT_EQ(values[i].length() + 1, strlen_buffer[i]); + ASSERT_EQ(values[i], std::string(buffer + i * max_strlen)); + } +} + +TEST(StringArrayAccessor, Test_CDataType_CHAR_Truncation) { + std::vector values = { + "ABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEF"}; + std::shared_ptr array; + ArrayFromVector(values, &array); + + FlightSqlAccessor accessor(array.get()); + + size_t max_strlen = 8; + char buffer[values.size() * max_strlen]; + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(1, CDataType_CHAR, 0, 0, buffer, max_strlen, + strlen_buffer); + + std::stringstream ss; + int64_t value_offset = 0; + + // Construct the whole string by concatenating smaller chunks from + // GetColumnarData + do { + ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset)); + ASSERT_EQ(values[0].length() + 1, strlen_buffer[0]); + + int64_t chunk_length = std::min(static_cast(max_strlen), + strlen_buffer[0] - 1 - value_offset); + ss << std::string(buffer, buffer + chunk_length); + value_offset += chunk_length; + } while (value_offset < strlen_buffer[0] - 1); + + ASSERT_EQ(values[0], ss.str()); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h index 62876a6c84010..83c8be7f5f368 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h @@ -17,29 +17,35 @@ #pragma once +#include #include #include +#include #include #include namespace driver { namespace flight_sql { +using arrow::Array; using odbcabstraction::CDataType; +class FlightSqlResultSet; + struct ColumnBinding { void *buffer; ssize_t *strlen_buffer; size_t buffer_length; CDataType target_type; - int column; int precision; int scale; - ColumnBinding(int column, CDataType target_type, int precision, int scale, - void *buffer, size_t buffer_length, ssize_t *strlen_buffer) - : column(column), target_type(target_type), precision(precision), - scale(scale), buffer(buffer), buffer_length(buffer_length), + ColumnBinding() = default; + + ColumnBinding(CDataType target_type, int precision, int scale, void *buffer, + size_t buffer_length, ssize_t *strlen_buffer) + : target_type(target_type), precision(precision), scale(scale), + buffer(buffer), buffer_length(buffer_length), strlen_buffer(strlen_buffer) {} }; @@ -47,15 +53,34 @@ struct ColumnBinding { /// single column to buffers bound by `ColumnarResultSet::BindColumn`. class Accessor { public: - virtual ~Accessor() = default; + const CDataType target_type_; - virtual CDataType GetTargetType() = 0; + Accessor(CDataType target_type) : target_type_(target_type) {} + + virtual ~Accessor() = default; /// \brief Populates next cells - virtual size_t GetColumnarData(FlightSqlResultSet *result_set, - ColumnBinding *binding, int64_t starting_row, + virtual size_t GetColumnarData(ColumnBinding *binding, int64_t starting_row, size_t cells, int64_t value_offset) = 0; }; +template +class FlightSqlAccessor : public Accessor { +public: + explicit FlightSqlAccessor(Array *array); + + size_t GetColumnarData(ColumnBinding *binding, int64_t starting_row, + size_t cells, int64_t value_offset) override; + +private: + ARROW_ARRAY *array_; + + size_t GetColumnarData(const std::shared_ptr &sliced_array, + ColumnBinding *binding, int64_t value_offset); + + inline void MoveSingleCell(ColumnBinding *binding, ARROW_ARRAY *array, + int64_t i, int64_t value_offset); +}; + } // namespace flight_sql } // namespace driver \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index 8de76c8e50067..150f1ed091e2a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -22,7 +22,7 @@ #include #include -#include "flight_sql_result_set_accessors.h" +#include "flight_sql_result_set_column.h" #include "flight_sql_result_set_metadata.h" #include "utils.h" @@ -39,59 +39,21 @@ using arrow::flight::FlightStreamReader; using odbcabstraction::CDataType; using odbcabstraction::DriverException; -FlightStreamChunkIterator::FlightStreamChunkIterator( - FlightSqlClient &flight_sql_client, - const flight::FlightCallOptions &call_options, - const std::shared_ptr &flight_info) - : closed_(false) { - const std::vector &vector = flight_info->endpoints(); - - stream_readers_.reserve(vector.size()); - for (int i = 0; i < vector.size(); ++i) { - auto result = flight_sql_client.DoGet(call_options, vector[0].ticket); - ThrowIfNotOK(result.status()); - stream_readers_.push_back(std::move(result.ValueOrDie())); - } - - stream_readers_it_ = stream_readers_.begin(); -} - -FlightStreamChunkIterator::~FlightStreamChunkIterator() { Close(); } - -bool FlightStreamChunkIterator::GetNext(FlightStreamChunk *chunk) { - chunk->data = nullptr; - while (stream_readers_it_ != stream_readers_.end()) { - ThrowIfNotOK((*stream_readers_it_)->Next(chunk)); - if (chunk->data != nullptr) { - return true; - } - stream_readers_it_++; - } - return false; -} - -void FlightStreamChunkIterator::Close() { - if (closed_) { - return; - } - for (const auto &item : stream_readers_) { - item->Cancel(); - } - closed_ = true; -} - FlightSqlResultSet::FlightSqlResultSet( std::shared_ptr metadata, FlightSqlClient &flight_sql_client, const arrow::flight::FlightCallOptions &call_options, const std::shared_ptr &flight_info) - : metadata_(std::move(metadata)), binding_(metadata->GetColumnCount()), - accessors_(metadata->GetColumnCount()), - get_data_offsets_(metadata->GetColumnCount(), 0), current_row_(0), + : metadata_(std::move(metadata)), columns_(metadata->GetColumnCount()), + get_data_offsets_(metadata->GetColumnCount()), current_row_(0), num_binding_(0), chunk_iterator_(flight_sql_client, call_options, flight_info) { current_chunk_.data = nullptr; + for (int i = 0; i < columns_.size(); ++i) { + columns_[i] = FlightSqlResultSetColumn(this, i + 1); + } + ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema_)); } @@ -121,19 +83,22 @@ size_t FlightSqlResultSet::Move(size_t rows) { if (!chunk_iterator_.GetNext(¤t_chunk_)) { break; } + for (auto &column : columns_) { + column.ResetAccessor(); + } current_row_ = 0; continue; } - for (auto it = binding_.begin(); it != binding_.end(); *it++) { + for (auto it = columns_.begin(); it != columns_.end(); *it++) { + auto &column = *it; + // There can be unbound columns. - ColumnBinding *binding = (*it).get(); - if (binding == nullptr) + if (!column.is_bound) continue; - Accessor *accessor = accessors_[binding->column - 1].get(); - size_t accessor_rows = accessor->GetColumnarData( - this, binding, current_row_, rows_to_fetch, 0); + size_t accessor_rows = column.GetAccessorForBinding()->GetColumnarData( + &column.binding, current_row_, rows_to_fetch, 0); if (rows_to_fetch != accessor_rows) { throw DriverException( @@ -141,7 +106,7 @@ size_t FlightSqlResultSet::Move(size_t rows) { } } - current_row_ += rows_to_fetch; + current_row_ += static_cast(rows_to_fetch); fetched_rows += rows_to_fetch; } @@ -153,28 +118,25 @@ void FlightSqlResultSet::Close() { current_chunk_.data = nullptr; } -bool FlightSqlResultSet::GetData(int column, CDataType target_type, +bool FlightSqlResultSet::GetData(int column_n, CDataType target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) { - ColumnBinding binding(column, target_type, precision, scale, buffer, - buffer_length, strlen_buffer); + ColumnBinding binding(target_type, precision, scale, buffer, buffer_length, + strlen_buffer); - Accessor *accessor = accessors_[column - 1].get(); - if (accessor == nullptr || accessor->GetTargetType() != target_type) { - accessors_[column - 1] = CreateAccessorForColumn(column, target_type); - accessor = accessors_[column - 1].get(); - } + auto &column = columns_[column_n - 1]; + Accessor *accessor = column.GetAccessorForGetData(target_type); - int64_t *value_offset = &get_data_offsets_[column - 1]; + int64_t &value_offset = get_data_offsets_[column_n - 1]; // Note: current_row_ is always positioned at the index _after_ the one we are // on after calling Move(). So if we want to get data from the _last_ row // fetched, we need to subtract one from the current row. - accessor->GetColumnarData(this, &binding, current_row_ - 1, 1, *value_offset); + accessor->GetColumnarData(&binding, current_row_ - 1, 1, value_offset); if (strlen_buffer) { - bool has_more = *value_offset + buffer_length <= strlen_buffer[0]; - *value_offset += buffer_length; + bool has_more = value_offset + buffer_length <= strlen_buffer[0]; + value_offset += static_cast(buffer_length); return has_more; } else { return false; @@ -183,44 +145,38 @@ bool FlightSqlResultSet::GetData(int column, CDataType target_type, std::shared_ptr FlightSqlResultSet::GetArrayForColumn(int column) { - std::shared_ptr result = current_chunk_.data->column(column - 1); - return result; + std::shared_ptr original_array = + current_chunk_.data->column(column - 1); + + return original_array; } std::shared_ptr FlightSqlResultSet::GetMetadata() { return metadata_; } -void FlightSqlResultSet::BindColumn(int column, CDataType target_type, +void FlightSqlResultSet::BindColumn(int column_n, CDataType target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) { + auto &column = columns_[column_n - 1]; if (buffer == nullptr) { - if (accessors_[column - 1] != nullptr) { + if (column.is_bound) { num_binding_--; } - binding_[column - 1].reset(); - accessors_[column - 1].reset(); + column.ResetBinding(); return; } - binding_[column - 1].reset(new ColumnBinding(column, target_type, precision, - scale, buffer, buffer_length, - strlen_buffer)); - if (accessors_[column - 1] == nullptr) { + if (!column.is_bound) { num_binding_++; } - accessors_[column - 1] = CreateAccessorForColumn(column, target_type); -} -std::unique_ptr -FlightSqlResultSet::CreateAccessorForColumn(int column, CDataType target_type) { - const std::shared_ptr &source_type = - schema_->field(column - 1)->type(); - return CreateAccessor(*source_type, target_type); + ColumnBinding binding(target_type, precision, scale, buffer, buffer_length, + strlen_buffer); + column.SetBinding(binding); } FlightSqlResultSet::~FlightSqlResultSet() = default; - } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index bbb72549988c3..ab1ab9a8e615b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -17,9 +17,15 @@ #pragma once +#include "flight_sql_result_set_accessors.h" +#include "flight_sql_stream_chunk_iterator.h" +#include "utils.h" +#include #include +#include #include #include +#include #include #include @@ -40,33 +46,13 @@ using odbcabstraction::DriverException; using odbcabstraction::ResultSet; using odbcabstraction::ResultSetMetadata; -class Accessor; -struct ColumnBinding; - -class FlightStreamChunkIterator { -private: - std::vector> stream_readers_; - std::vector>::iterator stream_readers_it_; - bool closed_; - -public: - FlightStreamChunkIterator( - FlightSqlClient &flight_sql_client, - const arrow::flight::FlightCallOptions &call_options, - const std::shared_ptr &flight_info); - - ~FlightStreamChunkIterator(); - - bool GetNext(FlightStreamChunk *chunk); - - void Close(); -}; +class FlightSqlResultSetColumn; class FlightSqlResultSet : public ResultSet { private: - std::vector> accessors_; + std::vector columns_; std::vector get_data_offsets_; - std::vector> binding_; + int num_binding_; std::shared_ptr metadata_; @@ -75,9 +61,6 @@ class FlightSqlResultSet : public ResultSet { FlightStreamChunk current_chunk_; std::shared_ptr schema_; - std::unique_ptr CreateAccessorForColumn(int column, - CDataType target_type); - public: ~FlightSqlResultSet() override; @@ -88,7 +71,7 @@ class FlightSqlResultSet : public ResultSet { void Close() override; - bool GetData(int column, CDataType target_type, int precision, int scale, + bool GetData(int column_n, CDataType target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) override; @@ -98,9 +81,58 @@ class FlightSqlResultSet : public ResultSet { std::shared_ptr GetMetadata() override; - void BindColumn(int column, CDataType target_type, int precision, int scale, + void BindColumn(int column_n, CDataType target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) override; }; + +template +FlightSqlAccessor::FlightSqlAccessor(Array *array) + : Accessor(TARGET_TYPE), + array_(arrow::internal::checked_cast(array)) {} + +template +size_t FlightSqlAccessor::GetColumnarData( + const std::shared_ptr &sliced_array, ColumnBinding *binding, + int64_t value_offset) { + int64_t length = sliced_array->length(); + for (int64_t i = 0; i < length; ++i) { + if (sliced_array->IsNull(i)) { + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = odbcabstraction::NULL_DATA; + } else { + // TODO: Report error when data is null bor strlen_buffer is nullptr + } + continue; + } + + MoveSingleCell(binding, sliced_array.get(), i, value_offset); + } + + return length; +} + +template +size_t FlightSqlAccessor::GetColumnarData( + ColumnBinding *binding, int64_t starting_row, size_t cells, + int64_t value_offset) { + const std::shared_ptr &array = + array_->Slice(starting_row, static_cast(cells)); + + return GetColumnarData( + arrow::internal::checked_pointer_cast(array), binding, + value_offset); +} + +template +void FlightSqlAccessor::MoveSingleCell( + ColumnBinding *binding, ARROW_ARRAY *array, int64_t i, + int64_t value_offset) { + std::stringstream ss; + ss << "Unknown type conversion from " << typeid(ARROW_ARRAY).name() + << " to target C type " << TARGET_TYPE; + throw odbcabstraction::DriverException(ss.str()); +} + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index 850e92225172e..32d14240671d2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -15,20 +15,20 @@ // specific language governing permissions and limitations // under the License. -#include "flight_sql_result_set_accessors.h" +#include "accessors/main.h" namespace driver { namespace flight_sql { template -inline std::unique_ptr -CreateAccessor(const arrow::DataType &source_type) { +inline std::unique_ptr CreateAccessor(arrow::Array *source_array) { #define ONE_CASE(ARROW_TYPE) \ case arrow::ARROW_TYPE##Type::type_id: \ return std::unique_ptr( \ - new FlightSqlAccessor()); + new FlightSqlAccessor( \ + source_array)); - switch (source_type.id()) { + switch (source_array->type_id()) { ONE_CASE(Boolean) ONE_CASE(UInt8) ONE_CASE(Int8) @@ -76,12 +76,12 @@ CreateAccessor(const arrow::DataType &source_type) { } std::unique_ptr -CreateAccessor(const arrow::DataType &source_type, +CreateAccessor(arrow::Array *source_array, odbcabstraction::CDataType target_type) { #define CASE_FOR_TYPE(TARGET_TYPE) \ case TARGET_TYPE: \ - return CreateAccessor(source_type); + return CreateAccessor(source_array); // TODO: Maybe use something like BOOST_PP_SEQ_ENUM? Would like not to have // all types mentioned one by one. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h index 78ae7276f7023..bcb788436618a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h @@ -17,15 +17,18 @@ #pragma once -#include "accessors/main.h" +#include "arrow/type_fwd.h" +#include +#include namespace driver { namespace flight_sql { +class Accessor; class FlightSqlResultSet; std::unique_ptr -CreateAccessor(const arrow::DataType &source_type, +CreateAccessor(arrow::Array *source_array, odbcabstraction::CDataType target_type); } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc new file mode 100644 index 0000000000000..01327dd1a8daa --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -0,0 +1,145 @@ +// 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 "flight_sql_result_set_column.h" +#include "flight_sql_result_set.h" +#include +#include +#include +#include + +namespace driver { +namespace flight_sql { + +namespace { +std::shared_ptr +ConvertCToArrowDataType(odbcabstraction::CDataType data_type) { + switch (data_type) { + case odbcabstraction::CDataType_CHAR: + case odbcabstraction::CDataType_WCHAR: + return arrow::utf8(); + case odbcabstraction::CDataType_SSHORT: + return arrow::int16(); + case odbcabstraction::CDataType_USHORT: + return arrow::uint16(); + case odbcabstraction::CDataType_SLONG: + return arrow::int32(); + case odbcabstraction::CDataType_ULONG: + return arrow::uint32(); + case odbcabstraction::CDataType_FLOAT: + return arrow::float32(); + case odbcabstraction::CDataType_DOUBLE: + return arrow::float64(); + case odbcabstraction::CDataType_BIT: + return arrow::boolean(); + case odbcabstraction::CDataType_STINYINT: + return arrow::int8(); + case odbcabstraction::CDataType_UTINYINT: + return arrow::uint8(); + case odbcabstraction::CDataType_SBIGINT: + return arrow::int64(); + case odbcabstraction::CDataType_UBIGINT: + return arrow::uint64(); + case odbcabstraction::CDataType_BINARY: + return arrow::binary(); + } +} + +std::shared_ptr +CastArray(const std::shared_ptr &original_array, + CDataType target_type) { + const std::shared_ptr &target_arrow_type = + ConvertCToArrowDataType(target_type); + if (original_array->type()->Equals(target_arrow_type)) { + // Avoid casting if target type is the same as original + return original_array; + } + + arrow::compute::CastOptions cast_options; + cast_options.to_type = target_arrow_type; + + const arrow::Result &result = + arrow::compute::CallFunction("cast", {original_array}, &cast_options); + ThrowIfNotOK(result.status()); + arrow::Datum datum = result.ValueOrDie(); + return std::move(datum).make_array(); +} + +} // namespace + +std::unique_ptr +FlightSqlResultSetColumn::CreateAccessor(CDataType target_type) { + const std::shared_ptr &original_array = + result_set_->GetArrayForColumn(column_n_); + cached_original_array_ = original_array.get(); + cached_casted_array_ = CastArray(original_array, target_type); + + return flight_sql::CreateAccessor(cached_casted_array_.get(), target_type); +} + +Accessor * +FlightSqlResultSetColumn::GetAccessorForTargetType(CDataType target_type) { + const std::shared_ptr &original_array = + result_set_->GetArrayForColumn(column_n_); + + // TODO: Figure out if that's the best way of caching + if (cached_accessor_ && original_array.get() == cached_original_array_ && + cached_accessor_->target_type_ == target_type) { + return cached_accessor_.get(); + } + + cached_accessor_ = CreateAccessor(target_type); + return cached_accessor_.get(); +} + +FlightSqlResultSetColumn::FlightSqlResultSetColumn() + : FlightSqlResultSetColumn(nullptr, 0) {} + +FlightSqlResultSetColumn::FlightSqlResultSetColumn( + FlightSqlResultSet *result_set, int column_n) + : result_set_(result_set), column_n_(column_n), + cached_original_array_(nullptr), is_bound(false) {} + +Accessor *FlightSqlResultSetColumn::GetAccessorForBinding() { + return GetAccessorForTargetType(binding.target_type); +} + +Accessor * +FlightSqlResultSetColumn::GetAccessorForGetData(CDataType target_type) { + return GetAccessorForTargetType(target_type); +} + +void FlightSqlResultSetColumn::SetBinding(ColumnBinding new_binding) { + binding = new_binding; + is_bound = true; + + ResetAccessor(); +} + +void FlightSqlResultSetColumn::ResetBinding() { + is_bound = false; + ResetAccessor(); +} + +void FlightSqlResultSetColumn::ResetAccessor() { + if (is_bound) { + cached_accessor_.reset(); + } +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h new file mode 100644 index 0000000000000..03b814fbaf9ba --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h @@ -0,0 +1,63 @@ +// 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. + +#pragma once + +#include +#include + +namespace driver { +namespace flight_sql { + +using arrow::Array; + +class FlightSqlResultSet; + +class FlightSqlResultSetColumn { +private: + FlightSqlResultSet *result_set_; + int column_n_; + + // TODO: Figure out if that's the best way of caching + Array *cached_original_array_; + std::shared_ptr cached_casted_array_; + std::unique_ptr cached_accessor_; + + std::unique_ptr CreateAccessor(CDataType target_type); + + Accessor *GetAccessorForTargetType(CDataType target_type); + +public: + FlightSqlResultSetColumn(); + + FlightSqlResultSetColumn(FlightSqlResultSet *result_set, int column_n); + + ColumnBinding binding; + bool is_bound; + + Accessor *GetAccessorForBinding(); + + Accessor *GetAccessorForGetData(CDataType target_type); + + void SetBinding(ColumnBinding new_binding); + + void ResetBinding(); + + void ResetAccessor(); +}; +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc new file mode 100644 index 0000000000000..b5d1ee0e22f2e --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc @@ -0,0 +1,68 @@ +// 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 "flight_sql_stream_chunk_iterator.h" +#include "utils.h" + +namespace driver { +namespace flight_sql { + +using arrow::flight::FlightEndpoint; + +FlightStreamChunkIterator::FlightStreamChunkIterator( + FlightSqlClient &flight_sql_client, + const arrow::flight::FlightCallOptions &call_options, + const std::shared_ptr &flight_info) + : closed_(false) { + const std::vector &vector = flight_info->endpoints(); + + stream_readers_.reserve(vector.size()); + for (int i = 0; i < vector.size(); ++i) { + auto result = flight_sql_client.DoGet(call_options, vector[0].ticket); + ThrowIfNotOK(result.status()); + stream_readers_.push_back(std::move(result.ValueOrDie())); + } + + stream_readers_it_ = stream_readers_.begin(); +} + +FlightStreamChunkIterator::~FlightStreamChunkIterator() { Close(); } + +bool FlightStreamChunkIterator::GetNext(FlightStreamChunk *chunk) { + chunk->data = nullptr; + while (stream_readers_it_ != stream_readers_.end()) { + ThrowIfNotOK((*stream_readers_it_)->Next(chunk)); + if (chunk->data != nullptr) { + return true; + } + stream_readers_it_++; + } + return false; +} + +void FlightStreamChunkIterator::Close() { + if (closed_) { + return; + } + for (const auto &item : stream_readers_) { + item->Cancel(); + } + closed_ = true; +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.h new file mode 100644 index 0000000000000..ba1c8b42cc5a3 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.h @@ -0,0 +1,51 @@ +// 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. + +#pragma once + +#include +#include + +namespace driver { +namespace flight_sql { + +using arrow::flight::FlightInfo; +using arrow::flight::FlightStreamChunk; +using arrow::flight::FlightStreamReader; +using arrow::flight::sql::FlightSqlClient; + +class FlightStreamChunkIterator { +private: + std::vector> stream_readers_; + std::vector>::iterator stream_readers_it_; + bool closed_; + +public: + FlightStreamChunkIterator( + FlightSqlClient &flight_sql_client, + const arrow::flight::FlightCallOptions &call_options, + const std::shared_ptr &flight_info); + + ~FlightStreamChunkIterator(); + + bool GetNext(FlightStreamChunk *chunk); + + void Close(); +}; + +} // namespace flight_sql +} // namespace driver From 55f5d58b7ae39b9afbc5ff3ff7a2887a553ea45e Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Thu, 24 Feb 2022 17:28:18 -0300 Subject: [PATCH 065/183] Implement CHAR/WCHAR convertions for StringArray Change-Id: I8194fd2acf7ff246b6a8c032a39867c0016f34a0 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 6 +- .../accessors/primitive_array_accessor.cc | 63 ++++++ .../accessors/primitive_array_accessor.h | 191 +----------------- .../accessors/string_array_accessor.cc | 105 ++++++++++ .../accessors/string_array_accessor.h | 48 ++--- .../accessors/string_array_accessor_test.cc | 79 +++++++- .../flight_sql/accessors/types.h | 58 +++++- .../flight_sql/flight_sql_result_set.h | 48 ----- .../flight_sql_result_set_accessors.cc | 158 +++++++-------- 9 files changed, 408 insertions(+), 348 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 549f1eaa4b8e5..948fdacf5c421 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -83,6 +83,8 @@ find_package(gRPC 1.36 CONFIG REQUIRED) enable_testing() set(ARROW_ODBC_SPI_SOURCES + accessors/primitive_array_accessor.cc + accessors/string_array_accessor.cc flight_sql_auth_method.cc flight_sql_connection.cc flight_sql_driver.cc @@ -140,5 +142,7 @@ set_target_properties(arrow_odbc_spi_impl_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test/$/bin ) -target_link_libraries(arrow_odbc_spi_impl_test arrow_odbc_spi_impl gtest gtest_main) +target_link_libraries(arrow_odbc_spi_impl_test + arrow_odbc_spi_impl + gtest gtest_main) add_test(connection_test arrow_odbc_spi_impl_test) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc new file mode 100644 index 0000000000000..d932757461c37 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc @@ -0,0 +1,63 @@ +// 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 "primitive_array_accessor.h" + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +template +PrimitiveArrayFlightSqlAccessor< + ARROW_ARRAY, TARGET_TYPE>::PrimitiveArrayFlightSqlAccessor(Array *array) + : FlightSqlAccessor< + ARROW_ARRAY, TARGET_TYPE, + PrimitiveArrayFlightSqlAccessor>(array) {} + +template +size_t +PrimitiveArrayFlightSqlAccessor::GetColumnarData_impl( + const std::shared_ptr &sliced_array, ColumnBinding *binding, + int64_t value_offset) { + return CopyFromArrayValuesToBinding(sliced_array, binding); +} + +template class PrimitiveArrayFlightSqlAccessor< + Int64Array, odbcabstraction::CDataType_SBIGINT>; +template class PrimitiveArrayFlightSqlAccessor< + Int32Array, odbcabstraction::CDataType_SLONG>; +template class PrimitiveArrayFlightSqlAccessor< + Int16Array, odbcabstraction::CDataType_SSHORT>; +template class PrimitiveArrayFlightSqlAccessor< + Int8Array, odbcabstraction::CDataType_STINYINT>; +template class PrimitiveArrayFlightSqlAccessor< + UInt64Array, odbcabstraction::CDataType_UBIGINT>; +template class PrimitiveArrayFlightSqlAccessor< + UInt32Array, odbcabstraction::CDataType_ULONG>; +template class PrimitiveArrayFlightSqlAccessor< + UInt16Array, odbcabstraction::CDataType_USHORT>; +template class PrimitiveArrayFlightSqlAccessor< + UInt8Array, odbcabstraction::CDataType_UTINYINT>; +template class PrimitiveArrayFlightSqlAccessor< + DoubleArray, odbcabstraction::CDataType_DOUBLE>; +template class PrimitiveArrayFlightSqlAccessor< + FloatArray, odbcabstraction::CDataType_FLOAT>; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h index e47a6fce4077d..30f7f2544736a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h @@ -30,186 +30,17 @@ namespace flight_sql { using namespace arrow; using namespace odbcabstraction; -/* - * Int64Array - */ - -template <> -inline size_t FlightSqlAccessor::GetColumnarData( - const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset) { - return CopyFromArrayValuesToBinding(sliced_array, binding); -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, Int64Array *array, int64_t i, - int64_t value_offset) { - MoveToCharBuffer(binding, array, i, value_offset); -} - -/* - * UInt64Array - */ - -template <> -inline size_t -FlightSqlAccessor::GetColumnarData( - const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset) { - return CopyFromArrayValuesToBinding(sliced_array, binding); -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, UInt64Array *array, int64_t i, - int64_t value_offset) { - MoveToCharBuffer(binding, array, i, value_offset); -} - -/* - * Int32Array - */ - -template <> -inline size_t FlightSqlAccessor::GetColumnarData( - const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset) { - return CopyFromArrayValuesToBinding(sliced_array, binding); -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, Int32Array *array, int64_t i, - int64_t value_offset) { - MoveToCharBuffer(binding, array, i, value_offset); -} - -/* - * UInt32Array - */ - -template <> -inline size_t FlightSqlAccessor::GetColumnarData( - const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset) { - return CopyFromArrayValuesToBinding(sliced_array, binding); -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, UInt32Array *array, int64_t i, - int64_t value_offset) { - MoveToCharBuffer(binding, array, i, value_offset); -} - -/* - * Int16Array - */ - -template <> -inline size_t FlightSqlAccessor::GetColumnarData( - const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset) { - return CopyFromArrayValuesToBinding(sliced_array, binding); -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, Int16Array *array, int64_t i, - int64_t value_offset) { - MoveToCharBuffer(binding, array, i, value_offset); -} - -/* - * UInt16Array - */ - -template <> -inline size_t FlightSqlAccessor::GetColumnarData( - const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset) { - return CopyFromArrayValuesToBinding(sliced_array, binding); -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, UInt16Array *array, int64_t i, - int64_t value_offset) { - MoveToCharBuffer(binding, array, i, value_offset); -} - -/* - * Int8Array - */ - -template <> -inline size_t FlightSqlAccessor::GetColumnarData( - const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset) { - return CopyFromArrayValuesToBinding(sliced_array, binding); -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, Int8Array *array, int64_t i, int64_t value_offset) { - MoveToCharBuffer(binding, array, i, value_offset); -} - -/* - * UInt8Array - */ - -template <> -inline size_t -FlightSqlAccessor::GetColumnarData( - const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset) { - return CopyFromArrayValuesToBinding(sliced_array, binding); -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, UInt8Array *array, int64_t i, - int64_t value_offset) { - MoveToCharBuffer(binding, array, i, value_offset); -} - -/* - * FloatArray - */ - -template <> -inline size_t FlightSqlAccessor::GetColumnarData( - const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset) { - return CopyFromArrayValuesToBinding(sliced_array, binding); -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, FloatArray *array, int64_t i, - int64_t value_offset) { - MoveToCharBuffer(binding, array, i, value_offset); -} - -/* - * DoubleArray - */ - -template <> -inline size_t FlightSqlAccessor::GetColumnarData( - const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset) { - return CopyFromArrayValuesToBinding(sliced_array, binding); -} - -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, DoubleArray *array, int64_t i, - int64_t value_offset) { - MoveToCharBuffer(binding, array, i, value_offset); -} +template +class PrimitiveArrayFlightSqlAccessor + : public FlightSqlAccessor< + ARROW_ARRAY, TARGET_TYPE, + PrimitiveArrayFlightSqlAccessor> { +public: + explicit PrimitiveArrayFlightSqlAccessor(Array *array); + + size_t GetColumnarData_impl(const std::shared_ptr &sliced_array, + ColumnBinding *binding, int64_t value_offset); +}; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc new file mode 100644 index 0000000000000..ed8a2627fcc02 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -0,0 +1,105 @@ +// 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 "string_array_accessor.h" + +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +namespace { + +template +inline void MoveSingleCellToCharBuffer(CharToWStrConverter *converter, + ColumnBinding *binding, + StringArray *array, int64_t i, + int64_t value_offset) { + + const char *raw_value = array->Value(i).data(); + const void *value; + size_t size_in_bytes; + SqlWString wstr; + if (sizeof(CHAR_TYPE) > sizeof(char)) { + wstr = converter->from_bytes(raw_value, raw_value + array->value_length(i)); + value = wstr.data(); + size_in_bytes = wstr.size() * sizeof(CHAR_TYPE); + } else { + value = raw_value; + size_in_bytes = array->value_length(i); + } + + // TODO: Handle truncation + size_t value_length = + std::min(static_cast(size_in_bytes - value_offset), + binding->buffer_length); + + auto *byte_buffer = + static_cast(binding->buffer) + i * binding->buffer_length; + auto *char_buffer = (CHAR_TYPE *)byte_buffer; + memcpy(char_buffer, ((char *)value) + value_offset, value_length); + + // Write a NUL terminator + if (binding->buffer_length > size_in_bytes + sizeof(CHAR_TYPE)) { + char_buffer[size_in_bytes / sizeof(CHAR_TYPE)] = '\0'; + } else { + size_t chars_written = binding->buffer_length / sizeof(CHAR_TYPE); + // If we failed to even write one char, the buffer is too small to hold a + // NUL-terminator. + if (chars_written > 0) { + char_buffer[(chars_written - 1)] = '\0'; + } + } + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = static_cast(size_in_bytes); + } +} + +} // namespace + +template +StringArrayFlightSqlAccessor::StringArrayFlightSqlAccessor( + Array *array) + : FlightSqlAccessor>(array), + converter_() {} + +template <> +void StringArrayFlightSqlAccessor::MoveSingleCell_impl( + ColumnBinding *binding, StringArray *array, int64_t i, + int64_t value_offset) { + MoveSingleCellToCharBuffer(&converter_, binding, array, i, + value_offset); +} + +template <> +void StringArrayFlightSqlAccessor::MoveSingleCell_impl( + ColumnBinding *binding, StringArray *array, int64_t i, + int64_t value_offset) { + MoveSingleCellToCharBuffer(&converter_, binding, array, i, + value_offset); +} + +template class StringArrayFlightSqlAccessor; +template class StringArrayFlightSqlAccessor; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h index 69e2a8f5bb0eb..fdc2c710a7409 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h @@ -19,37 +19,39 @@ #include "arrow/type_fwd.h" #include "types.h" -#include -#include +#include +#include #include +#ifdef WITH_IODBC +typedef char32_t SqlWChar; +typedef std::u32string SqlWString; +#else +typedef char16_t SqlWChar; +typedef std::u16string SqlWString; +#endif +typedef std::wstring_convert, SqlWChar> + CharToWStrConverter; + namespace driver { namespace flight_sql { using namespace arrow; using namespace odbcabstraction; -template <> -inline void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset) { - // TODO: Handle truncation - size_t value_length = - std::min(static_cast(array->value_length(i) - value_offset), - binding->buffer_length); - const char *value = array->Value(i).data(); - - char *char_buffer = static_cast(binding->buffer); - memcpy(&char_buffer[i * binding->buffer_length], value + value_offset, - value_length); - if (value_length + 1 < binding->buffer_length) { - char_buffer[i * binding->buffer_length + value_length] = '\0'; - } - - if (binding->strlen_buffer) { - binding->strlen_buffer[i] = array->value_length(i) + 1; - } -} +template +class StringArrayFlightSqlAccessor + : public FlightSqlAccessor> { +public: + explicit StringArrayFlightSqlAccessor(Array *array); + + void MoveSingleCell_impl(ColumnBinding *binding, StringArray *array, + int64_t i, int64_t value_offset); + +private: + CharToWStrConverter converter_; +}; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc index 6d8796998d546..88205f0a19dc5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc @@ -30,20 +30,20 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Basic) { std::shared_ptr array; ArrayFromVector(values, &array); - FlightSqlAccessor accessor(array.get()); + StringArrayFlightSqlAccessor accessor(array.get()); size_t max_strlen = 64; char buffer[values.size() * max_strlen]; ssize_t strlen_buffer[values.size()]; - ColumnBinding binding(1, CDataType_CHAR, 0, 0, buffer, max_strlen, + ColumnBinding binding(CDataType_CHAR, 0, 0, buffer, max_strlen, strlen_buffer); ASSERT_EQ(values.size(), accessor.GetColumnarData(&binding, 0, values.size(), 0)); for (int i = 0; i < values.size(); ++i) { - ASSERT_EQ(values[i].length() + 1, strlen_buffer[i]); + ASSERT_EQ(values[i].length(), strlen_buffer[i]); ASSERT_EQ(values[i], std::string(buffer + i * max_strlen)); } } @@ -54,13 +54,13 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Truncation) { std::shared_ptr array; ArrayFromVector(values, &array); - FlightSqlAccessor accessor(array.get()); + StringArrayFlightSqlAccessor accessor(array.get()); size_t max_strlen = 8; char buffer[values.size() * max_strlen]; ssize_t strlen_buffer[values.size()]; - ColumnBinding binding(1, CDataType_CHAR, 0, 0, buffer, max_strlen, + ColumnBinding binding(CDataType_CHAR, 0, 0, buffer, max_strlen, strlen_buffer); std::stringstream ss; @@ -70,16 +70,77 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Truncation) { // GetColumnarData do { ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset)); - ASSERT_EQ(values[0].length() + 1, strlen_buffer[0]); + ASSERT_EQ(values[0].length(), strlen_buffer[0]); int64_t chunk_length = std::min(static_cast(max_strlen), - strlen_buffer[0] - 1 - value_offset); - ss << std::string(buffer, buffer + chunk_length); - value_offset += chunk_length; + strlen_buffer[0] - value_offset); + ss << buffer; + value_offset += chunk_length - 1; } while (value_offset < strlen_buffer[0] - 1); ASSERT_EQ(values[0], ss.str()); } +TEST(StringArrayAccessor, Test_CDataType_WCHAR_Basic) { + std::vector values = {"foo", "barx", "baz123"}; + std::shared_ptr array; + ArrayFromVector(values, &array); + + StringArrayFlightSqlAccessor accessor(array.get()); + + size_t max_strlen = 64; + SqlWChar buffer[values.size() * max_strlen]; + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(CDataType_WCHAR, 0, 0, buffer, max_strlen, + strlen_buffer); + + ASSERT_EQ(values.size(), + accessor.GetColumnarData(&binding, 0, values.size(), 0)); + + for (int i = 0; i < values.size(); ++i) { + ASSERT_EQ(values[i].length() * sizeof(SqlWChar), strlen_buffer[i]); + auto expected = CharToWStrConverter().from_bytes(values[i].c_str()); + auto actual = SqlWString(buffer + i * max_strlen / sizeof(SqlWChar)); + ASSERT_EQ(0, expected.compare(actual)); + } +} + +TEST(StringArrayAccessor, Test_CDataType_WCHAR_Truncation) { + std::vector values = { + "ABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEF"}; + std::shared_ptr array; + ArrayFromVector(values, &array); + + StringArrayFlightSqlAccessor accessor(array.get()); + + size_t max_strlen = 8; + SqlWChar buffer[values.size() * max_strlen]; + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(CDataType_WCHAR, 0, 0, buffer, + max_strlen * sizeof(SqlWChar), strlen_buffer); + + std::basic_stringstream ss; + int64_t value_offset = 0; + + // Construct the whole string by concatenating smaller chunks from + // GetColumnarData + do { + ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset)); + ASSERT_EQ(values[0].length() * sizeof(SqlWChar), strlen_buffer[0]); + + int64_t chunk_length = + std::min(static_cast(max_strlen * sizeof(SqlWChar)), + strlen_buffer[0] - value_offset); + ss << buffer; + value_offset += chunk_length - sizeof(SqlWChar); + } while (value_offset < strlen_buffer[0] - sizeof(SqlWChar)); + + auto expected = CharToWStrConverter().from_bytes(values[0].c_str()); + auto actual = ss.str(); + ASSERT_EQ(0, expected.compare(actual)); +} + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h index 83c8be7f5f368..3bab8764b869a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h @@ -64,23 +64,65 @@ class Accessor { size_t cells, int64_t value_offset) = 0; }; -template +template class FlightSqlAccessor : public Accessor { public: - explicit FlightSqlAccessor(Array *array); + explicit FlightSqlAccessor(Array *array) + : Accessor(TARGET_TYPE), + array_(arrow::internal::checked_cast(array)) {} size_t GetColumnarData(ColumnBinding *binding, int64_t starting_row, - size_t cells, int64_t value_offset) override; + size_t cells, int64_t value_offset) override { + const std::shared_ptr &array = + array_->Slice(starting_row, static_cast(cells)); + + return GetColumnarData( + arrow::internal::checked_pointer_cast(array), binding, + value_offset); + } private: ARROW_ARRAY *array_; size_t GetColumnarData(const std::shared_ptr &sliced_array, - ColumnBinding *binding, int64_t value_offset); - - inline void MoveSingleCell(ColumnBinding *binding, ARROW_ARRAY *array, - int64_t i, int64_t value_offset); + ColumnBinding *binding, int64_t value_offset) { + return static_cast(this)->GetColumnarData_impl( + sliced_array, binding, value_offset); + } + + size_t GetColumnarData_impl(const std::shared_ptr &sliced_array, + ColumnBinding *binding, int64_t value_offset) { + int64_t length = sliced_array->length(); + for (int64_t i = 0; i < length; ++i) { + if (sliced_array->IsNull(i)) { + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = odbcabstraction::NULL_DATA; + } else { + // TODO: Report error when data is null bor strlen_buffer is nullptr + } + continue; + } + + MoveSingleCell(binding, sliced_array.get(), i, value_offset); + } + + return length; + } + + void MoveSingleCell(ColumnBinding *binding, ARROW_ARRAY *array, int64_t i, + int64_t value_offset) { + return static_cast(this)->MoveSingleCell_impl(binding, array, i, + value_offset); + } + + void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, + int64_t i, int64_t value_offset) { + std::stringstream ss; + ss << "Unknown type conversion from StringArray to target C type " + << TARGET_TYPE; + throw odbcabstraction::DriverException(ss.str()); + } }; } // namespace flight_sql -} // namespace driver \ No newline at end of file +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index ab1ab9a8e615b..cae171f6c7c84 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -86,53 +86,5 @@ class FlightSqlResultSet : public ResultSet { ssize_t *strlen_buffer) override; }; -template -FlightSqlAccessor::FlightSqlAccessor(Array *array) - : Accessor(TARGET_TYPE), - array_(arrow::internal::checked_cast(array)) {} - -template -size_t FlightSqlAccessor::GetColumnarData( - const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset) { - int64_t length = sliced_array->length(); - for (int64_t i = 0; i < length; ++i) { - if (sliced_array->IsNull(i)) { - if (binding->strlen_buffer) { - binding->strlen_buffer[i] = odbcabstraction::NULL_DATA; - } else { - // TODO: Report error when data is null bor strlen_buffer is nullptr - } - continue; - } - - MoveSingleCell(binding, sliced_array.get(), i, value_offset); - } - - return length; -} - -template -size_t FlightSqlAccessor::GetColumnarData( - ColumnBinding *binding, int64_t starting_row, size_t cells, - int64_t value_offset) { - const std::shared_ptr &array = - array_->Slice(starting_row, static_cast(cells)); - - return GetColumnarData( - arrow::internal::checked_pointer_cast(array), binding, - value_offset); -} - -template -void FlightSqlAccessor::MoveSingleCell( - ColumnBinding *binding, ARROW_ARRAY *array, int64_t i, - int64_t value_offset) { - std::stringstream ss; - ss << "Unknown type conversion from " << typeid(ARROW_ARRAY).name() - << " to target C type " << TARGET_TYPE; - throw odbcabstraction::DriverException(ss.str()); -} - } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index 32d14240671d2..406545186d391 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -16,94 +16,94 @@ // under the License. #include "accessors/main.h" +#include "boost/functional/hash.hpp" namespace driver { namespace flight_sql { -template -inline std::unique_ptr CreateAccessor(arrow::Array *source_array) { -#define ONE_CASE(ARROW_TYPE) \ - case arrow::ARROW_TYPE##Type::type_id: \ - return std::unique_ptr( \ - new FlightSqlAccessor( \ - source_array)); +using odbcabstraction::CDataType; - switch (source_array->type_id()) { - ONE_CASE(Boolean) - ONE_CASE(UInt8) - ONE_CASE(Int8) - ONE_CASE(UInt16) - ONE_CASE(Int16) - ONE_CASE(UInt32) - ONE_CASE(Int32) - ONE_CASE(UInt64) - ONE_CASE(Int64) - ONE_CASE(HalfFloat) - ONE_CASE(Float) - ONE_CASE(Double) - ONE_CASE(String) - ONE_CASE(Binary) - ONE_CASE(FixedSizeBinary) - ONE_CASE(Date32) - ONE_CASE(Date64) - ONE_CASE(Timestamp) - ONE_CASE(Time32) - ONE_CASE(Time64) - // ONE_CASE(IntervalMonths) - // ONE_CASE(IntervalDayTime) - ONE_CASE(Decimal128) - ONE_CASE(Decimal256) - ONE_CASE(List) - ONE_CASE(Struct) - ONE_CASE(SparseUnion) - ONE_CASE(DenseUnion) - ONE_CASE(Dictionary) - ONE_CASE(Map) - // ONE_CASE(Extension) - ONE_CASE(FixedSizeList) - ONE_CASE(Duration) - ONE_CASE(LargeString) - ONE_CASE(LargeBinary) - ONE_CASE(LargeList) - // ONE_CASE(IntervalMonthDayNano) - // ONE_CASE(MaxId) - default: - break; - } -#undef ONE_CASE - - throw odbcabstraction::DriverException("Unreachable"); -} - -std::unique_ptr -CreateAccessor(arrow::Array *source_array, - odbcabstraction::CDataType target_type) { +typedef std::pair SourceAndTargetPair; +typedef std::function AccessorConstructor; -#define CASE_FOR_TYPE(TARGET_TYPE) \ - case TARGET_TYPE: \ - return CreateAccessor(source_array); +std::unordered_map> + ACCESSORS_CONSTRUCTORS = { + {SourceAndTargetPair(arrow::Type::type::STRING, CDataType_CHAR), + [](arrow::Array *array) { + return new StringArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::STRING, CDataType_WCHAR), + [](arrow::Array *array) { + return new StringArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::DOUBLE, CDataType_DOUBLE), + [](arrow::Array *array) { + return new PrimitiveArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::FLOAT, CDataType_FLOAT), + [](arrow::Array *array) { + return new PrimitiveArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::INT64, CDataType_SBIGINT), + [](arrow::Array *array) { + return new PrimitiveArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::UINT64, CDataType_UBIGINT), + [](arrow::Array *array) { + return new PrimitiveArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::INT32, CDataType_SLONG), + [](arrow::Array *array) { + return new PrimitiveArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::UINT32, CDataType_ULONG), + [](arrow::Array *array) { + return new PrimitiveArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::INT16, CDataType_SSHORT), + [](arrow::Array *array) { + return new PrimitiveArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::UINT16, CDataType_USHORT), + [](arrow::Array *array) { + return new PrimitiveArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::INT8, CDataType_STINYINT), + [](arrow::Array *array) { + return new PrimitiveArrayFlightSqlAccessor( + array); + }}, + {SourceAndTargetPair(arrow::Type::type::UINT8, CDataType_UTINYINT), + [](arrow::Array *array) { + return new PrimitiveArrayFlightSqlAccessor( + array); + }}}; - // TODO: Maybe use something like BOOST_PP_SEQ_ENUM? Would like not to have - // all types mentioned one by one. - switch (target_type) { - CASE_FOR_TYPE(CDataType_CHAR) - CASE_FOR_TYPE(CDataType_WCHAR) - CASE_FOR_TYPE(CDataType_SSHORT) - CASE_FOR_TYPE(CDataType_USHORT) - CASE_FOR_TYPE(CDataType_SLONG) - CASE_FOR_TYPE(CDataType_ULONG) - CASE_FOR_TYPE(CDataType_FLOAT) - CASE_FOR_TYPE(CDataType_DOUBLE) - CASE_FOR_TYPE(CDataType_BIT) - CASE_FOR_TYPE(CDataType_STINYINT) - CASE_FOR_TYPE(CDataType_UTINYINT) - CASE_FOR_TYPE(CDataType_SBIGINT) - CASE_FOR_TYPE(CDataType_UBIGINT) - CASE_FOR_TYPE(CDataType_BINARY) +std::unique_ptr CreateAccessor(arrow::Array *source_array, + CDataType target_type) { + auto it = ACCESSORS_CONSTRUCTORS.find( + SourceAndTargetPair(source_array->type_id(), target_type)); + if (it != ACCESSORS_CONSTRUCTORS.end()) { + auto accessor = it->second(source_array); + return std::unique_ptr(accessor); } -#undef CASE_FOR_TYPE - throw odbcabstraction::DriverException("Unreachable"); + std::stringstream ss; + ss << "Unsupported type conversion! Tried to convert '" + << source_array->type()->ToString() << "' to C type '" << target_type + << "'"; + throw odbcabstraction::DriverException(ss.str()); } } // namespace flight_sql From 5a752d9f51fd989fb2d5fc388e62a446f4f1f2ac Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Thu, 3 Mar 2022 17:50:11 -0300 Subject: [PATCH 066/183] DX-45559: Implement SQL-to-C data conversions - primitive number types to simple C types Add unit tests for primitive array and implement accessor for BooleanArray (BIT data type) Change-Id: Id3da0a302765e9a52e070f6fa21b9e16b0f327fd --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 3 + .../accessors/boolean_array_accessor.cc | 50 ++++++++++ .../accessors/boolean_array_accessor.h | 42 ++++++++ .../accessors/boolean_array_accessor_test.cc | 50 ++++++++++ .../primitive_array_accessor_test.cc | 96 +++++++++++++++++++ 5 files changed, 241 insertions(+) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 948fdacf5c421..47afa5e33da4e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -83,6 +83,7 @@ find_package(gRPC 1.36 CONFIG REQUIRED) enable_testing() set(ARROW_ODBC_SPI_SOURCES + accessors/boolean_array_accessor.cc accessors/primitive_array_accessor.cc accessors/string_array_accessor.cc flight_sql_auth_method.cc @@ -132,6 +133,8 @@ target_link_libraries(arrow_odbc_spi_impl_cli arrow_odbc_spi_impl) # Unit tests set(ARROW_ODBC_SPI_TEST_SOURCES + accessors/boolean_array_accessor_test.cc + accessors/primitive_array_accessor_test.cc accessors/string_array_accessor_test.cc flight_sql_connection_test.cc ) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc new file mode 100644 index 0000000000000..2a86787b1d547 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc @@ -0,0 +1,50 @@ +// 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 "boolean_array_accessor.h" + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +template +BooleanArrayFlightSqlAccessor::BooleanArrayFlightSqlAccessor( + Array *array) + : FlightSqlAccessor>(array) {} + +template +void BooleanArrayFlightSqlAccessor::MoveSingleCell_impl( + ColumnBinding *binding, BooleanArray *array, int64_t i, + int64_t value_offset) { + typedef unsigned char c_type; + bool value = array->Value(i); + + auto *buffer = static_cast(binding->buffer); + buffer[i] = value ? 1 : 0; + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = static_cast(sizeof(unsigned char)); + } +} + +template class BooleanArrayFlightSqlAccessor; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h new file mode 100644 index 0000000000000..59f1ca6f5a618 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h @@ -0,0 +1,42 @@ +// 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. + +#pragma once + +#include "arrow/type_fwd.h" +#include "types.h" +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +template +class BooleanArrayFlightSqlAccessor + : public FlightSqlAccessor> { +public: + explicit BooleanArrayFlightSqlAccessor(Array *array); + + void MoveSingleCell_impl(ColumnBinding *binding, BooleanArray *array, + int64_t i, int64_t value_offset); +}; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc new file mode 100644 index 0000000000000..d5b252dc974b1 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc @@ -0,0 +1,50 @@ +// 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 "arrow/testing/gtest_util.h" +#include "boolean_array_accessor.h" +#include "gtest/gtest.h" + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +TEST(BooleanArrayFlightSqlAccessor, Test_BooleanArray_CDataType_BIT) { + std::vector values = {true, false, true}; + std::shared_ptr array; + ArrayFromVector(values, &array); + + BooleanArrayFlightSqlAccessor accessor(array.get()); + + char buffer[values.size()]; + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(CDataType_BIT, 0, 0, buffer, 0, strlen_buffer); + + ASSERT_EQ(values.size(), + accessor.GetColumnarData(&binding, 0, values.size(), 0)); + + for (int i = 0; i < values.size(); ++i) { + ASSERT_EQ(sizeof(unsigned char), strlen_buffer[i]); + ASSERT_EQ(values[i] ? 1 : 0, buffer[i]); + } +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc new file mode 100644 index 0000000000000..45d3a86e28a6c --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc @@ -0,0 +1,96 @@ +// 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 "arrow/testing/gtest_util.h" +#include "primitive_array_accessor.h" +#include "gtest/gtest.h" + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +template +void TestPrimitiveArraySqlAccessor() { + typedef typename ARROW_ARRAY::TypeClass::c_type c_type; + + std::vector values = {0, 1, 2, 3, 127}; + + std::shared_ptr array; + ArrayFromVector(values, &array); + + PrimitiveArrayFlightSqlAccessor accessor( + array.get()); + + c_type buffer[values.size()]; + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(TARGET_TYPE, 0, 0, buffer, values.size(), + strlen_buffer); + + ASSERT_EQ(values.size(), + accessor.GetColumnarData(&binding, 0, values.size(), 0)); + + for (int i = 0; i < values.size(); ++i) { + ASSERT_EQ(sizeof(c_type), strlen_buffer[i]); + ASSERT_EQ(values[i], buffer[i]); + } +} + +TEST(PrimitiveArrayFlightSqlAccessor, Test_Int64Array_CDataType_SBIGINT) { + TestPrimitiveArraySqlAccessor(); +} + +TEST(PrimitiveArrayFlightSqlAccessor, Test_Int32Array_CDataType_SLONG) { + TestPrimitiveArraySqlAccessor(); +} + +TEST(PrimitiveArrayFlightSqlAccessor, Test_Int16Array_CDataType_SSHORT) { + TestPrimitiveArraySqlAccessor(); +} + +TEST(PrimitiveArrayFlightSqlAccessor, Test_Int8Array_CDataType_STINYINT) { + TestPrimitiveArraySqlAccessor(); +} + +TEST(PrimitiveArrayFlightSqlAccessor, Test_UInt64Array_CDataType_UBIGINT) { + TestPrimitiveArraySqlAccessor(); +} + +TEST(PrimitiveArrayFlightSqlAccessor, Test_UInt32Array_CDataType_ULONG) { + TestPrimitiveArraySqlAccessor(); +} + +TEST(PrimitiveArrayFlightSqlAccessor, Test_UInt16Array_CDataType_USHORT) { + TestPrimitiveArraySqlAccessor(); +} + +TEST(PrimitiveArrayFlightSqlAccessor, Test_UInt8Array_CDataType_UTINYINT) { + TestPrimitiveArraySqlAccessor(); +} + +TEST(PrimitiveArrayFlightSqlAccessor, Test_FloatArray_CDataType_FLOAT) { + TestPrimitiveArraySqlAccessor(); +} + +TEST(PrimitiveArrayFlightSqlAccessor, Test_DoubleArray_CDataType_DOUBLE) { + TestPrimitiveArraySqlAccessor(); +} + +} // namespace flight_sql +} // namespace driver From 826068399bc37bc665ab33fe084fc95149de9900 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Fri, 4 Mar 2022 11:36:29 -0300 Subject: [PATCH 067/183] DX-45572: Implement SQL-to-C conversion - SQL_BIT This integrates BooleanArrayFlightSqlAccessor into FlightSqlResultSet. Change-Id: I652117b82cc90dbb450129f3cdd168cd09adbf70 --- .../flightsql-odbc/flight_sql/accessors/main.h | 1 + .../flight_sql/flight_sql_result_set_accessors.cc | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h index e7496ff4d2fdd..8639b56780bb4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h @@ -17,5 +17,6 @@ #pragma once +#include "boolean_array_accessor.h" #include "primitive_array_accessor.h" #include "string_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index 406545186d391..10ba67fa5364b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -26,8 +26,10 @@ using odbcabstraction::CDataType; typedef std::pair SourceAndTargetPair; typedef std::function AccessorConstructor; -std::unordered_map> +namespace { + +const std::unordered_map> ACCESSORS_CONSTRUCTORS = { {SourceAndTargetPair(arrow::Type::type::STRING, CDataType_CHAR), [](arrow::Array *array) { @@ -88,8 +90,14 @@ std::unordered_map( array); + }}, + {SourceAndTargetPair(arrow::Type::type::BOOL, CDataType_BIT), + [](arrow::Array *array) { + return new BooleanArrayFlightSqlAccessor(array); }}}; +} + std::unique_ptr CreateAccessor(arrow::Array *source_array, CDataType target_type) { auto it = ACCESSORS_CONSTRUCTORS.find( From d1130de1680834759cfb3ea85bd7828aa004a851 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Fri, 4 Mar 2022 15:11:24 -0300 Subject: [PATCH 068/183] DX-45564: Implement SQL-to-C conversion - binary This implements BinaryArrayFlightSqlAccessor for dealing with BINARY data, which is similar to CHAR except for its values are not null terminated Change-Id: I63152d22a5ebc333ffda46701a86a9179b85fe90 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 2 + .../accessors/binary_array_accessor.cc | 69 ++++++++++++++ .../accessors/binary_array_accessor.h | 42 +++++++++ .../accessors/binary_array_accessor_test.cc | 94 +++++++++++++++++++ .../flight_sql/accessors/main.h | 1 + .../flight_sql_result_set_accessors.cc | 4 + 6 files changed, 212 insertions(+) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 47afa5e33da4e..320f1c7f09ae0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -83,6 +83,7 @@ find_package(gRPC 1.36 CONFIG REQUIRED) enable_testing() set(ARROW_ODBC_SPI_SOURCES + accessors/binary_array_accessor.cc accessors/boolean_array_accessor.cc accessors/primitive_array_accessor.cc accessors/string_array_accessor.cc @@ -134,6 +135,7 @@ target_link_libraries(arrow_odbc_spi_impl_cli arrow_odbc_spi_impl) # Unit tests set(ARROW_ODBC_SPI_TEST_SOURCES accessors/boolean_array_accessor_test.cc + accessors/binary_array_accessor_test.cc accessors/primitive_array_accessor_test.cc accessors/string_array_accessor_test.cc flight_sql_connection_test.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc new file mode 100644 index 0000000000000..d3a02e1f94ce9 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc @@ -0,0 +1,69 @@ +// 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 + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +namespace { + +inline void MoveSingleCellToBinaryBuffer(ColumnBinding *binding, + BinaryArray *array, int64_t i, + int64_t value_offset) { + + const char *value = array->Value(i).data(); + size_t size_in_bytes = array->value_length(i); + + // TODO: Handle truncation + size_t value_length = + std::min(static_cast(size_in_bytes - value_offset), + binding->buffer_length); + + auto *byte_buffer = static_cast(binding->buffer) + + i * binding->buffer_length; + memcpy(byte_buffer, ((char *)value) + value_offset, value_length); + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = static_cast(size_in_bytes); + } +} + +} // namespace + +template +BinaryArrayFlightSqlAccessor::BinaryArrayFlightSqlAccessor( + Array *array) + : FlightSqlAccessor>(array) {} + +template <> +void BinaryArrayFlightSqlAccessor::MoveSingleCell_impl( + ColumnBinding *binding, BinaryArray *array, int64_t i, + int64_t value_offset) { + MoveSingleCellToBinaryBuffer(binding, array, i, value_offset); +} + +template class BinaryArrayFlightSqlAccessor; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h new file mode 100644 index 0000000000000..57689eeff76ad --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h @@ -0,0 +1,42 @@ +// 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. + +#pragma once + +#include "arrow/type_fwd.h" +#include "types.h" +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +template +class BinaryArrayFlightSqlAccessor + : public FlightSqlAccessor> { +public: + explicit BinaryArrayFlightSqlAccessor(Array *array); + + void MoveSingleCell_impl(ColumnBinding *binding, BinaryArray *array, + int64_t i, int64_t value_offset); +}; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc new file mode 100644 index 0000000000000..fbdb51b426cb1 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc @@ -0,0 +1,94 @@ +// 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 "arrow/testing/gtest_util.h" +#include "binary_array_accessor.h" +#include "gtest/gtest.h" + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Basic) { + std::vector values = {"foo", "barx", "baz123"}; + std::shared_ptr array; + ArrayFromVector(values, &array); + + BinaryArrayFlightSqlAccessor accessor(array.get()); + + size_t max_strlen = 64; + char buffer[values.size() * max_strlen]; + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(CDataType_BINARY, 0, 0, buffer, max_strlen, + strlen_buffer); + + ASSERT_EQ(values.size(), + accessor.GetColumnarData(&binding, 0, values.size(), 0)); + + for (int i = 0; i < values.size(); ++i) { + ASSERT_EQ(values[i].length(), strlen_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 ASCII, + // this doesn't work with arbitrary binary data. + ASSERT_EQ(values[i], + std::string(buffer + i * max_strlen, + buffer + i * max_strlen + strlen_buffer[i])); + } +} + +TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Truncation) { + std::vector values = { + "ABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEF"}; + std::shared_ptr array; + ArrayFromVector(values, &array); + + BinaryArrayFlightSqlAccessor accessor(array.get()); + + size_t max_strlen = 8; + char buffer[values.size() * max_strlen]; + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(CDataType_BINARY, 0, 0, buffer, max_strlen, + strlen_buffer); + + std::stringstream ss; + int64_t value_offset = 0; + + // Construct the whole string by concatenating smaller chunks from + // GetColumnarData + do { + ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset)); + ASSERT_EQ(values[0].length(), strlen_buffer[0]); + + int64_t chunk_length = std::min(static_cast(max_strlen), + strlen_buffer[0] - value_offset); + + // 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 ASCII, + // this doesn't work with arbitrary binary data. + ss << std::string(buffer, buffer + chunk_length); + value_offset += chunk_length; + } while (value_offset < strlen_buffer[0]); + + ASSERT_EQ(values[0], ss.str()); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h index 8639b56780bb4..8cd34cc133117 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h @@ -17,6 +17,7 @@ #pragma once +#include "binary_array_accessor.h" #include "boolean_array_accessor.h" #include "primitive_array_accessor.h" #include "string_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index 10ba67fa5364b..6e5ed809ebb74 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -94,6 +94,10 @@ const std::unordered_map(array); + }}, + {SourceAndTargetPair(arrow::Type::type::BINARY, CDataType_BINARY), + [](arrow::Array *array) { + return new BinaryArrayFlightSqlAccessor(array); }}}; } From 097c202a954321d9b6490805581b9e4131795980 Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 7 Mar 2022 16:40:52 -0800 Subject: [PATCH 069/183] Fix Mac build errors after adding bulk accessors - Remove unneeded dependency on utf8proc - Fix missing includes of arrow/testing/builder.h used for vectorToArray - Fix portability issues with unicode converter tests Change-Id: I48f6821851827726444f08eec5ace8e70c869bc1 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 5 +++++ .../flight_sql/accessors/binary_array_accessor_test.cc | 3 +++ .../flight_sql/accessors/boolean_array_accessor_test.cc | 3 +++ .../flight_sql/accessors/primitive_array_accessor_test.cc | 3 +++ .../flight_sql/accessors/string_array_accessor_test.cc | 8 ++++++-- 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 320f1c7f09ae0..65fc286955871 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -34,6 +34,7 @@ set(ARROW_CMAKE_ARGS -DARROW_BUILD_SHARED=OFF -DARROW_BUILD_STATIC=ON -DARROW_COMPUTE=ON + -DARROW_WITH_UTF8PROC=OFF -DARROW_BUILD_TESTS=OFF -DARROW_DEPENDENCY_USE_SHARED=OFF -DCMAKE_DEPENDS_USE_COMPILER=FALSE @@ -80,6 +81,10 @@ find_package(OpenSSL REQUIRED) # Add gRPC dependencies needed by Arrow Flight. Should be pre-installed. find_package(gRPC 1.36 CONFIG REQUIRED) +if (APPLE) + add_compile_definitions(WITH_IODBC) +endif() + enable_testing() set(ARROW_ODBC_SPI_SOURCES diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc index fbdb51b426cb1..e2b536f98b6c2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc @@ -16,6 +16,9 @@ // under the License. #include "arrow/testing/gtest_util.h" +#ifdef __APPLE__ +#include "arrow/testing/builder.h" +#endif #include "binary_array_accessor.h" #include "gtest/gtest.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc index d5b252dc974b1..fbf07c61eab8b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc @@ -16,6 +16,9 @@ // under the License. #include "arrow/testing/gtest_util.h" +#ifdef __APPLE__ +#include "arrow/testing/builder.h" +#endif #include "boolean_array_accessor.h" #include "gtest/gtest.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc index 45d3a86e28a6c..b8df5dc5eb128 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc @@ -16,6 +16,9 @@ // under the License. #include "arrow/testing/gtest_util.h" +#ifdef __APPLE__ +#include "arrow/testing/builder.h" +#endif #include "primitive_array_accessor.h" #include "gtest/gtest.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc index 88205f0a19dc5..1e4204816fee2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc @@ -16,6 +16,9 @@ // under the License. #include "arrow/testing/gtest_util.h" +#ifdef __APPLE__ +#include "arrow/testing/builder.h" +#endif #include "string_array_accessor.h" #include "gtest/gtest.h" @@ -126,6 +129,7 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Truncation) { // Construct the whole string by concatenating smaller chunks from // GetColumnarData + std::basic_string finalStr; do { ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset)); ASSERT_EQ(values[0].length() * sizeof(SqlWChar), strlen_buffer[0]); @@ -133,12 +137,12 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Truncation) { int64_t chunk_length = std::min(static_cast(max_strlen * sizeof(SqlWChar)), strlen_buffer[0] - value_offset); - ss << buffer; + finalStr += std::basic_string(buffer, chunk_length); value_offset += chunk_length - sizeof(SqlWChar); } while (value_offset < strlen_buffer[0] - sizeof(SqlWChar)); auto expected = CharToWStrConverter().from_bytes(values[0].c_str()); - auto actual = ss.str(); + auto actual = finalStr; ASSERT_EQ(0, expected.compare(actual)); } From 42623d976b51ab5ccd697b55817c9958334dba7b Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Tue, 8 Mar 2022 16:55:56 -0300 Subject: [PATCH 070/183] DX-45556: Design a transformer that will change a RecordBatch according to parameters It implements a new class RecordBatchTransformer with its Builder. It is responsible to convert the name of fields inside a RecordBatch. These fields are changed based on tasks created by the methods RenameRecord() and AddEmptyFields(). The execution of the tasks is handled by the method transformer. Change-Id: I8894d0cbfc21b11aa6c64c9ffaab92dcedff0724 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 3 + .../accessors/binary_array_accessor_test.cc | 8 +- .../flight_sql/record_batch_transformer.cc | 127 ++++++++++++++ .../flight_sql/record_batch_transformer.h | 93 ++++++++++ .../record_batch_transformer_test.cc | 161 ++++++++++++++++++ 5 files changed, 388 insertions(+), 4 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 65fc286955871..0ab83840951f4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -101,6 +101,7 @@ set(ARROW_ODBC_SPI_SOURCES flight_sql_result_set_metadata.cc flight_sql_statement.cc flight_sql_stream_chunk_iterator.cc + record_batch_transformer.cc ) set(ARROW_ODBC_SPI_THIRDPARTY_LIBS @@ -144,6 +145,7 @@ set(ARROW_ODBC_SPI_TEST_SOURCES accessors/primitive_array_accessor_test.cc accessors/string_array_accessor_test.cc flight_sql_connection_test.cc + record_batch_transformer_test.cc ) add_executable(arrow_odbc_spi_impl_test ${ARROW_ODBC_SPI_TEST_SOURCES}) @@ -156,3 +158,4 @@ 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) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc index e2b536f98b6c2..8bb32bb262c3d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc @@ -48,8 +48,8 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Basic) { for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(values[i].length(), strlen_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 ASCII, - // this doesn't work with arbitrary binary data. + // It's safe to create a std::string from this data because we know it's + // ASCII, this doesn't work with arbitrary binary data. ASSERT_EQ(values[i], std::string(buffer + i * max_strlen, buffer + i * max_strlen + strlen_buffer[i])); @@ -84,8 +84,8 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Truncation) { strlen_buffer[0] - value_offset); // 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 ASCII, - // this doesn't work with arbitrary binary data. + // It's safe to create a std::string from this data because we know it's + // ASCII, this doesn't work with arbitrary binary data. ss << std::string(buffer, buffer + chunk_length); value_offset += chunk_length; } while (value_offset < strlen_buffer[0]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc new file mode 100644 index 0000000000000..4e54db69566d4 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc @@ -0,0 +1,127 @@ +// 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 "record_batch_transformer.h" + +#include "utils.h" +#include +#include +#include +#include + +#include "arrow/array/array_base.h" + +namespace driver { +namespace flight_sql { + +using namespace arrow; + +namespace { +Result> MakeEmptyArray(std::shared_ptr type, + MemoryPool *memory_pool, + int64_t array_size) { + std::unique_ptr builder; + RETURN_NOT_OK(MakeBuilder(memory_pool, type, &builder)); + RETURN_NOT_OK(builder->AppendNulls(array_size)); + return builder->Finish(); +} +} // namespace + +RecordBatchTransformer::Builder &RecordBatchTransformer::Builder::RenameRecord( + const std::string &original_name, const std::string &transformed_name) { + + auto rename_task = [&original_name, &transformed_name]( + const std::shared_ptr &original_record, + const std::shared_ptr &transformed_schema) { + auto original_data_type = + original_record->schema()->GetFieldByName(original_name); + auto transformed_data_type = + transformed_schema->GetFieldByName(transformed_name); + + if (original_data_type->type() != transformed_data_type->type()) { + throw odbcabstraction::DriverException( + "Original data and target data has different types"); + } + + return original_record->GetColumnByName(original_name); + }; + + task_collection_.emplace_back(rename_task); + + auto original_fields = schema_->GetFieldByName(original_name); + + new_fields_.push_back(field(transformed_name, original_fields->type(), + original_fields->metadata())); + + return *this; +} + +RecordBatchTransformer::Builder & +RecordBatchTransformer::Builder::AddEmptyFields( + const std::string &field_name, const std::shared_ptr &data_type) { + auto empty_fields_task = + [=](const std::shared_ptr &original_record, + const std::shared_ptr &transformed_schema) { + auto result = + MakeEmptyArray(data_type, nullptr, original_record->num_rows()); + driver::flight_sql::ThrowIfNotOK(result.status()); + + return result.ValueOrDie(); + }; + + task_collection_.emplace_back(empty_fields_task); + + new_fields_.push_back(field(field_name, data_type)); + + return *this; +} + +RecordBatchTransformer RecordBatchTransformer::Builder::Build() { + RecordBatchTransformer transformer(*this); + + return transformer; +} + +RecordBatchTransformer::Builder::Builder(std::shared_ptr schema) + : schema_(std::move(schema)) {} + +std::shared_ptr RecordBatchTransformer::Transform( + const std::shared_ptr &original) { + auto new_schema = schema(fields_); + + std::vector> arrays; + + for (const auto &item : tasks_) { + arrays.push_back(item(original, new_schema)); + } + + auto transformed_batch = + RecordBatch::Make(new_schema, original->num_rows(), arrays); + return transformed_batch; +} + +std::shared_ptr RecordBatchTransformer::GetTransformedSchema() { + return schema(fields_); +} + +RecordBatchTransformer::RecordBatchTransformer( + RecordBatchTransformer::Builder &builder) { + this->fields_.swap(builder.new_fields_); + this->tasks_.swap(builder.task_collection_); +} +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.h new file mode 100644 index 0000000000000..f4444d7bfad3f --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.h @@ -0,0 +1,93 @@ +// 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. + +#pragma once + +#include +#include +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; + +/// A transformer class which is responsible to convert the name of fields +/// inside a RecordBatch. These fields are changed based on tasks created by the +/// methods RenameRecord() and AddEmptyFields(). The execution of the tasks is +/// handled by the method transformer. +class RecordBatchTransformer { +private: + std::vector> fields_; + std::vector( + const std::shared_ptr &original_record_batch, + const std::shared_ptr &transformed_schema)>> + tasks_; + +public: + class Builder { + private: + std::vector> new_fields_; + std::vector( + const std::shared_ptr &original_record_batch, + const std::shared_ptr &transformed_schema)>> + task_collection_; + std::shared_ptr schema_; + + public: + friend class RecordBatchTransformer; + + /// Based on the original array name and in a target array name it prepares + /// a task that will execute the transformation. + /// \param original_name The original name of the field. + /// \param transformed_name The name after the transformation. + Builder &RenameRecord(const std::string &original_name, + const std::string &transformed_name); + + /// Add an empty field to the transformed record batch. + /// \param field_name The name of the empty fields. + /// \param data_type The target data type for the new fields. + Builder &AddEmptyFields(const std::string &field_name, + const std::shared_ptr &data_type); + + /// It creates an object of RecordBatchTransformer + /// \return a RecordBatchTransformer object. + RecordBatchTransformer Build(); + + /// Instantiate a Builder object. + /// \param schema The schema from the original RecordBatch. + explicit Builder(std::shared_ptr schema); + }; + + /// Execute the transformation based on predeclared tasks created by + /// RenameRecord() method and/or AddEmptyFields(). + /// \param original The original RecordBatch that will be used as base + /// for the transformation. + /// \return The new transformed RecordBatch. + std::shared_ptr + Transform(const std::shared_ptr &original); + + /// Use the new list of fields constructed during creation of task + /// to return the new schema. + /// \return the schema from the transformedRecordBatch. + std::shared_ptr GetTransformedSchema(); + +private: + explicit RecordBatchTransformer(Builder &builder); +}; +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc new file mode 100644 index 0000000000000..777916ecb23a8 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc @@ -0,0 +1,161 @@ +// 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 "record_batch_transformer.h" +#include "gtest/gtest.h" +#include +#include + +using namespace arrow; + +namespace { +std::shared_ptr CreateOriginalRecordBatch() { + std::vector values = {1, 2, 3, 4, 5}; + std::shared_ptr array; + + ArrayFromVector(values, &array); + + auto schema = arrow::schema({field("test", int32(), false)}); + + return RecordBatch::Make(schema, 4, {array}); +} +} // namespace + +namespace driver { +namespace flight_sql { + +TEST(Transformer, TransformerRenameTest) { + // Prepare the Original Record Batch + auto original_record_batch = CreateOriginalRecordBatch(); + auto schema = original_record_batch->schema(); + + // Execute the transformation of the Record Batch + std::string original_name("test"); + std::string transformed_name("test1"); + + auto transformer = RecordBatchTransformer::Builder(schema) + .RenameRecord(original_name, transformed_name) + .Build(); + + auto transformed_record_batch = transformer.Transform(original_record_batch); + + auto transformed_array_ptr = + transformed_record_batch->GetColumnByName(transformed_name); + + auto original_array_ptr = + original_record_batch->GetColumnByName(original_name); + + // Assert that the arrays are being the same and we are not creating new + // buffers + ASSERT_EQ(transformed_array_ptr, original_array_ptr); + + // Assert if the schema is not the same + ASSERT_NE(original_record_batch->schema(), + transformed_record_batch->schema()); + // Assert if the data is not changed + ASSERT_EQ(original_record_batch->GetColumnByName(original_name), + transformed_record_batch->GetColumnByName(transformed_name)); +} + +TEST(Transformer, TransformerAddEmptyVectorTest) { + // Prepare the Original Record Batch + auto original_record_batch = CreateOriginalRecordBatch(); + auto schema = original_record_batch->schema(); + + std::string original_name("test"); + std::string transformed_name("test1"); + auto emptyField = std::string("empty"); + + auto transformer = RecordBatchTransformer::Builder(schema) + .RenameRecord(original_name, transformed_name) + .AddEmptyFields(emptyField, int32()) + .Build(); + + auto transformed_schema = transformer.GetTransformedSchema(); + + ASSERT_EQ(transformed_schema->num_fields(), 2); + ASSERT_EQ(transformed_schema->GetFieldIndex(transformed_name), 0); + ASSERT_EQ(transformed_schema->GetFieldIndex(emptyField), 1); + + auto transformed_record_batch = transformer.Transform(original_record_batch); + + auto transformed_array_ptr = + transformed_record_batch->GetColumnByName(transformed_name); + + auto original_array_ptr = + original_record_batch->GetColumnByName(original_name); + + // Assert that the arrays are being the same and we are not creating new + // buffers + ASSERT_EQ(transformed_array_ptr, original_array_ptr); + + // Assert if the schema is not the same + ASSERT_NE(original_record_batch->schema(), + transformed_record_batch->schema()); + // Assert if the data is not changed + ASSERT_EQ(original_record_batch->GetColumnByName(original_name), + transformed_record_batch->GetColumnByName(transformed_name)); +} + +TEST(Transformer, TransformerChangingOrderOfArrayTest) { + std::vector first_array_value = {1, 2, 3, 4, 5}; + std::vector second_array_value = {6, 7, 8, 9, 10}; + std::vector third_array_value = {2, 4, 6, 8, 10}; + std::shared_ptr first_array; + std::shared_ptr second_array; + std::shared_ptr third_array; + + ArrayFromVector(first_array_value, &first_array); + ArrayFromVector(second_array_value, &second_array); + ArrayFromVector(third_array_value, &third_array); + + auto schema = arrow::schema({field("first_array", int32(), false), + field("second_array", int32(), false), + field("third_array", int32(), false)}); + + auto original_record_batch = + RecordBatch::Make(schema, 5, {first_array, second_array, third_array}); + + auto transformer = + RecordBatchTransformer::Builder(schema) + .RenameRecord(std::string("third_array"), std::string("test3")) + .RenameRecord(std::string("second_array"), std::string("test2")) + .RenameRecord(std::string("first_array"), std::string("test1")) + .AddEmptyFields(std::string("empty"), int32()) + .Build(); + + const std::shared_ptr &transformed_record_batch = + transformer.Transform(original_record_batch); + + auto transformed_schema = transformed_record_batch->schema(); + + // Assert to check if the empty fields was added + ASSERT_EQ(transformed_record_batch->num_columns(), 4); + + // Assert to make sure that the elements changed his order. + ASSERT_EQ(transformed_schema->GetFieldIndex("test3"), 0); + ASSERT_EQ(transformed_schema->GetFieldIndex("test2"), 1); + ASSERT_EQ(transformed_schema->GetFieldIndex("test1"), 2); + ASSERT_EQ(transformed_schema->GetFieldIndex("empty"), 3); + + // Assert to make sure that the data didn't change after renaming the arrays + ASSERT_EQ(transformed_record_batch->GetColumnByName("test3"), third_array); + ASSERT_EQ(transformed_record_batch->GetColumnByName("test2"), second_array); + ASSERT_EQ(transformed_record_batch->GetColumnByName("test1"), first_array); +} +} // namespace flight_sql +} // namespace driver From 3aa7639afaade1836b531f9b556f47c1ab2bc4eb Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 21 Mar 2022 08:32:42 -0700 Subject: [PATCH 071/183] FIXUP: test include issues - Include arrow builder on tests - Remove referencing gtest_util in the implementation Change-Id: I3383a3aee72b4cd9b6ecf3fb7c833c473e4bc24c --- .../flight_sql/accessors/binary_array_accessor_test.cc | 3 --- .../flight_sql/accessors/boolean_array_accessor_test.cc | 3 --- .../flight_sql/accessors/primitive_array_accessor_test.cc | 3 --- .../flight_sql/accessors/string_array_accessor_test.cc | 3 --- .../flightsql-odbc/flight_sql/flight_sql_connection.cc | 1 - .../flightsql-odbc/flight_sql/record_batch_transformer.cc | 2 +- .../flightsql-odbc/flight_sql/record_batch_transformer_test.cc | 3 +-- 7 files changed, 2 insertions(+), 16 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc index 8bb32bb262c3d..1dd590b550d55 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc @@ -15,10 +15,7 @@ // specific language governing permissions and limitations // under the License. -#include "arrow/testing/gtest_util.h" -#ifdef __APPLE__ #include "arrow/testing/builder.h" -#endif #include "binary_array_accessor.h" #include "gtest/gtest.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc index fbf07c61eab8b..d23fd9f7bc857 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc @@ -15,10 +15,7 @@ // specific language governing permissions and limitations // under the License. -#include "arrow/testing/gtest_util.h" -#ifdef __APPLE__ #include "arrow/testing/builder.h" -#endif #include "boolean_array_accessor.h" #include "gtest/gtest.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc index b8df5dc5eb128..5ff49ae26bb2a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc @@ -15,10 +15,7 @@ // specific language governing permissions and limitations // under the License. -#include "arrow/testing/gtest_util.h" -#ifdef __APPLE__ #include "arrow/testing/builder.h" -#endif #include "primitive_array_accessor.h" #include "gtest/gtest.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc index 1e4204816fee2..c8e901d4ed038 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc @@ -15,10 +15,7 @@ // specific language governing permissions and limitations // under the License. -#include "arrow/testing/gtest_util.h" -#ifdef __APPLE__ #include "arrow/testing/builder.h" -#endif #include "string_array_accessor.h" #include "gtest/gtest.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index f2d108546c73a..10454a5d2a1b6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -23,7 +23,6 @@ #include #include #include -#include #include namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc index 4e54db69566d4..ec8c3cea2d6a9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc @@ -19,7 +19,7 @@ #include "utils.h" #include -#include +#include #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc index 777916ecb23a8..b6c3d2aecb76a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc @@ -18,8 +18,7 @@ #include "record_batch_transformer.h" #include "gtest/gtest.h" #include -#include - +#include "arrow/testing/builder.h" using namespace arrow; namespace { From f1afb6830bc3c20c9de884c146232beef216272f Mon Sep 17 00:00:00 2001 From: James Duong Date: Wed, 16 Mar 2022 08:12:40 -0700 Subject: [PATCH 072/183] Implement GetInfo based on GetSqlInfo data - Update the signature of GetInfo to match ODBC's types. - Populate a map of GetInfo metadata based on SqlGetInfo - Add stubs for GetInfo types that can't be reported by SqlGetInfo - Implement SQL_USER_NAME based on user when using basic credentials. - Allow UID/PWD to alias username/password per the spec for SQLDriverConnect Change-Id: I8c5d99022157eda0938db789a2740f3f1abbfb63 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 2 + .../flight_sql/flight_sql_auth_method.cc | 14 +- .../flight_sql/flight_sql_auth_method.h | 5 + .../flight_sql/flight_sql_connection.cc | 25 +- .../flight_sql/flight_sql_connection.h | 5 + .../flight_sql/get_info_cache.cc | 1078 +++++++++++++++++ .../flight_sql/get_info_cache.h | 58 + .../flight_sql/scalar_function_reporter.cc | 142 +++ .../flight_sql/scalar_function_reporter.h | 36 + .../include/odbcabstraction/connection.h | 2 +- .../include/odbcabstraction/driver.h | 4 +- .../include/odbcabstraction/result_set.h | 4 +- 12 files changed, 1358 insertions(+), 17 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 0ab83840951f4..06c0f305c3c9e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -101,7 +101,9 @@ set(ARROW_ODBC_SPI_SOURCES flight_sql_result_set_metadata.cc flight_sql_statement.cc flight_sql_stream_chunk_iterator.cc + get_info_cache.cc record_batch_transformer.cc + scalar_function_reporter.cc ) set(ARROW_ODBC_SPI_THIRDPARTY_LIBS diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index af5f2f91e3feb..19b25d50c7244 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -78,6 +78,10 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { call_options.headers.push_back(bearer_result.ValueOrDie()); } + std::string GetUser() override { + return user_; + } + private: FlightClient &client_; std::string user_; @@ -90,8 +94,14 @@ std::unique_ptr FlightSqlAuthMethod::FromProperties( const Connection::ConnPropertyMap &properties) { // Check if should use user-password authentication - const auto &it_user = properties.find(FlightSqlConnection::USER); - const auto &it_password = properties.find(FlightSqlConnection::PASSWORD); + auto it_user = properties.find(FlightSqlConnection::USER); + auto it_password = properties.find(FlightSqlConnection::PASSWORD); + if (it_user == properties.end() || it_password == properties.end()) { + // Accept UID/PWD as aliases for User/Password. These are suggested as standard properties + // in the documentation for SQLDriverConnect. + it_user = properties.find(FlightSqlConnection::UID); + it_password = properties.find(FlightSqlConnection::PWD); + } if (it_user != properties.end() || it_password != properties.end()) { const std::string &user = it_user != properties.end() ? boost::get(it_user->second) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index 0d897b7dfdda5..ccdfee3b43e57 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -21,6 +21,7 @@ #include #include #include +#include #include namespace driver { @@ -33,6 +34,10 @@ class FlightSqlAuthMethod { virtual void Authenticate(FlightSqlConnection &connection, arrow::flight::FlightCallOptions &call_options) = 0; + virtual std::string GetUser() { + return std::string(); + } + static std::unique_ptr FromProperties( const std::unique_ptr &client, const odbcabstraction::Connection::ConnPropertyMap &properties); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 10454a5d2a1b6..eaa9ec08b7c14 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -17,13 +17,16 @@ #include "flight_sql_connection.h" -#include "flight_sql_auth_method.h" -#include "flight_sql_statement.h" #include #include #include #include #include +#include + +#include "flight_sql_auth_method.h" +#include "flight_sql_statement.h" +#include "utils.h" namespace driver { namespace flight_sql { @@ -44,19 +47,15 @@ using driver::odbcabstraction::Statement; const std::string FlightSqlConnection::HOST = "host"; const std::string FlightSqlConnection::PORT = "port"; const std::string FlightSqlConnection::USER = "user"; +const std::string FlightSqlConnection::UID = "uid"; const std::string FlightSqlConnection::PASSWORD = "password"; +const std::string FlightSqlConnection::PWD = "pwd"; const std::string FlightSqlConnection::USE_TLS = "useTls"; namespace { // TODO: Add properties for getting the certificates // TODO: Check if gRPC can use the system truststore, if not copy from Drill -inline void ThrowIfNotOK(const Status &status) { - if (!status.ok()) { - throw DriverException(status.ToString()); - } -} - Connection::ConnPropertyMap::const_iterator TrackMissingRequiredProperty(const std::string &property, const Connection::ConnPropertyMap &properties, @@ -91,6 +90,11 @@ void FlightSqlConnection::Connect(const ConnPropertyMap &properties, auth_method->Authenticate(*this, call_options_); sql_client_.reset(new FlightSqlClient(std::move(flight_client))); + + // Note: This should likely come from Flight instead of being from the + // connection properties to allow reporting a user for other auth mechanisms + // and also decouple the database user from user credentials. + info_.SetProperty(SQL_USER_NAME, auth_method->GetUser()); SetAttribute(CONNECTION_DEAD, false); PopulateCallOptionsFromAttributes(); @@ -181,11 +185,12 @@ FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { } Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { - throw DriverException("GetInfo not implemented"); + return info_.GetInfo(info_type); } FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version) - : odbc_version_(odbc_version) {} + : odbc_version_(odbc_version), info_(call_options_, sql_client_), + closed_(false) {} } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 78a1f6c65a27a..b09b48881862f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -22,6 +22,8 @@ #include #include +#include "get_info_cache.h" + namespace driver { namespace flight_sql { @@ -31,6 +33,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { std::map attribute_; arrow::flight::FlightCallOptions call_options_; std::unique_ptr sql_client_; + GetInfoCache info_; odbcabstraction::OdbcVersion odbc_version_; bool closed_; @@ -38,7 +41,9 @@ class FlightSqlConnection : public odbcabstraction::Connection { static const std::string HOST; static const std::string PORT; static const std::string USER; + static const std::string UID; static const std::string PASSWORD; + static const std::string PWD; static const std::string USE_TLS; explicit FlightSqlConnection(odbcabstraction::OdbcVersion odbc_version); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc new file mode 100644 index 0000000000000..36eaa8c239ac5 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc @@ -0,0 +1,1078 @@ +// 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 "get_info_cache.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "flight_sql_stream_chunk_iterator.h" +#include "scalar_function_reporter.h" +#include "utils.h" + +// Aliases for entries in SqlInfoOptions::SqlInfo that are defined here +// due to causing compilation errors conflicting with ODBC definitions. +#define ARROW_SQL_IDENTIFIER_CASE 503 +#define ARROW_SQL_IDENTIFIER_QUOTE_CHAR 504 +#define ARROW_SQL_QUOTED_IDENTIFIER_CASE 505 +#define ARROW_SQL_KEYWORDS 508 +#define ARROW_SQL_NUMERIC_FUNCTIONS 509 +#define ARROW_SQL_STRING_FUNCTIONS 510 +#define ARROW_SQL_SYSTEM_FUNCTIONS 511 +#define ARROW_SQL_SCHEMA_TERM 529 +#define ARROW_SQL_PROCEDURE_TERM 530 +#define ARROW_SQL_CATALOG_TERM 531 +#define ARROW_SQL_MAX_COLUMNS_IN_GROUP_BY 544 +#define ARROW_SQL_MAX_COLUMNS_IN_INDEX 545 +#define ARROW_SQL_MAX_COLUMNS_IN_ORDER_BY 546 +#define ARROW_SQL_MAX_COLUMNS_IN_SELECT 547 +#define ARROW_SQL_MAX_COLUMNS_IN_TABLE 548 +#define ARROW_SQL_MAX_ROW_SIZE 555 +#define ARROW_SQL_MAX_TABLES_IN_SELECT 560 + +#define ARROW_CONVERT_BIGINT 0 +#define ARROW_CONVERT_BINARY 1 +#define ARROW_CONVERT_BIT 2 +#define ARROW_CONVERT_CHAR 3 +#define ARROW_CONVERT_DATE 4 +#define ARROW_CONVERT_DECIMAL 5 +#define ARROW_CONVERT_FLOAT 6 +#define ARROW_CONVERT_INTEGER 7 +#define ARROW_CONVERT_INTERVAL_DAY_TIME 8 +#define ARROW_CONVERT_INTERVAL_YEAR_MONTH 9 +#define ARROW_CONVERT_LONGVARBINARY 10 +#define ARROW_CONVERT_LONGVARCHAR 11 +#define ARROW_CONVERT_NUMERIC 12 +#define ARROW_CONVERT_REAL 13 +#define ARROW_CONVERT_SMALLINT 14 +#define ARROW_CONVERT_TIME 15 +#define ARROW_CONVERT_TIMESTAMP 16 +#define ARROW_CONVERT_TINYINT 17 +#define ARROW_CONVERT_VARBINARY 18 +#define ARROW_CONVERT_VARCHAR 19 + +namespace { +// Return the corresponding field in SQLGetInfo's SQL_CONVERT_* field +// types for the given Arrow SqlConvert enum value. +// +// The caller is responsible for casting the result to a uint16. Note +// that -1 is returned if there's no corresponding entry. +int32_t GetInfoTypeForArrowConvertEntry(int32_t convert_entry) { + switch (convert_entry) { + case ARROW_CONVERT_BIGINT: + return SQL_CONVERT_BIGINT; + case ARROW_CONVERT_BINARY: + return SQL_CONVERT_BINARY; + case ARROW_CONVERT_BIT: + return SQL_CONVERT_BIT; + case ARROW_CONVERT_CHAR: + return SQL_CONVERT_CHAR; + case ARROW_CONVERT_DATE: + return SQL_CONVERT_DATE; + case ARROW_CONVERT_DECIMAL: + return SQL_CONVERT_DECIMAL; + case ARROW_CONVERT_FLOAT: + return SQL_CONVERT_FLOAT; + case ARROW_CONVERT_INTEGER: + return SQL_CONVERT_INTEGER; + case ARROW_CONVERT_INTERVAL_DAY_TIME: + return SQL_CONVERT_INTERVAL_DAY_TIME; + case ARROW_CONVERT_INTERVAL_YEAR_MONTH: + return SQL_CONVERT_INTERVAL_YEAR_MONTH; + case ARROW_CONVERT_LONGVARBINARY: + return SQL_CONVERT_LONGVARBINARY; + case ARROW_CONVERT_LONGVARCHAR: + return SQL_CONVERT_LONGVARCHAR; + case ARROW_CONVERT_NUMERIC: + return SQL_CONVERT_NUMERIC; + case ARROW_CONVERT_REAL: + return SQL_CONVERT_REAL; + case ARROW_CONVERT_SMALLINT: + return SQL_CONVERT_SMALLINT; + case ARROW_CONVERT_TIME: + return SQL_CONVERT_TIME; + case ARROW_CONVERT_TIMESTAMP: + return SQL_CONVERT_TIMESTAMP; + case ARROW_CONVERT_TINYINT: + return SQL_CONVERT_TINYINT; + case ARROW_CONVERT_VARBINARY: + return SQL_CONVERT_VARBINARY; + case ARROW_CONVERT_VARCHAR: + return SQL_CONVERT_VARCHAR; + } + // Arbitrarily return a negative value + return -1; +} + +// Return the corresponding bitmask to OR in SQLGetInfo's SQL_CONVERT_* field +// value for the given Arrow SqlConvert enum value. +// +// This is _not_ a bit position, it is an integer with only a single bit set. +uint32_t GetCvtBitForArrowConvertEntry(int32_t convert_entry) { + switch (convert_entry) { + case ARROW_CONVERT_BIGINT: + return SQL_CVT_BIGINT; + case ARROW_CONVERT_BINARY: + return SQL_CVT_BINARY; + case ARROW_CONVERT_BIT: + return SQL_CVT_BIT; + case ARROW_CONVERT_CHAR: + return SQL_CVT_CHAR; + case ARROW_CONVERT_DATE: + return SQL_CVT_DATE; + case ARROW_CONVERT_DECIMAL: + return SQL_CVT_DECIMAL; + case ARROW_CONVERT_FLOAT: + return SQL_CVT_FLOAT; + case ARROW_CONVERT_INTEGER: + return SQL_CVT_INTEGER; + case ARROW_CONVERT_INTERVAL_DAY_TIME: + return SQL_CVT_INTERVAL_DAY_TIME; + case ARROW_CONVERT_INTERVAL_YEAR_MONTH: + return SQL_CVT_INTERVAL_YEAR_MONTH; + case ARROW_CONVERT_LONGVARBINARY: + return SQL_CVT_LONGVARBINARY; + case ARROW_CONVERT_LONGVARCHAR: + return SQL_CVT_LONGVARCHAR; + case ARROW_CONVERT_NUMERIC: + return SQL_CVT_NUMERIC; + case ARROW_CONVERT_REAL: + return SQL_CVT_REAL; + case ARROW_CONVERT_SMALLINT: + return SQL_CVT_SMALLINT; + case ARROW_CONVERT_TIME: + return SQL_CVT_TIME; + case ARROW_CONVERT_TIMESTAMP: + return SQL_CVT_TIMESTAMP; + case ARROW_CONVERT_TINYINT: + return SQL_CVT_TINYINT; + case ARROW_CONVERT_VARBINARY: + return SQL_CVT_VARBINARY; + case ARROW_CONVERT_VARCHAR: + return SQL_CVT_VARCHAR; + } + // Return zero, which has no bits set. + return 0; +} + +inline int32_t ScalarToInt32(arrow::UnionScalar *scalar) { + return reinterpret_cast(scalar)->value; +} + +inline int64_t ScalarToInt64(arrow::UnionScalar *scalar) { + return reinterpret_cast(scalar)->value; +} + +inline std::string ScalarToBoolString(arrow::UnionScalar *scalar) { + return reinterpret_cast(scalar)->value ? "Y" : "N"; +} + +} // namespace + +namespace driver { +namespace flight_sql { +using namespace arrow::flight::sql; +using namespace arrow::flight; +using namespace driver::odbcabstraction; + +GetInfoCache::GetInfoCache(FlightCallOptions &call_options, + std::unique_ptr &client) + : call_options_(call_options), sql_client_(client), + has_server_info_(false) { + info_[SQL_DRIVER_NAME] = "Arrow Flight ODBC Driver"; + info_[SQL_DRIVER_VER] = "1.0.0"; + + info_[SQL_GETDATA_EXTENSIONS] = + static_cast(SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER); + info_[SQL_CURSOR_SENSITIVITY] = static_cast(SQL_UNSPECIFIED); + + // Properties which don't currently have SqlGetInfo fields but probably + // should. + info_[SQL_ACCESSIBLE_PROCEDURES] = "N"; + info_[SQL_COLLATION_SEQ] = ""; + info_[SQL_ALTER_TABLE] = static_cast(0); + info_[SQL_DATETIME_LITERALS] = static_cast( + SQL_DL_SQL92_DATE | SQL_DL_SQL92_TIME | SQL_DL_SQL92_TIMESTAMP); + info_[SQL_CREATE_ASSERTION] = static_cast(0); + info_[SQL_CREATE_CHARACTER_SET] = static_cast(0); + info_[SQL_CREATE_COLLATION] = static_cast(0); + info_[SQL_CREATE_DOMAIN] = static_cast(0); + info_[SQL_INDEX_KEYWORDS] = static_cast(SQL_IK_NONE); + info_[SQL_TIMEDATE_ADD_INTERVALS] = static_cast( + SQL_FN_TSI_FRAC_SECOND | SQL_FN_TSI_SECOND | SQL_FN_TSI_MINUTE | + SQL_FN_TSI_HOUR | SQL_FN_TSI_DAY | SQL_FN_TSI_WEEK | SQL_FN_TSI_MONTH | + SQL_FN_TSI_QUARTER | SQL_FN_TSI_YEAR); + info_[SQL_TIMEDATE_DIFF_INTERVALS] = static_cast( + SQL_FN_TSI_FRAC_SECOND | SQL_FN_TSI_SECOND | SQL_FN_TSI_MINUTE | + SQL_FN_TSI_HOUR | SQL_FN_TSI_DAY | SQL_FN_TSI_WEEK | SQL_FN_TSI_MONTH | + SQL_FN_TSI_QUARTER | SQL_FN_TSI_YEAR); + info_[SQL_CURSOR_COMMIT_BEHAVIOR] = static_cast(SQL_CB_CLOSE); + info_[SQL_CURSOR_ROLLBACK_BEHAVIOR] = static_cast(SQL_CB_CLOSE); + info_[SQL_CREATE_TRANSLATION] = static_cast(0); + info_[SQL_DDL_INDEX] = static_cast(0); + info_[SQL_DROP_ASSERTION] = static_cast(0); + info_[SQL_DROP_CHARACTER_SET] = static_cast(0); + info_[SQL_DROP_COLLATION] = static_cast(0); + info_[SQL_DROP_DOMAIN] = static_cast(0); + info_[SQL_DROP_TRANSLATION] = static_cast(0); + info_[SQL_DROP_VIEW] = static_cast(0); + info_[SQL_MAX_IDENTIFIER_LEN] = static_cast(65535); // arbitrary + + // Assume all aggregate functions reported in ODBC are supported. + info_[SQL_AGGREGATE_FUNCTIONS] = static_cast( + SQL_AF_ALL | SQL_AF_AVG | SQL_AF_COUNT | SQL_AF_DISTINCT | SQL_AF_MAX | + SQL_AF_MIN | SQL_AF_SUM); +} + +void GetInfoCache::SetProperty( + uint16_t property, driver::odbcabstraction::Connection::Info value) { + info_[property] = value; +} + +Connection::Info GetInfoCache::GetInfo(uint16_t info_type) { + auto it = info_.find(info_type); + + if (info_.end() == it) { + if (LoadInfoFromServer()) { + it = info_.find(info_type); + } + if (info_.end() == it) { + throw DriverException("Unknown GetInfo type: " + + std::to_string(info_type)); + } + } + return it->second; +} + +bool GetInfoCache::LoadInfoFromServer() { + if (has_server_info_.exchange(true)) { + std::unique_lock lock(mutex_); + arrow::Result> result = + sql_client_->GetSqlInfo(call_options_, {}); + ThrowIfNotOK(result.status()); + FlightStreamChunkIterator chunk_iter(*sql_client_, call_options_, + result.ValueOrDie()); + + FlightStreamChunk chunk; + bool supports_correlation_name = false; + bool requires_different_correlation_name = false; + bool transactions_supported = false; + bool transaction_ddl_commit = false; + bool transaction_ddl_ignore = false; + while (chunk_iter.GetNext(&chunk)) { + auto name_array = chunk.data->GetColumnByName("info_name"); + auto value_array = chunk.data->GetColumnByName("value"); + + arrow::UInt32Array *info_type_array = + static_cast(name_array.get()); + arrow::UnionArray *value_union_array = + static_cast(value_array.get()); + for (int64_t i = 0; i < chunk.data->num_rows(); ++i) { + if (!value_array->IsNull(i)) { + auto info_type = + static_cast( + info_type_array->Value(i)); + auto result_scalar = value_union_array->GetScalar(i); + ThrowIfNotOK(result_scalar.status()); + std::shared_ptr scalar_ptr = + result_scalar.ValueOrDie(); + arrow::UnionScalar *scalar = + reinterpret_cast(scalar_ptr.get()); + switch (info_type) { + // String properties + case SqlInfoOptions::FLIGHT_SQL_SERVER_NAME: { + std::string server_name = scalar->ToString(); + + // TODO: Consider creating different properties in GetSqlInfo. + // TODO: Investigate if SQL_SERVER_NAME should just be the host + // address as well. In JDBC, FLIGHT_SQL_SERVER_NAME is only used for + // the DatabaseProductName. + info_[SQL_SERVER_NAME] = server_name; + info_[SQL_DBMS_NAME] = server_name; + info_[SQL_DATABASE_NAME] = + server_name; // This is usually the current catalog. May need to + // throw HYC00 instead. + break; + } + case SqlInfoOptions::FLIGHT_SQL_SERVER_VERSION: { + info_[SQL_DBMS_VER] = scalar->ToString(); + break; + } + case SqlInfoOptions::FLIGHT_SQL_SERVER_ARROW_VERSION: { + // Unused. + break; + } + case SqlInfoOptions::SQL_SEARCH_STRING_ESCAPE: { + info_[SQL_SEARCH_PATTERN_ESCAPE] = scalar->ToString(); + break; + } + case ARROW_SQL_IDENTIFIER_QUOTE_CHAR: { + info_[SQL_IDENTIFIER_QUOTE_CHAR] = scalar->ToString(); + break; + } + case ARROW_SQL_KEYWORDS: { + info_[SQL_KEYWORDS] = scalar->ToString(); + break; + } + case SqlInfoOptions::SQL_EXTRA_NAME_CHARACTERS: { + info_[SQL_SPECIAL_CHARACTERS] = scalar->ToString(); + break; + } + case ARROW_SQL_SCHEMA_TERM: { + info_[SQL_SCHEMA_TERM] = scalar->ToString(); + break; + } + case ARROW_SQL_PROCEDURE_TERM: { + info_[SQL_PROCEDURE_TERM] = scalar->ToString(); + break; + } + case ARROW_SQL_CATALOG_TERM: { + info_[SQL_CATALOG_TERM] = scalar->ToString(); + + // This property implies catalogs are supported. + info_[SQL_CATALOG_NAME] = "Y"; + info_[SQL_CATALOG_NAME_SEPARATOR] = "."; + break; + } + + // Bool properties + case SqlInfoOptions::FLIGHT_SQL_SERVER_READ_ONLY: { + info_[SQL_DATA_SOURCE_READ_ONLY] = ScalarToBoolString(scalar); + + // Assume all forms of insert are supported, however this should + // come from a property. + info_[SQL_INSERT_STATEMENT] = static_cast( + SQL_IS_INSERT_LITERALS | SQL_IS_INSERT_SEARCHED | + SQL_IS_SELECT_INTO); + break; + } + case SqlInfoOptions::SQL_DDL_CATALOG: + // Unused by ODBC. + break; + case SqlInfoOptions::SQL_DDL_SCHEMA: { + bool supports_schema_ddl = + reinterpret_cast(scalar)->value; + // Note: this is a bitmask and we can't describe cascade or restrict + // flags. + info_[SQL_DROP_SCHEMA] = static_cast(SQL_DS_DROP_SCHEMA); + + // Note: this is a bitmask and we can't describe authorization or + // collation + info_[SQL_CREATE_SCHEMA] = + static_cast(SQL_CS_CREATE_SCHEMA); + break; + } + case SqlInfoOptions::SQL_DDL_TABLE: { + bool supports_table_ddl = + reinterpret_cast(scalar)->value; + // This is a bitmask and we cannot describe all clauses. + info_[SQL_CREATE_TABLE] = + static_cast(SQL_CT_CREATE_TABLE); + info_[SQL_DROP_TABLE] = static_cast(SQL_DT_DROP_TABLE); + break; + } + case SqlInfoOptions::SQL_ALL_TABLES_ARE_SELECTABLE: { + info_[SQL_ACCESSIBLE_TABLES] = ScalarToBoolString(scalar); + break; + } + case SqlInfoOptions::SQL_SUPPORTS_COLUMN_ALIASING: { + info_[SQL_COLUMN_ALIAS] = ScalarToBoolString(scalar); + break; + } + case SqlInfoOptions::SQL_NULL_PLUS_NULL_IS_NULL: { + info_[SQL_CONCAT_NULL_BEHAVIOR] = static_cast( + reinterpret_cast(scalar)->value + ? SQL_CB_NULL + : SQL_CB_NON_NULL); + break; + } + case SqlInfoOptions::SQL_SUPPORTS_TABLE_CORRELATION_NAMES: { + // Simply cache SQL_SUPPORTS_TABLE_CORRELATION_NAMES and + // SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES since we need both + // properties to determine the value for SQL_CORRELATION_NAME. + supports_correlation_name = + reinterpret_cast(scalar)->value; + break; + } + case SqlInfoOptions::SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES: { + // Simply cache SQL_SUPPORTS_TABLE_CORRELATION_NAMES and + // SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES since we need both + // properties to determine the value for SQL_CORRELATION_NAME. + requires_different_correlation_name = + reinterpret_cast(scalar)->value; + break; + } + case SqlInfoOptions::SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY: { + info_[SQL_EXPRESSIONS_IN_ORDERBY] = ScalarToBoolString(scalar); + break; + } + case SqlInfoOptions::SQL_SUPPORTS_ORDER_BY_UNRELATED: { + // Note: this is the negation of the Flight SQL property. + info_[SQL_ORDER_BY_COLUMNS_IN_SELECT] = + reinterpret_cast(scalar)->value ? "N" + : "Y"; + break; + } + case SqlInfoOptions::SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE: { + info_[SQL_LIKE_ESCAPE_CLAUSE] = ScalarToBoolString(scalar); + break; + } + case SqlInfoOptions::SQL_SUPPORTS_NON_NULLABLE_COLUMNS: { + info_[SQL_NON_NULLABLE_COLUMNS] = static_cast( + reinterpret_cast(scalar)->value + ? SQL_NNC_NON_NULL + : SQL_NNC_NULL); + break; + } + case SqlInfoOptions::SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY: { + info_[SQL_INTEGRITY] = ScalarToBoolString(scalar); + break; + } + case SqlInfoOptions::SQL_CATALOG_AT_START: { + info_[SQL_CATALOG_LOCATION] = static_cast( + reinterpret_cast(scalar)->value + ? SQL_CL_START + : SQL_CL_END); + break; + } + case SqlInfoOptions::SQL_SELECT_FOR_UPDATE_SUPPORTED: + // Not used. + break; + case SqlInfoOptions::SQL_STORED_PROCEDURES_SUPPORTED: { + info_[SQL_PROCEDURES] = ScalarToBoolString(scalar); + break; + } + case SqlInfoOptions::SQL_MAX_ROW_SIZE_INCLUDES_BLOBS: { + info_[SQL_MAX_ROW_SIZE_INCLUDES_LONG] = ScalarToBoolString(scalar); + break; + } + case SqlInfoOptions::SQL_TRANSACTIONS_SUPPORTED: { + transactions_supported = + reinterpret_cast(scalar)->value; + break; + } + case SqlInfoOptions::SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT: { + transaction_ddl_commit = + reinterpret_cast(scalar)->value; + break; + } + case SqlInfoOptions::SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED: { + transaction_ddl_ignore = + reinterpret_cast(scalar)->value; + break; + } + case SqlInfoOptions::SQL_BATCH_UPDATES_SUPPORTED: { + info_[SQL_BATCH_SUPPORT] = static_cast( + reinterpret_cast(scalar)->value + ? SQL_BS_ROW_COUNT_EXPLICIT + : 0); + break; + } + case SqlInfoOptions::SQL_SAVEPOINTS_SUPPORTED: + // Not used. + break; + case SqlInfoOptions::SQL_NAMED_PARAMETERS_SUPPORTED: + // Not used. + break; + case SqlInfoOptions::SQL_LOCATORS_UPDATE_COPY: + // Not used. + break; + case SqlInfoOptions::SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED: + // Not used. + break; + case SqlInfoOptions::SQL_CORRELATED_SUBQUERIES_SUPPORTED: + // Not used. This is implied by SQL_SUPPORTED_SUBQUERIES. + break; + + // Int64 properties + case ARROW_SQL_IDENTIFIER_CASE: { + // Missing from C++ enum. constant from Java. + constexpr int64_t LOWER = 3; + uint16_t value = 0; + int64_t sensitivity = ScalarToInt64(scalar); + switch (sensitivity) { + case SqlInfoOptions::SQL_CASE_SENSITIVITY_UNKNOWN: + value = SQL_IC_SENSITIVE; + break; + case SqlInfoOptions::SQL_CASE_SENSITIVITY_CASE_INSENSITIVE: + value = SQL_IC_MIXED; + break; + case SqlInfoOptions::SQL_CASE_SENSITIVITY_UPPERCASE: + value = SQL_IC_UPPER; + break; + case LOWER: + value = SQL_IC_LOWER; + break; + default: + value = SQL_IC_SENSITIVE; + break; + } + info_[SQL_IDENTIFIER_CASE] = value; + break; + } + case SqlInfoOptions::SQL_NULL_ORDERING: { + uint16_t value = 0; + int64_t scalar_value = ScalarToInt64(scalar); + switch (scalar_value) { + case SqlInfoOptions::SQL_NULLS_SORTED_AT_START: + value = SQL_NC_START; + break; + case SqlInfoOptions::SQL_NULLS_SORTED_AT_END: + value = SQL_NC_END; + break; + case SqlInfoOptions::SQL_NULLS_SORTED_HIGH: + value = SQL_NC_HIGH; + break; + case SqlInfoOptions::SQL_NULLS_SORTED_LOW: + default: + value = SQL_NC_LOW; + break; + } + info_[SQL_NULL_COLLATION] = value; + break; + } + case ARROW_SQL_QUOTED_IDENTIFIER_CASE: { + // Missing from C++ enum. constant from Java. + constexpr int64_t LOWER = 3; + uint16_t value = 0; + int64_t sensitivity = ScalarToInt64(scalar); + switch (sensitivity) { + case SqlInfoOptions::SQL_CASE_SENSITIVITY_UNKNOWN: + value = SQL_IC_SENSITIVE; + break; + case SqlInfoOptions::SQL_CASE_SENSITIVITY_CASE_INSENSITIVE: + value = SQL_IC_MIXED; + break; + case SqlInfoOptions::SQL_CASE_SENSITIVITY_UPPERCASE: + value = SQL_IC_UPPER; + break; + case LOWER: + value = SQL_IC_LOWER; + break; + default: + value = SQL_IC_SENSITIVE; + break; + } + info_[SQL_QUOTED_IDENTIFIER_CASE] = value; + break; + } + case SqlInfoOptions::SQL_MAX_BINARY_LITERAL_LENGTH: { + info_[SQL_MAX_BINARY_LITERAL_LEN] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_MAX_CHAR_LITERAL_LENGTH: { + info_[SQL_MAX_CHAR_LITERAL_LEN] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_MAX_COLUMN_NAME_LENGTH: { + info_[SQL_MAX_COLUMN_NAME_LEN] = + static_cast(ScalarToInt64(scalar)); + break; + } + case ARROW_SQL_MAX_COLUMNS_IN_GROUP_BY: { + info_[SQL_MAX_COLUMNS_IN_GROUP_BY] = + static_cast(ScalarToInt64(scalar)); + break; + } + case ARROW_SQL_MAX_COLUMNS_IN_INDEX: { + info_[SQL_MAX_COLUMNS_IN_INDEX] = + static_cast(ScalarToInt64(scalar)); + break; + } + case ARROW_SQL_MAX_COLUMNS_IN_ORDER_BY: { + info_[SQL_MAX_COLUMNS_IN_ORDER_BY] = + static_cast(ScalarToInt64(scalar)); + break; + } + case ARROW_SQL_MAX_COLUMNS_IN_SELECT: { + info_[SQL_MAX_COLUMNS_IN_SELECT] = + static_cast(ScalarToInt64(scalar)); + break; + } + case ARROW_SQL_MAX_COLUMNS_IN_TABLE: { + info_[SQL_MAX_COLUMNS_IN_TABLE] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_MAX_CONNECTIONS: { + info_[SQL_MAX_DRIVER_CONNECTIONS] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_MAX_CURSOR_NAME_LENGTH: { + info_[SQL_MAX_CURSOR_NAME_LEN] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_MAX_INDEX_LENGTH: { + info_[SQL_MAX_INDEX_SIZE] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_SCHEMA_NAME_LENGTH: { + info_[SQL_MAX_SCHEMA_NAME_LEN] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_MAX_PROCEDURE_NAME_LENGTH: { + info_[SQL_MAX_SCHEMA_NAME_LEN] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_MAX_CATALOG_NAME_LENGTH: { + info_[SQL_MAX_CATALOG_NAME_LEN] = + static_cast(ScalarToInt64(scalar)); + break; + } + case ARROW_SQL_MAX_ROW_SIZE: { + info_[SQL_MAX_ROW_SIZE] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_MAX_STATEMENT_LENGTH: { + info_[SQL_MAX_STATEMENT_LEN] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_MAX_STATEMENTS: { + info_[SQL_MAX_CONCURRENT_ACTIVITIES] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_MAX_TABLE_NAME_LENGTH: { + info_[SQL_MAX_TABLE_NAME_LEN] = + static_cast(ScalarToInt64(scalar)); + break; + } + case ARROW_SQL_MAX_TABLES_IN_SELECT: { + info_[SQL_MAX_TABLES_IN_SELECT] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_MAX_USERNAME_LENGTH: { + info_[SQL_MAX_USER_NAME_LEN] = + static_cast(ScalarToInt64(scalar)); + break; + } + case SqlInfoOptions::SQL_DEFAULT_TRANSACTION_ISOLATION: { + constexpr int32_t NONE = 0; + constexpr int32_t READ_UNCOMMITTED = 1; + constexpr int32_t READ_COMMITTED = 2; + constexpr int32_t REPEATABLE_READ = 3; + constexpr int32_t SERIALIZABLE = 4; + int64_t scalar_value = static_cast(ScalarToInt64(scalar)); + uint32_t result = 0; + if ((scalar_value & (1 << READ_UNCOMMITTED)) != 0) { + result = SQL_TXN_READ_UNCOMMITTED; + } else if ((scalar_value & (1 << READ_COMMITTED)) != 0) { + result = SQL_TXN_READ_COMMITTED; + } else if ((scalar_value & (1 << REPEATABLE_READ)) != 0) { + result = SQL_TXN_REPEATABLE_READ; + } else if ((scalar_value & (1 << SERIALIZABLE)) != 0) { + result = SQL_TXN_SERIALIZABLE; + } + info_[SQL_DEFAULT_TXN_ISOLATION] = result; + break; + } + + // Int32 properties + case SqlInfoOptions::SQL_SUPPORTED_GROUP_BY: { + // Note: SqlGroupBy enum is missing in C++. Using Java values. + constexpr int32_t UNRELATED = 0; + constexpr int32_t BEYOND_SELECT = 1; + int32_t scalar_value = static_cast(ScalarToInt32(scalar)); + uint16_t result = SQL_GB_NOT_SUPPORTED; + if ((scalar_value & (1 << UNRELATED)) != 0) { + result = SQL_GB_NO_RELATION; + } else if ((scalar_value & (1 << BEYOND_SELECT)) != 0) { + result = SQL_GB_GROUP_BY_CONTAINS_SELECT; + } + // Note GROUP_BY_EQUALS_SELECT and COLLATE cannot be described. + info_[SQL_GROUP_BY] = result; + break; + } + case SqlInfoOptions::SQL_SUPPORTED_GRAMMAR: { + // Note: SupportedSqlGrammar enum is missing in C++. Using Java + // values. + constexpr int32_t MINIMUM = 0; + constexpr int32_t CORE = 1; + constexpr int32_t EXTENDED = 2; + int32_t scalar_value = static_cast(ScalarToInt32(scalar)); + uint32_t result = SQL_OIC_CORE; + if ((scalar_value & (1 << MINIMUM)) != 0) { + result = SQL_OIC_CORE; + } else if ((scalar_value & (1 << CORE)) != 0) { + result = SQL_OIC_LEVEL1; + } else if ((scalar_value & (1 << EXTENDED)) != 0) { + result = SQL_OIC_LEVEL2; + } + info_[SQL_ODBC_API_CONFORMANCE] = result; + break; + } + case SqlInfoOptions::SQL_ANSI92_SUPPORTED_LEVEL: { + // Note: SupportedAnsi92SqlGrammarLevel enum is missing in C++. + // Using Java values. + constexpr int32_t ENTRY = 0; + constexpr int32_t INTERMEDIATE = 1; + constexpr int32_t FULL = 2; + int32_t scalar_value = static_cast(ScalarToInt32(scalar)); + uint32_t result = SQL_SC_SQL92_ENTRY; + uint16_t odbc_sql_conformance = SQL_OSC_MINIMUM; + if ((scalar_value & (1 << ENTRY)) != 0) { + result = SQL_SC_SQL92_ENTRY; + } else if ((scalar_value & (1 << INTERMEDIATE)) != 0) { + result = SQL_SC_SQL92_INTERMEDIATE; + odbc_sql_conformance = SQL_OSC_CORE; + } else if ((scalar_value & (1 << FULL)) != 0) { + result = SQL_SC_SQL92_FULL; + odbc_sql_conformance = SQL_OSC_EXTENDED; + } + info_[SQL_SQL_CONFORMANCE] = result; + info_[SQL_ODBC_SQL_CONFORMANCE] = odbc_sql_conformance; + break; + } + case SqlInfoOptions::SQL_OUTER_JOINS_SUPPORT_LEVEL: { + int32_t scalar_value = static_cast(ScalarToInt32(scalar)); + + // If limited outer joins is supported, we can't tell which joins + // are supported so just report none. If full outer joins is + // supported, nested joins are supported and full outer joins are + // supported, so all joins + nested are supported. + constexpr int32_t UNSUPPORTED = 0; + constexpr int32_t LIMITED = 1; + constexpr int32_t FULL = 2; + uint32_t result = 0; + // Assume inner and cross joins are supported. Flight SQL can't + // report this currently. + uint32_t relational_operators = + SQL_SRJO_CROSS_JOIN | SQL_SRJO_INNER_JOIN; + if ((scalar_value & (1 << FULL)) != 0) { + result = SQL_OJ_LEFT | SQL_OJ_RIGHT | SQL_OJ_FULL | SQL_OJ_NESTED; + relational_operators |= SQL_SRJO_FULL_OUTER_JOIN | + SQL_SRJO_LEFT_OUTER_JOIN | + SQL_SRJO_RIGHT_OUTER_JOIN; + } else if ((scalar_value & (1 << LIMITED)) != 0) { + result = SQL_SC_SQL92_INTERMEDIATE; + } else if ((scalar_value & (1 << UNSUPPORTED)) != 0) { + result = 0; + } + info_[SQL_OJ_CAPABILITIES] = result; + info_[SQL_OUTER_JOINS] = result != 0 ? "Y" : "N"; + info_[SQL_SQL92_RELATIONAL_JOIN_OPERATORS] = relational_operators; + break; + } + case SqlInfoOptions::SQL_SCHEMAS_SUPPORTED_ACTIONS: { + int32_t scalar_value = static_cast(ScalarToInt32(scalar)); + + // Missing SqlSupportedElementActions enum in C++. Values taken from + // java. + constexpr int32_t PROCEDURE = 0; + constexpr int32_t INDEX = 1; + constexpr int32_t PRIVILEGE = 2; + // Assume schemas are supported in DML and Table manipulation. + uint32_t result = SQL_SU_DML_STATEMENTS | SQL_SU_TABLE_DEFINITION; + if ((scalar_value & (1 << PROCEDURE)) != 0) { + result |= SQL_SU_PROCEDURE_INVOCATION; + } + if ((scalar_value & (1 << INDEX)) != 0) { + result |= SQL_SU_INDEX_DEFINITION; + } + if ((scalar_value & (1 << PRIVILEGE)) != 0) { + result |= SQL_SU_PRIVILEGE_DEFINITION; + } + info_[SQL_SCHEMA_USAGE] = result; + break; + } + case SqlInfoOptions::SQL_CATALOGS_SUPPORTED_ACTIONS: { + int32_t scalar_value = static_cast(ScalarToInt32(scalar)); + + // Missing SqlSupportedElementActions enum in C++. Values taken from + // java. + constexpr int32_t PROCEDURE = 0; + constexpr int32_t INDEX = 1; + constexpr int32_t PRIVILEGE = 2; + // Assume catalogs are supported in DML and Table manipulation. + uint32_t result = SQL_CU_DML_STATEMENTS | SQL_CU_TABLE_DEFINITION; + if ((scalar_value & (1 << PROCEDURE)) != 0) { + result |= SQL_CU_PROCEDURE_INVOCATION; + } + if ((scalar_value & (1 << INDEX)) != 0) { + result |= SQL_CU_INDEX_DEFINITION; + } + if ((scalar_value & (1 << PRIVILEGE)) != 0) { + result |= SQL_CU_PRIVILEGE_DEFINITION; + } + info_[SQL_CATALOG_USAGE] = result; + break; + } + case SqlInfoOptions::SQL_SUPPORTED_POSITIONED_COMMANDS: { + // Ignore, positioned updates/deletes unsupported. + break; + } + case SqlInfoOptions::SQL_SUPPORTED_SUBQUERIES: { + int32_t scalar_value = static_cast(ScalarToInt32(scalar)); + + // Missing SqlSupportedElementActions enum in C++. Values taken from + // java. + constexpr int32_t COMPARISONS = 0; + constexpr int32_t EXISTS = 1; + constexpr int32_t IN = 2; + constexpr int32_t QUANTIFIEDS = 3; + uint32_t result = 0; + if ((scalar_value & (1 << COMPARISONS)) != 0) { + result |= SQL_SQ_COMPARISON; + } + if ((scalar_value & (1 << EXISTS)) != 0) { + result |= SQL_SQ_EXISTS; + } + if ((scalar_value & (1 << IN)) != 0) { + result |= SQL_SQ_IN; + } + if ((scalar_value & (1 << QUANTIFIEDS)) != 0) { + result |= SQL_SQ_QUANTIFIED; + } + info_[SQL_SUBQUERIES] = result; + break; + } + case SqlInfoOptions::SQL_SUPPORTED_UNIONS: { + int32_t scalar_value = static_cast(ScalarToInt32(scalar)); + + // Missing enum in C++. Values taken from java. + constexpr int32_t UNION = 0; + constexpr int32_t UNION_ALL = 1; + uint32_t result = 0; + if ((scalar_value & (1 << UNION)) != 0) { + result |= SQL_U_UNION; + } + if ((scalar_value & (1 << UNION_ALL)) != 0) { + result |= SQL_U_UNION_ALL; + } + info_[SQL_UNION] = result; + break; + } + case SqlInfoOptions::SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS: { + int32_t scalar_value = static_cast(ScalarToInt32(scalar)); + + // Missing enum in C++. Values taken from java. + constexpr int32_t NONE = 0; + constexpr int32_t READ_UNCOMMITTED = 1; + constexpr int32_t READ_COMMITTED = 2; + constexpr int32_t REPEATABLE_READ = 3; + constexpr int32_t SERIALIZABLE = 4; + uint32_t result = 0; + if ((scalar_value & (1 << NONE)) != 0) { + result = 0; + } + if ((scalar_value & (1 << READ_UNCOMMITTED)) != 0) { + result |= SQL_TXN_READ_UNCOMMITTED; + } + if ((scalar_value & (1 << READ_COMMITTED)) != 0) { + result |= SQL_TXN_READ_COMMITTED; + } + if ((scalar_value & (1 << REPEATABLE_READ)) != 0) { + result |= SQL_TXN_REPEATABLE_READ; + } + if ((scalar_value & (1 << SERIALIZABLE)) != 0) { + result |= SQL_TXN_SERIALIZABLE; + } + info_[SQL_TXN_ISOLATION_OPTION] = result; + break; + } + case SqlInfoOptions::SQL_SUPPORTED_RESULT_SET_TYPES: + // Ignored. Warpdrive supports forward-only only. + break; + case SqlInfoOptions:: + SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED: + // Ignored. Warpdrive supports forward-only only. + break; + case SqlInfoOptions:: + SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY: + // Ignored. Warpdrive supports forward-only only. + break; + case SqlInfoOptions:: + SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE: + // Ignored. Warpdrive supports forward-only only. + break; + case SqlInfoOptions:: + SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE: + // Ignored. Warpdrive supports forward-only only. + break; + + // List properties + case ARROW_SQL_NUMERIC_FUNCTIONS: { + std::shared_ptr list_value = + reinterpret_cast(scalar)->value; + uint32_t result = 0; + for (int64_t list_index = 0; list_index < list_value->length(); + ++list_index) { + if (!list_value->IsNull(list_index)) { + ReportNumericFunction( + reinterpret_cast(list_value.get()) + ->GetString(list_index), + result); + } + } + info_[SQL_NUMERIC_FUNCTIONS] = result; + break; + } + + case ARROW_SQL_STRING_FUNCTIONS: { + std::shared_ptr list_value = + reinterpret_cast(scalar)->value; + uint32_t result = 0; + for (int64_t list_index = 0; list_index < list_value->length(); + ++list_index) { + if (!list_value->IsNull(list_index)) { + ReportStringFunction( + reinterpret_cast(list_value.get()) + ->GetString(list_index), + result); + } + } + info_[SQL_STRING_FUNCTIONS] = result; + break; + } + case ARROW_SQL_SYSTEM_FUNCTIONS: { + std::shared_ptr list_value = + reinterpret_cast(scalar)->value; + uint32_t sys_result = 0; + uint32_t convert_result = 0; + for (int64_t list_index = 0; list_index < list_value->length(); + ++list_index) { + if (!list_value->IsNull(list_index)) { + ReportSystemFunction( + reinterpret_cast(list_value.get()) + ->GetString(list_index), + sys_result, convert_result); + } + } + info_[SQL_CONVERT_FUNCTIONS] = convert_result; + info_[SQL_SYSTEM_FUNCTIONS] = sys_result; + break; + } + case SqlInfoOptions::SQL_DATETIME_FUNCTIONS: { + std::shared_ptr list_value = + reinterpret_cast(scalar)->value; + uint32_t result = 0; + for (int64_t list_index = 0; list_index < list_value->length(); + ++list_index) { + if (!list_value->IsNull(list_index)) { + ReportDatetimeFunction( + reinterpret_cast(list_value.get()) + ->GetString(list_index), + result); + } + } + info_[SQL_TIMEDATE_FUNCTIONS] = result; + break; + } + + // Map properties + case SqlInfoOptions::SQL_SUPPORTS_CONVERT: { + arrow::MapScalar *map_scalar = + reinterpret_cast(scalar); + auto data_array = map_scalar->value; + arrow::StructArray *map_contents = + reinterpret_cast(data_array.get()); + auto map_keys = map_contents->field(0); + auto map_values = map_contents->field(1); + for (int64_t map_index = 0; map_index < map_contents->length(); + ++map_index) { + if (!map_values->IsNull(map_index)) { + auto map_key_scalar_ptr = + map_keys->GetScalar(map_index).ValueOrDie(); + auto map_value_scalar_ptr = + map_values->GetScalar(map_index).ValueOrDie(); + int32_t map_key_scalar = reinterpret_cast( + map_key_scalar_ptr.get()) + ->value; + auto map_value_scalar = + reinterpret_cast( + map_value_scalar_ptr.get()) + ->value; + + int32_t info_type = + GetInfoTypeForArrowConvertEntry(map_key_scalar); + if (info_type < 0) { + continue; + } + uint32_t info_to_write = 0; + for (int64_t map_value_array_index = 0; + map_value_array_index < map_value_scalar->length(); + ++map_value_array_index) { + if (!map_value_scalar->IsNull(map_value_array_index)) { + auto list_entry_scalar = + map_value_scalar->GetScalar(map_value_array_index) + .ValueOrDie(); + info_to_write |= GetCvtBitForArrowConvertEntry( + reinterpret_cast( + list_entry_scalar.get()) + ->value); + } + } + info_[info_type] = info_to_write; + } + } + break; + } + + default: + // Ignore unrecognized. + break; + } + } + } + + if (transactions_supported) { + if (transaction_ddl_commit) { + info_[SQL_TXN_CAPABLE] = static_cast(SQL_TC_DDL_COMMIT); + } else if (transaction_ddl_ignore) { + info_[SQL_TXN_CAPABLE] = static_cast(SQL_TC_DDL_IGNORE); + } else { + // Ambiguous if this means transactions on DDL is supported or not. + // Assume not + info_[SQL_TXN_CAPABLE] = static_cast(SQL_TC_DML); + } + } else { + info_[SQL_TXN_CAPABLE] = static_cast(SQL_TC_NONE); + } + + if (supports_correlation_name) { + if (requires_different_correlation_name) { + info_[SQL_CORRELATION_NAME] = static_cast(SQL_CN_DIFFERENT); + } else { + info_[SQL_CORRELATION_NAME] = static_cast(SQL_CN_ANY); + } + } else { + info_[SQL_CORRELATION_NAME] = static_cast(SQL_CN_NONE); + } + } + } + + return false; +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h new file mode 100644 index 0000000000000..e72d8e83c7eb2 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h @@ -0,0 +1,58 @@ +// 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. + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace arrow { +namespace flight { +namespace sql { +class FlightSqlClient; +} +} // namespace flight +} // namespace arrow + +namespace driver { +namespace flight_sql { + +class GetInfoCache { + +private: + std::map info_; + arrow::flight::FlightCallOptions &call_options_; + std::unique_ptr &sql_client_; + std::mutex mutex_; + std::atomic has_server_info_; + +public: + GetInfoCache(arrow::flight::FlightCallOptions &call_options, + std::unique_ptr &client); + void SetProperty(uint16_t property, + driver::odbcabstraction::Connection::Info value); + driver::odbcabstraction::Connection::Info GetInfo(uint16_t info_type); + +private: + bool LoadInfoFromServer(); +}; +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.cc new file mode 100644 index 0000000000000..09827ad5a8ff8 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.cc @@ -0,0 +1,142 @@ +// 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 "scalar_function_reporter.h" + +#include +#include +#include + +namespace driver { +namespace flight_sql { + +// The list of functions that can be converted from string to ODBC bitmasks is +// based on Calcite's SqlJdbcFunctionCall class. + +namespace { +static const std::unordered_map numeric_functions = { + {"ABS", SQL_FN_NUM_ABS}, {"ACOS", SQL_FN_NUM_ACOS}, + {"ASIN", SQL_FN_NUM_ASIN}, {"ATAN", SQL_FN_NUM_ATAN}, + {"ATAN2", SQL_FN_NUM_ATAN2}, {"CEILING", SQL_FN_NUM_CEILING}, + {"COS", SQL_FN_NUM_ACOS}, {"COT", SQL_FN_NUM_COT}, + {"DEGREES", SQL_FN_NUM_DEGREES}, {"EXP", SQL_FN_NUM_EXP}, + {"FLOOR", SQL_FN_NUM_FLOOR}, {"LOG", SQL_FN_NUM_LOG}, + {"LOG10", SQL_FN_NUM_LOG10}, {"MOD", SQL_FN_NUM_MOD}, + {"PI", SQL_FN_NUM_PI}, {"POWER", SQL_FN_NUM_POWER}, + {"RADIANS", SQL_FN_NUM_RADIANS}, {"RAND", SQL_FN_NUM_RAND}, + {"ROUND", SQL_FN_NUM_ROUND}, {"SIGN", SQL_FN_NUM_SIGN}, + {"SIN", SQL_FN_NUM_SIN}, {"SQRT", SQL_FN_NUM_SQRT}, + {"TAN", SQL_FN_NUM_TAN}, {"TRUNCATE", SQL_FN_NUM_TRUNCATE}}; + +static const std::unordered_map system_functions = { + {"DATABASE", SQL_FN_SYS_DBNAME}, + {"IFNULL", SQL_FN_SYS_IFNULL}, + {"USER", SQL_FN_SYS_USERNAME}}; + +static const std::unordered_map datetime_functions = { + {"CURDATE", SQL_FN_TD_CURDATE}, + {"CURTIME", SQL_FN_TD_CURTIME}, + {"DAYNAME", SQL_FN_TD_DAYNAME}, + {"DAYOFMONTH", SQL_FN_TD_DAYOFMONTH}, + {"DAYOFWEEK", SQL_FN_TD_DAYOFWEEK}, + {"DAYOFYEAR", SQL_FN_TD_DAYOFYEAR}, + {"HOUR", SQL_FN_TD_HOUR}, + {"MINUTE", SQL_FN_TD_MINUTE}, + {"MONTH", SQL_FN_TD_MONTH}, + {"MONTHNAME", SQL_FN_TD_MONTHNAME}, + {"NOW", SQL_FN_TD_NOW}, + {"QUARTER", SQL_FN_TD_QUARTER}, + {"SECOND", SQL_FN_TD_SECOND}, + {"TIMESTAMPADD", SQL_FN_TD_TIMESTAMPADD}, + {"TIMESTAMPDIFF", SQL_FN_TD_TIMESTAMPDIFF}, + {"WEEK", SQL_FN_TD_WEEK}, + {"YEAR", SQL_FN_TD_YEAR}, + // Additional functions in ODBC but not Calcite: + {"CURRENT_DATE", SQL_FN_TD_CURRENT_DATE}, + {"CURRENT_TIME", SQL_FN_TD_CURRENT_TIME}, + {"CURRENT_TIMESTAMP", SQL_FN_TD_CURRENT_TIMESTAMP}, + {"EXTRACT", SQL_FN_TD_EXTRACT}}; + +static const std::unordered_map string_functions = { + {"ASCII", SQL_FN_STR_ASCII}, + {"CHAR", SQL_FN_STR_CHAR}, + {"CONCAT", SQL_FN_STR_CONCAT}, + {"DIFFERENCE", SQL_FN_STR_DIFFERENCE}, + {"INSERT", SQL_FN_STR_INSERT}, + {"LCASE", SQL_FN_STR_LCASE}, + {"LEFT", SQL_FN_STR_LEFT}, + {"LENGTH", SQL_FN_STR_LENGTH}, + {"LOCATE", SQL_FN_STR_LOCATE}, + {"LTRIM", SQL_FN_STR_LTRIM}, + {"REPEAT", SQL_FN_STR_REPEAT}, + {"REPLACE", SQL_FN_STR_REPLACE}, + {"RIGHT", SQL_FN_STR_RIGHT}, + {"RTRIM", SQL_FN_STR_RTRIM}, + {"SOUNDEX", SQL_FN_STR_SOUNDEX}, + {"SPACE", SQL_FN_STR_SPACE}, + {"SUBSTRING", SQL_FN_STR_SUBSTRING}, + {"UCASE", SQL_FN_STR_UCASE}, + // Additional functions in ODBC but not Calcite: + {"LOCATE_2", SQL_FN_STR_LOCATE_2}, + {"BIT_LENGTH", SQL_FN_STR_BIT_LENGTH}, + {"CHAR_LENGTH", SQL_FN_STR_CHAR_LENGTH}, + {"CHARACTER_LENGTH", SQL_FN_STR_CHARACTER_LENGTH}, + {"OCTET_LENGTH", SQL_FN_STR_OCTET_LENGTH}, + {"POSTION", SQL_FN_STR_POSITION}, + {"SOUNDEX", SQL_FN_STR_SOUNDEX}}; +} // namespace + +void ReportSystemFunction(const std::string &function, + uint32_t ¤t_sys_functions, + uint32_t ¤t_convert_functions) { + const auto &result = system_functions.find(function); + if (result != system_functions.end()) { + current_sys_functions |= result->second; + } else if (function == "CONVERT") { + // CAST and CONVERT are system functions from FlightSql/Calcite, but are + // CONVERT functions in ODBC. Assume that if CONVERT is reported as a system + // function, then CAST and CONVERT are both supported. + current_convert_functions |= SQL_FN_CVT_CONVERT | SQL_FN_CVT_CAST; + } +} + +void ReportNumericFunction(const std::string &function, + uint32_t ¤t_functions) { + const auto &result = numeric_functions.find(function); + if (result != numeric_functions.end()) { + current_functions |= result->second; + } +} + +void ReportStringFunction(const std::string &function, + uint32_t ¤t_functions) { + const auto &result = string_functions.find(function); + if (result != string_functions.end()) { + current_functions |= result->second; + } +} + +void ReportDatetimeFunction(const std::string &function, + uint32_t ¤t_functions) { + const auto &result = datetime_functions.find(function); + if (result != datetime_functions.end()) { + current_functions |= result->second; + } +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.h new file mode 100644 index 0000000000000..9e31536188f4e --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.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. + +#pragma once + +#include + +namespace driver { +namespace flight_sql { + +void ReportSystemFunction(const std::string &function, + uint32_t ¤t_sys_functions, + uint32_t ¤t_convert_functions); +void ReportNumericFunction(const std::string &function, + uint32_t ¤t_functions); +void ReportStringFunction(const std::string &function, + uint32_t ¤t_functions); +void ReportDatetimeFunction(const std::string &function, + uint32_t ¤t_functions); + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index 8bc57a0611ce1..7f78781de6e24 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -62,7 +62,7 @@ class Connection { typedef boost::variant Attribute; typedef std::string Property; - typedef boost::variant Info; + typedef boost::variant Info; // ConnPropertyMap is case-insensitive for keys. typedef std::map ConnPropertyMap; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h index 9d23e77980b5e..ae152a320a135 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h @@ -15,12 +15,12 @@ // specific language governing permissions and limitations // under the License. +#pragma once + #include #include -#pragma once - namespace driver { namespace odbcabstraction { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h index f6e722bd84f71..a6f35a4d8f236 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h @@ -15,13 +15,13 @@ // specific language governing permissions and limitations // under the License. +#pragma once + #include #include #include -#pragma once - namespace driver { namespace odbcabstraction { From 9825e1e967c95f489089e405b35a75ba87508a54 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Wed, 9 Mar 2022 14:31:32 -0300 Subject: [PATCH 073/183] Implement GetTables on FlightSqlStatement It contains: - The implementaion of the GetTablesV2 and GetTablesV3, covering all the special cases when passing SQL_ALL_ arguments; - A parser for the table types when a string with values separated by comma are transformed correctly into a std::vector, which is required by flight-sql - The conversion for the correct columns names required to ODBC v2 and V3 Change-Id: Iaf1b0ecdcfa58ca1a1e311296edbced6019eaaa3 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 2 + .../flight_sql/flight_sql_result_set.cc | 25 ++- .../flight_sql/flight_sql_result_set.h | 19 +- .../flight_sql_result_set_metadata.cc | 18 +- .../flight_sql_result_set_metadata.h | 6 +- .../flight_sql/flight_sql_statement.cc | 88 ++++++--- .../flight_sql/flight_sql_statement.h | 8 +- .../flight_sql_statement_get_tables.cc | 185 ++++++++++++++++++ .../flight_sql_statement_get_tables.h | 63 ++++++ .../flightsql-odbc/flight_sql/main.cc | 26 ++- .../flight_sql/parse_table_types_test.cc | 53 +++++ .../flight_sql/record_batch_transformer.cc | 100 ++++++---- .../flight_sql/record_batch_transformer.h | 90 ++++----- .../record_batch_transformer_test.cc | 30 +-- 14 files changed, 565 insertions(+), 148 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/parse_table_types_test.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 06c0f305c3c9e..ea07af7552362 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -100,6 +100,7 @@ set(ARROW_ODBC_SPI_SOURCES flight_sql_result_set_column.cc flight_sql_result_set_metadata.cc flight_sql_statement.cc + flight_sql_statement_get_tables.cc flight_sql_stream_chunk_iterator.cc get_info_cache.cc record_batch_transformer.cc @@ -147,6 +148,7 @@ set(ARROW_ODBC_SPI_TEST_SOURCES accessors/primitive_array_accessor_test.cc accessors/string_array_accessor_test.cc flight_sql_connection_test.cc + parse_table_types_test.cc record_batch_transformer_test.cc ) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index 150f1ed091e2a..996f41ba94dba 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -40,14 +40,18 @@ using odbcabstraction::CDataType; using odbcabstraction::DriverException; FlightSqlResultSet::FlightSqlResultSet( - std::shared_ptr metadata, FlightSqlClient &flight_sql_client, const arrow::flight::FlightCallOptions &call_options, - const std::shared_ptr &flight_info) - : metadata_(std::move(metadata)), columns_(metadata->GetColumnCount()), - get_data_offsets_(metadata->GetColumnCount()), current_row_(0), - num_binding_(0), - chunk_iterator_(flight_sql_client, call_options, flight_info) { + const std::shared_ptr &flight_info, + const std::shared_ptr &transformer) + : num_binding_(0), current_row_(0), + chunk_iterator_(flight_sql_client, call_options, flight_info), + transformer_(transformer), + metadata_(transformer ? new FlightSqlResultSetMetadata( + transformer->GetTransformedSchema()) + : new FlightSqlResultSetMetadata(flight_info)), + columns_(metadata_->GetColumnCount()), + get_data_offsets_(metadata_->GetColumnCount()) { current_chunk_.data = nullptr; for (int i = 0; i < columns_.size(); ++i) { @@ -65,6 +69,10 @@ size_t FlightSqlResultSet::Move(size_t rows) { if (!chunk_iterator_.GetNext(¤t_chunk_)) { return 0; } + + if (transformer_) { + current_chunk_.data = transformer_->Transform(current_chunk_.data); + } } // Reset GetData value offsets. @@ -83,6 +91,11 @@ size_t FlightSqlResultSet::Move(size_t rows) { if (!chunk_iterator_.GetNext(¤t_chunk_)) { break; } + + if (transformer_) { + current_chunk_.data = transformer_->Transform(current_chunk_.data); + } + for (auto &column : columns_) { column.ResetAccessor(); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index cae171f6c7c84..77dbbb758b215 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -19,6 +19,7 @@ #include "flight_sql_result_set_accessors.h" #include "flight_sql_stream_chunk_iterator.h" +#include "record_batch_transformer.h" #include "utils.h" #include #include @@ -50,24 +51,24 @@ class FlightSqlResultSetColumn; class FlightSqlResultSet : public ResultSet { private: - std::vector columns_; - std::vector get_data_offsets_; - int num_binding_; - std::shared_ptr metadata_; - int64_t current_row_; FlightStreamChunkIterator chunk_iterator_; FlightStreamChunk current_chunk_; std::shared_ptr schema_; + std::shared_ptr transformer_; + std::shared_ptr metadata_; + std::vector columns_; + std::vector get_data_offsets_; public: ~FlightSqlResultSet() override; - FlightSqlResultSet(std::shared_ptr metadata, - FlightSqlClient &flight_sql_client, - const arrow::flight::FlightCallOptions &call_options, - const std::shared_ptr &flight_info); + FlightSqlResultSet( + FlightSqlClient &flight_sql_client, + const arrow::flight::FlightCallOptions &call_options, + const std::shared_ptr &flight_info, + const std::shared_ptr &transformer); void Close() override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index b4d258acbbde0..41cbce86f776c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -17,6 +17,7 @@ #include "flight_sql_result_set_metadata.h" #include "arrow/util/key_value_metadata.h" +#include "utils.h" #include #include @@ -29,16 +30,16 @@ using arrow::DataType; using arrow::Field; size_t FlightSqlResultSetMetadata::GetColumnCount() { - return schema->num_fields(); + return schema_->num_fields(); } std::string FlightSqlResultSetMetadata::GetColumnName(int column_position) { - return schema->field(column_position - 1)->name(); + return schema_->field(column_position - 1)->name(); } std::string FlightSqlResultSetMetadata::GetName(int column_position) { // TODO Get column alias from column metadata - return schema->field(column_position - 1)->name(); + return schema_->field(column_position - 1)->name(); } size_t FlightSqlResultSetMetadata::GetPrecision(int column_position) { @@ -52,7 +53,7 @@ size_t FlightSqlResultSetMetadata::GetScale(int column_position) { } SqlDataType FlightSqlResultSetMetadata::GetDataType(int column_position) { - const std::shared_ptr &field = schema->field(column_position - 1); + const std::shared_ptr &field = schema_->field(column_position - 1); const std::shared_ptr &type = field->type(); switch (type->id()) { @@ -233,7 +234,14 @@ bool FlightSqlResultSetMetadata::IsFixedPrecScale(int column_position) { FlightSqlResultSetMetadata::FlightSqlResultSetMetadata( std::shared_ptr schema) - : schema(std::move(schema)) {} + : schema_(std::move(schema)) {} + +FlightSqlResultSetMetadata::FlightSqlResultSetMetadata( + const std::shared_ptr &flight_info) { + arrow::ipc::DictionaryMemo dict_memo; + + ThrowIfNotOK(flight_info->GetSchema(&dict_memo, &schema_)); +} } // namespace flight_sql } // namespace driver \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h index 8ee5d265f529d..d851baefb49eb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include @@ -24,9 +25,12 @@ namespace driver { namespace flight_sql { class FlightSqlResultSetMetadata : public odbcabstraction::ResultSetMetadata { private: - std::shared_ptr schema; + std::shared_ptr schema_; public: + explicit FlightSqlResultSetMetadata( + const std::shared_ptr &flight_info); + explicit FlightSqlResultSetMetadata(std::shared_ptr schema); size_t GetColumnCount() override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index 8ff32ffb84ab3..8ad1507e26c11 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -18,7 +18,10 @@ #include "flight_sql_statement.h" #include "flight_sql_result_set.h" #include "flight_sql_result_set_metadata.h" +#include "flight_sql_statement_get_tables.h" +#include "record_batch_transformer.h" #include "utils.h" +#include #include #include @@ -35,21 +38,23 @@ using arrow::flight::Location; using arrow::flight::TimeoutDuration; using arrow::flight::sql::FlightSqlClient; using arrow::flight::sql::PreparedStatement; +using arrow::flight::sql::SqlSchema; using driver::odbcabstraction::DriverException; using driver::odbcabstraction::ResultSet; using driver::odbcabstraction::ResultSetMetadata; using driver::odbcabstraction::Statement; namespace { -std::shared_ptr -CreateResultSetMetaData(const std::shared_ptr &flight_info) { - std::shared_ptr schema; - arrow::ipc::DictionaryMemo dict_memo; - ThrowIfNotOK(flight_info->GetSchema(&dict_memo, &schema)); - - return std::make_shared(schema); +void ClosePreparedStatementIfAny( + std::shared_ptr + &prepared_statement) { + if (prepared_statement != nullptr) { + ThrowIfNotOK(prepared_statement->Close()); + prepared_statement.reset(); + } } + } // namespace FlightSqlStatement::FlightSqlStatement(FlightSqlClient &sql_client, @@ -69,10 +74,7 @@ FlightSqlStatement::GetAttribute(StatementAttributeId attribute) { boost::optional> FlightSqlStatement::Prepare(const std::string &query) { - if (prepared_statement_.get() != nullptr) { - ThrowIfNotOK(prepared_statement_->Close()); - prepared_statement_.reset(); - } + ClosePreparedStatementIfAny(prepared_statement_); Result> result = sql_client_.Prepare(call_options_, query); @@ -93,28 +95,21 @@ bool FlightSqlStatement::ExecutePrepared() { Result> result = prepared_statement_->Execute(); ThrowIfNotOK(result.status()); - current_result_set_metadata_ = CreateResultSetMetaData(result.ValueOrDie()); current_result_set_ = std::make_shared( - current_result_set_metadata_, sql_client_, call_options_, - result.ValueOrDie()); + sql_client_, call_options_, result.ValueOrDie(), nullptr); return true; } bool FlightSqlStatement::Execute(const std::string &query) { - if (prepared_statement_ != nullptr) { - ThrowIfNotOK(prepared_statement_->Close()); - prepared_statement_.reset(); - } + ClosePreparedStatementIfAny(prepared_statement_); Result> result = sql_client_.Execute(call_options_, query); ThrowIfNotOK(result.status()); - current_result_set_metadata_ = CreateResultSetMetaData(result.ValueOrDie()); current_result_set_ = std::make_shared( - current_result_set_metadata_, sql_client_, call_options_, - result.ValueOrDie()); + sql_client_, call_options_, result.ValueOrDie(), nullptr); return true; } @@ -125,16 +120,63 @@ std::shared_ptr FlightSqlStatement::GetResultSet() { long FlightSqlStatement::GetUpdateCount() { return -1; } +std::shared_ptr FlightSqlStatement::GetTables( + const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, const std::string *table_type, + const ColumnNames &column_names) { + ClosePreparedStatementIfAny(prepared_statement_); + + std::vector table_types; + + if ((catalog_name && *catalog_name == "%") && + (schema_name && schema_name->empty()) && + (table_name && table_name->empty()) && + (table_type && table_type->empty())) { + current_result_set_ = + GetTablesForSQLAllCatalogs(column_names, call_options_, sql_client_); + } else if ((catalog_name && catalog_name->empty()) && + (schema_name && *schema_name == "%") && + (table_name && table_name->empty()) && + (table_type && table_type->empty())) { + current_result_set_ = GetTablesForSQLAllDbSchemas( + column_names, call_options_, sql_client_, schema_name); + } else if ((catalog_name && catalog_name->empty()) && + (schema_name && schema_name->empty()) && + (table_name && table_name->empty()) && + (table_type && *table_type == "%")) { + current_result_set_ = + GetTablesForSQLAllTableTypes(column_names, call_options_, sql_client_); + } else { + if (table_type) { + ParseTableTypes(*table_type, table_types); + } + + current_result_set_ = GetTablesForGenericUse( + column_names, call_options_, sql_client_, catalog_name, schema_name, + table_name, table_types); + } + + return current_result_set_; +} + std::shared_ptr FlightSqlStatement::GetTables_V2( const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *table_type) { - return current_result_set_; + ColumnNames column_names{"TABLE_QUALIFIER", "TABLE_OWNER", "TABLE_NAME", + "TABLE_TYPE", "REMARKS"}; + + return GetTables(catalog_name, schema_name, table_name, table_type, + column_names); } std::shared_ptr FlightSqlStatement::GetTables_V3( const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *table_type) { - return current_result_set_; + ColumnNames column_names{"TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", + "TABLE_TYPE", "REMARKS"}; + + return GetTables(catalog_name, schema_name, table_name, table_type, + column_names); } std::shared_ptr FlightSqlStatement::GetColumns_V2( diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h index 0b5216f58c908..b51f2f7e1de52 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h @@ -18,6 +18,7 @@ #pragma once #include "arrow/flight/sql/client.h" +#include "flight_sql_statement_get_tables.h" #include #include @@ -34,10 +35,13 @@ class FlightSqlStatement : public odbcabstraction::Statement { arrow::flight::FlightCallOptions call_options_; arrow::flight::sql::FlightSqlClient &sql_client_; std::shared_ptr current_result_set_; - std::shared_ptr - current_result_set_metadata_; std::shared_ptr prepared_statement_; + std::shared_ptr + GetTables(const std::string *catalog_name, const std::string *schema_name, + const std::string *table_name, const std::string *table_type, + const ColumnNames &column_names); + public: FlightSqlStatement(arrow::flight::sql::FlightSqlClient &sql_client, arrow::flight::FlightCallOptions call_options); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc new file mode 100644 index 0000000000000..f9469dfc058f3 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc @@ -0,0 +1,185 @@ +// 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 "flight_sql_statement_get_tables.h" +#include "arrow/flight/api.h" +#include "arrow/flight/types.h" +#include "flight_sql_result_set.h" +#include "record_batch_transformer.h" +#include "utils.h" + +#include +#include + +namespace driver { +namespace flight_sql { + +using arrow::Result; +using arrow::flight::FlightClientOptions; +using arrow::flight::FlightInfo; +using arrow::flight::sql::FlightSqlClient; + +typedef boost::tokenizer> Tokenizer; + +void ParseTableTypes(const std::string &table_type, + std::vector &table_types) { + bool encountered = false; // for checking if there is a single quote + std::string curr_parse; // the current string + + for (char temp : table_type) { // while still in the string + switch (temp) { // switch depending on the character + case '\'': // if the character is a single quote + if (encountered) { + encountered = + false; // if we already found a single quote, reset encountered + } else { + encountered = + true; // if we haven't found a single quote, set encountered to true + } + break; + case ',': // if it is a comma + if (!encountered) { // if we have not found a single quote + table_types.push_back( + curr_parse); // put our current string into our vector + curr_parse = ""; // reset the current string + break; + } + default: // if it is a normal character + if (encountered && isspace(temp)) { + curr_parse.push_back(temp); // if we have found a single quote put the + // whitespace, we don't care + } else if (temp == '\'' || temp == ' ') { + break; // if the current character is a single quote, trash it and go to + // the next character. + } else { + curr_parse.push_back(temp); // if all of the above failed, put the + // character into the current string + } + break; // go to the next character + } + } + table_types.emplace_back( + curr_parse); // if we have found a single quote put the whitespace, + // we don't care +} + +std::shared_ptr +GetTablesForSQLAllCatalogs(const ColumnNames &names, + FlightCallOptions &call_options, + FlightSqlClient &sql_client) { + Result> result = + sql_client.GetCatalogs(call_options); + + std::shared_ptr schema; + std::shared_ptr flight_info; + + ThrowIfNotOK(result.status()); + flight_info = result.ValueOrDie(); + ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema)); + + auto transformer = RecordBatchTransformerWithTasksBuilder(schema) + .RenameField("catalog_name", names.catalog_column) + .AddFieldOfNulls(names.schema_column, utf8()) + .AddFieldOfNulls(names.table_column, utf8()) + .AddFieldOfNulls(names.table_type_column, utf8()) + .AddFieldOfNulls(names.remarks_column, utf8()) + .Build(); + + return std::make_shared(sql_client, call_options, + flight_info, transformer); +} + +std::shared_ptr GetTablesForSQLAllDbSchemas( + const ColumnNames &names, FlightCallOptions &call_options, + FlightSqlClient &sql_client, const std::string *schema_name) { + Result> result = + sql_client.GetDbSchemas(call_options, nullptr, schema_name); + + std::shared_ptr schema; + std::shared_ptr flight_info; + + ThrowIfNotOK(result.status()); + flight_info = result.ValueOrDie(); + ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema)); + + auto transformer = RecordBatchTransformerWithTasksBuilder(schema) + .AddFieldOfNulls(names.catalog_column, utf8()) + .RenameField("db_schema_name", names.schema_column) + .AddFieldOfNulls(names.table_column, utf8()) + .AddFieldOfNulls(names.table_type_column, utf8()) + .AddFieldOfNulls(names.remarks_column, utf8()) + .Build(); + + return std::make_shared(sql_client, call_options, + flight_info, transformer); +} + +std::shared_ptr +GetTablesForSQLAllTableTypes(const ColumnNames &names, + FlightCallOptions &call_options, + FlightSqlClient &sql_client) { + Result> result = + sql_client.GetTableTypes(call_options); + + std::shared_ptr schema; + std::shared_ptr flight_info; + + ThrowIfNotOK(result.status()); + flight_info = result.ValueOrDie(); + ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema)); + + auto transformer = RecordBatchTransformerWithTasksBuilder(schema) + .AddFieldOfNulls(names.catalog_column, utf8()) + .AddFieldOfNulls(names.schema_column, utf8()) + .AddFieldOfNulls(names.table_column, utf8()) + .RenameField("table_type", names.table_type_column) + .AddFieldOfNulls(names.remarks_column, utf8()) + .Build(); + + return std::make_shared(sql_client, call_options, + flight_info, transformer); +} + +std::shared_ptr GetTablesForGenericUse( + const ColumnNames &names, FlightCallOptions &call_options, + FlightSqlClient &sql_client, const std::string *catalog_name, + const std::string *schema_name, const std::string *table_name, + const std::vector &table_types) { + Result> result = sql_client.GetTables( + call_options, catalog_name, schema_name, table_name, false, &table_types); + + std::shared_ptr schema; + std::shared_ptr flight_info; + + ThrowIfNotOK(result.status()); + flight_info = result.ValueOrDie(); + ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema)); + + auto transformer = RecordBatchTransformerWithTasksBuilder(schema) + .RenameField("catalog_name", names.catalog_column) + .RenameField("db_schema_name", names.schema_column) + .RenameField("table_name", names.table_column) + .RenameField("table_type", names.table_type_column) + .AddFieldOfNulls(names.remarks_column, utf8()) + .Build(); + + return std::make_shared(sql_client, call_options, + flight_info, transformer); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h new file mode 100644 index 0000000000000..8c14acd9a8601 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h @@ -0,0 +1,63 @@ +// 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. + +#pragma once + +#include "arrow/flight/types.h" +#include "odbcabstraction/result_set.h" +#include "record_batch_transformer.h" +#include +#include + +namespace driver { +namespace flight_sql { + +using arrow::flight::FlightCallOptions; +using arrow::flight::sql::FlightSqlClient; +using odbcabstraction::ResultSet; + +typedef struct { + std::string catalog_column; + std::string schema_column; + std::string table_column; + std::string table_type_column; + std::string remarks_column; +} ColumnNames; + +void ParseTableTypes(const std::string &table_type, + std::vector &table_types); + +std::shared_ptr +GetTablesForSQLAllCatalogs(const ColumnNames &column_names, + FlightCallOptions &call_options, + FlightSqlClient &sql_client); +std::shared_ptr GetTablesForSQLAllDbSchemas( + const ColumnNames &column_names, FlightCallOptions &call_options, + FlightSqlClient &sql_client, const std::string *schema_name); + +std::shared_ptr +GetTablesForSQLAllTableTypes(const ColumnNames &column_names, + FlightCallOptions &call_options, + FlightSqlClient &sql_client); + +std::shared_ptr GetTablesForGenericUse( + const ColumnNames &column_names, FlightCallOptions &call_options, + FlightSqlClient &sql_client, const std::string *catalog_name, + const std::string *schema_name, const std::string *table_name, + const std::vector &table_types); +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 83d1529c3f8a0..fac76d2d5a9b6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -148,6 +148,27 @@ void TestBindColumnBigInt(const std::shared_ptr &connection) { } } +void TestGetTablesV2(const std::shared_ptr &connection) { + const std::shared_ptr &statement = connection->CreateStatement(); + const std::shared_ptr &result_set = + statement->GetTables_V2(nullptr, nullptr, nullptr, nullptr); + + const std::shared_ptr &metadata = + result_set->GetMetadata(); + size_t column_count = metadata->GetColumnCount(); + + while (result_set->Move(1) == 1) { + int buffer_length = 1024; + char result[buffer_length]; + ssize_t result_length; + result_set->GetData(1, driver::odbcabstraction::CDataType_CHAR, 0, 0, + result, buffer_length, &result_length); + std::cout << result << std::endl; + } + + std::cout << column_count << std::endl; +} + int main() { FlightSqlDriver driver; @@ -163,9 +184,10 @@ int main() { std::vector missing_attr; connection->Connect(properties, missing_attr); - TestBindColumnBigInt(connection); + // TestBindColumnBigInt(connection); // TestBindColumn(connection); - // TestGetData(connection); + // TestGetData(connection); + TestGetTablesV2(connection); connection->Close(); return 0; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/parse_table_types_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/parse_table_types_test.cc new file mode 100644 index 0000000000000..888fdb0eda99c --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/parse_table_types_test.cc @@ -0,0 +1,53 @@ +// 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 "flight_sql_statement_get_tables.h" +#include "gtest/gtest.h" + +namespace driver { +namespace flight_sql { + +void AssertParseTest(const std::string &input_string, + const std::vector &assert_vector) { + std::vector table_types; + + ParseTableTypes(input_string, table_types); + ASSERT_EQ(table_types, assert_vector); +} + +TEST(TableTypeParser, ParsingWithoutSingleQuotesWithLeadingWhiteSpace) { + AssertParseTest("TABLE, VIEW", {"TABLE", "VIEW"}); +} + +TEST(TableTypeParser, ParsingWithoutSingleQuotesWithoutLeadingWhiteSpace) { + AssertParseTest("TABLE,VIEW", {"TABLE", "VIEW"}); +} + +TEST(TableTypeParser, ParsingWithSingleQuotesWithLeadingWhiteSpace) { + AssertParseTest("'TABLE', 'VIEW'", {"TABLE", "VIEW"}); +} + +TEST(TableTypeParser, ParsingWithSingleQuotesWithoutLeadingWhiteSpace) { + AssertParseTest("'TABLE','VIEW'", {"TABLE", "VIEW"}); +} + +TEST(TableTypeParser, ParsingWithCommaInsideSingleQuotes) { + AssertParseTest("'TABLE, TEST', 'VIEW, TEMPORARY'", + {"TABLE, TEST", "VIEW, TEMPORARY"}); +} +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc index ec8c3cea2d6a9..3f6bc54b609a2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc @@ -39,13 +39,57 @@ Result> MakeEmptyArray(std::shared_ptr type, RETURN_NOT_OK(builder->AppendNulls(array_size)); return builder->Finish(); } + +/// A transformer class which is responsible to convert the name of fields +/// inside a RecordBatch. These fields are changed based on tasks created by the +/// methods RenameField() and AddFieldOfNulls(). The execution of the tasks is +/// handled by the method transformer. +class RecordBatchTransformerWithTasks : public RecordBatchTransformer { +private: + std::vector> fields_; + std::vector( + const std::shared_ptr &original_record_batch, + const std::shared_ptr &transformed_schema)>> + tasks_; + +public: + RecordBatchTransformerWithTasks( + std::vector> fields, + std::vector( + const std::shared_ptr &original_record_batch, + const std::shared_ptr &transformed_schema)>> + tasks) { + this->fields_.swap(fields); + this->tasks_.swap(tasks); + } + + std::shared_ptr + Transform(const std::shared_ptr &original) override { + auto new_schema = schema(fields_); + + std::vector> arrays; + arrays.reserve(new_schema->num_fields()); + + for (const auto &item : tasks_) { + arrays.emplace_back(item(original, new_schema)); + } + + auto transformed_batch = + RecordBatch::Make(new_schema, original->num_rows(), arrays); + return transformed_batch; + } + + std::shared_ptr GetTransformedSchema() override { + return schema(fields_); + } +}; } // namespace -RecordBatchTransformer::Builder &RecordBatchTransformer::Builder::RenameRecord( +RecordBatchTransformerWithTasksBuilder & +RecordBatchTransformerWithTasksBuilder::RenameField( const std::string &original_name, const std::string &transformed_name) { - auto rename_task = [&original_name, &transformed_name]( - const std::shared_ptr &original_record, + auto rename_task = [=](const std::shared_ptr &original_record, const std::shared_ptr &transformed_schema) { auto original_data_type = original_record->schema()->GetFieldByName(original_name); @@ -64,21 +108,26 @@ RecordBatchTransformer::Builder &RecordBatchTransformer::Builder::RenameRecord( auto original_fields = schema_->GetFieldByName(original_name); - new_fields_.push_back(field(transformed_name, original_fields->type(), - original_fields->metadata())); + if (original_fields->HasMetadata()) { + new_fields_.push_back(field(transformed_name, original_fields->type(), + original_fields->metadata())); + } else { + new_fields_.push_back( + field(transformed_name, original_fields->type(), nullptr)); + } return *this; } -RecordBatchTransformer::Builder & -RecordBatchTransformer::Builder::AddEmptyFields( +RecordBatchTransformerWithTasksBuilder & +RecordBatchTransformerWithTasksBuilder::AddFieldOfNulls( const std::string &field_name, const std::shared_ptr &data_type) { auto empty_fields_task = [=](const std::shared_ptr &original_record, const std::shared_ptr &transformed_schema) { auto result = MakeEmptyArray(data_type, nullptr, original_record->num_rows()); - driver::flight_sql::ThrowIfNotOK(result.status()); + ThrowIfNotOK(result.status()); return result.ValueOrDie(); }; @@ -90,38 +139,17 @@ RecordBatchTransformer::Builder::AddEmptyFields( return *this; } -RecordBatchTransformer RecordBatchTransformer::Builder::Build() { - RecordBatchTransformer transformer(*this); +std::shared_ptr +RecordBatchTransformerWithTasksBuilder::Build() { + std::shared_ptr transformer( + new RecordBatchTransformerWithTasks(this->new_fields_, + this->task_collection_)); return transformer; } -RecordBatchTransformer::Builder::Builder(std::shared_ptr schema) +RecordBatchTransformerWithTasksBuilder::RecordBatchTransformerWithTasksBuilder( + std::shared_ptr schema) : schema_(std::move(schema)) {} - -std::shared_ptr RecordBatchTransformer::Transform( - const std::shared_ptr &original) { - auto new_schema = schema(fields_); - - std::vector> arrays; - - for (const auto &item : tasks_) { - arrays.push_back(item(original, new_schema)); - } - - auto transformed_batch = - RecordBatch::Make(new_schema, original->num_rows(), arrays); - return transformed_batch; -} - -std::shared_ptr RecordBatchTransformer::GetTransformedSchema() { - return schema(fields_); -} - -RecordBatchTransformer::RecordBatchTransformer( - RecordBatchTransformer::Builder &builder) { - this->fields_.swap(builder.new_fields_); - this->tasks_.swap(builder.task_collection_); -} } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.h index f4444d7bfad3f..70b5395f4aa7f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.h @@ -26,68 +26,60 @@ namespace flight_sql { using namespace arrow; -/// A transformer class which is responsible to convert the name of fields -/// inside a RecordBatch. These fields are changed based on tasks created by the -/// methods RenameRecord() and AddEmptyFields(). The execution of the tasks is -/// handled by the method transformer. -class RecordBatchTransformer { -private: - std::vector> fields_; - std::vector( - const std::shared_ptr &original_record_batch, - const std::shared_ptr &transformed_schema)>> - tasks_; +typedef std::function( + const std::shared_ptr &original_record_batch, + const std::shared_ptr &transformed_schema)> + TransformTask; +/// A base class to implement different types of transformer. +class RecordBatchTransformer { public: - class Builder { - private: - std::vector> new_fields_; - std::vector( - const std::shared_ptr &original_record_batch, - const std::shared_ptr &transformed_schema)>> - task_collection_; - std::shared_ptr schema_; - - public: - friend class RecordBatchTransformer; - - /// Based on the original array name and in a target array name it prepares - /// a task that will execute the transformation. - /// \param original_name The original name of the field. - /// \param transformed_name The name after the transformation. - Builder &RenameRecord(const std::string &original_name, - const std::string &transformed_name); - - /// Add an empty field to the transformed record batch. - /// \param field_name The name of the empty fields. - /// \param data_type The target data type for the new fields. - Builder &AddEmptyFields(const std::string &field_name, - const std::shared_ptr &data_type); - - /// It creates an object of RecordBatchTransformer - /// \return a RecordBatchTransformer object. - RecordBatchTransformer Build(); - - /// Instantiate a Builder object. - /// \param schema The schema from the original RecordBatch. - explicit Builder(std::shared_ptr schema); - }; + virtual ~RecordBatchTransformer() = default; /// Execute the transformation based on predeclared tasks created by - /// RenameRecord() method and/or AddEmptyFields(). + /// RenameField() method and/or AddFieldOfNulls(). /// \param original The original RecordBatch that will be used as base /// for the transformation. /// \return The new transformed RecordBatch. - std::shared_ptr - Transform(const std::shared_ptr &original); + virtual std::shared_ptr + Transform(const std::shared_ptr &original) = 0; /// Use the new list of fields constructed during creation of task /// to return the new schema. /// \return the schema from the transformedRecordBatch. - std::shared_ptr GetTransformedSchema(); + virtual std::shared_ptr GetTransformedSchema() = 0; +}; +class RecordBatchTransformerWithTasksBuilder { private: - explicit RecordBatchTransformer(Builder &builder); + std::vector> new_fields_; + std::vector task_collection_; + std::shared_ptr schema_; + +public: + /// Based on the original array name and in a target array name it prepares + /// a task that will execute the transformation. + /// \param original_name The original name of the field. + /// \param transformed_name The name after the transformation. + RecordBatchTransformerWithTasksBuilder & + RenameField(const std::string &original_name, + const std::string &transformed_name); + + /// Add an empty field to the transformed record batch. + /// \param field_name The name of the empty fields. + /// \param data_type The target data type for the new fields. + RecordBatchTransformerWithTasksBuilder & + AddFieldOfNulls(const std::string &field_name, + const std::shared_ptr &data_type); + + /// It creates an object of RecordBatchTransformerWithTasksBuilder + /// \return a RecordBatchTransformerWithTasksBuilder object. + std::shared_ptr Build(); + + /// Instantiate a RecordBatchTransformerWithTasksBuilder object. + /// \param schema The schema from the original RecordBatch. + explicit RecordBatchTransformerWithTasksBuilder( + std::shared_ptr schema); }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc index b6c3d2aecb76a..914cc068fabf4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc @@ -15,10 +15,10 @@ // specific language governing permissions and limitations // under the License. +#include "arrow/testing/builder.h" #include "record_batch_transformer.h" #include "gtest/gtest.h" #include -#include "arrow/testing/builder.h" using namespace arrow; namespace { @@ -46,11 +46,11 @@ TEST(Transformer, TransformerRenameTest) { std::string original_name("test"); std::string transformed_name("test1"); - auto transformer = RecordBatchTransformer::Builder(schema) - .RenameRecord(original_name, transformed_name) + auto transformer = RecordBatchTransformerWithTasksBuilder(schema) + .RenameField(original_name, transformed_name) .Build(); - auto transformed_record_batch = transformer.Transform(original_record_batch); + auto transformed_record_batch = transformer->Transform(original_record_batch); auto transformed_array_ptr = transformed_record_batch->GetColumnByName(transformed_name); @@ -79,18 +79,18 @@ TEST(Transformer, TransformerAddEmptyVectorTest) { std::string transformed_name("test1"); auto emptyField = std::string("empty"); - auto transformer = RecordBatchTransformer::Builder(schema) - .RenameRecord(original_name, transformed_name) - .AddEmptyFields(emptyField, int32()) + auto transformer = RecordBatchTransformerWithTasksBuilder(schema) + .RenameField(original_name, transformed_name) + .AddFieldOfNulls(emptyField, int32()) .Build(); - auto transformed_schema = transformer.GetTransformedSchema(); + auto transformed_schema = transformer->GetTransformedSchema(); ASSERT_EQ(transformed_schema->num_fields(), 2); ASSERT_EQ(transformed_schema->GetFieldIndex(transformed_name), 0); ASSERT_EQ(transformed_schema->GetFieldIndex(emptyField), 1); - auto transformed_record_batch = transformer.Transform(original_record_batch); + auto transformed_record_batch = transformer->Transform(original_record_batch); auto transformed_array_ptr = transformed_record_batch->GetColumnByName(transformed_name); @@ -130,15 +130,15 @@ TEST(Transformer, TransformerChangingOrderOfArrayTest) { RecordBatch::Make(schema, 5, {first_array, second_array, third_array}); auto transformer = - RecordBatchTransformer::Builder(schema) - .RenameRecord(std::string("third_array"), std::string("test3")) - .RenameRecord(std::string("second_array"), std::string("test2")) - .RenameRecord(std::string("first_array"), std::string("test1")) - .AddEmptyFields(std::string("empty"), int32()) + RecordBatchTransformerWithTasksBuilder(schema) + .RenameField("third_array", "test3") + .RenameField("second_array", "test2") + .RenameField("first_array", "test1") + .AddFieldOfNulls("empty", int32()) .Build(); const std::shared_ptr &transformed_record_batch = - transformer.Transform(original_record_batch); + transformer->Transform(original_record_batch); auto transformed_schema = transformed_record_batch->schema(); From 20339c865bc4c865ede0c21b50234f07c4c0b604 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Wed, 16 Mar 2022 15:00:52 -0300 Subject: [PATCH 074/183] Implement GetColumns_V3 and GetColumns_V2 This implemments GetColumns capabilities to Flight SQL ODBC Driver. This works by gettings results from Flight SQL's CommandGetTables and using a RecordBatchTransformer to retrieve data for each column on each table. Change-Id: I778bc8bb6ad254af2240a07f95f3a8e08a5d5059 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 4 + .../flight_sql/flight_sql_auth_method.cc | 8 +- .../flight_sql/flight_sql_auth_method.h | 6 +- .../flight_sql_get_tables_reader.cc | 88 +++++ .../flight_sql/flight_sql_get_tables_reader.h | 52 +++ .../flight_sql_result_set_metadata.cc | 63 +--- .../flight_sql/flight_sql_statement.cc | 30 ++ .../flight_sql_statement_get_columns.cc | 240 ++++++++++++++ .../flight_sql_statement_get_columns.h | 100 ++++++ .../flightsql-odbc/flight_sql/main.cc | 32 +- .../record_batch_transformer_test.cc | 13 +- .../flightsql-odbc/flight_sql/utils.cc | 312 ++++++++++++++++++ .../flightsql-odbc/flight_sql/utils.h | 37 +++ .../flightsql-odbc/flight_sql/utils_test.cc | 33 ++ .../include/odbcabstraction/types.h | 21 +- 15 files changed, 958 insertions(+), 81 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index ea07af7552362..6ee08d8193ebc 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -101,10 +101,13 @@ set(ARROW_ODBC_SPI_SOURCES flight_sql_result_set_metadata.cc flight_sql_statement.cc flight_sql_statement_get_tables.cc + flight_sql_statement_get_columns.cc + flight_sql_get_tables_reader.cc flight_sql_stream_chunk_iterator.cc get_info_cache.cc record_batch_transformer.cc scalar_function_reporter.cc + utils.cc ) set(ARROW_ODBC_SPI_THIRDPARTY_LIBS @@ -150,6 +153,7 @@ set(ARROW_ODBC_SPI_TEST_SOURCES flight_sql_connection_test.cc parse_table_types_test.cc record_batch_transformer_test.cc + utils_test.cc ) add_executable(arrow_odbc_spi_impl_test ${ARROW_ODBC_SPI_TEST_SOURCES}) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 19b25d50c7244..f55ceabb81c31 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -78,9 +78,7 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { call_options.headers.push_back(bearer_result.ValueOrDie()); } - std::string GetUser() override { - return user_; - } + std::string GetUser() override { return user_; } private: FlightClient &client_; @@ -97,8 +95,8 @@ std::unique_ptr FlightSqlAuthMethod::FromProperties( auto it_user = properties.find(FlightSqlConnection::USER); auto it_password = properties.find(FlightSqlConnection::PASSWORD); if (it_user == properties.end() || it_password == properties.end()) { - // Accept UID/PWD as aliases for User/Password. These are suggested as standard properties - // in the documentation for SQLDriverConnect. + // Accept UID/PWD as aliases for User/Password. These are suggested as + // standard properties in the documentation for SQLDriverConnect. it_user = properties.find(FlightSqlConnection::UID); it_password = properties.find(FlightSqlConnection::PWD); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index ccdfee3b43e57..61ba4d1d316fe 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include namespace driver { namespace flight_sql { @@ -34,9 +34,7 @@ class FlightSqlAuthMethod { virtual void Authenticate(FlightSqlConnection &connection, arrow::flight::FlightCallOptions &call_options) = 0; - virtual std::string GetUser() { - return std::string(); - } + virtual std::string GetUser() { return std::string(); } static std::unique_ptr FromProperties( const std::unique_ptr &client, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc new file mode 100644 index 0000000000000..e105c7f1f660a --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc @@ -0,0 +1,88 @@ +// 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 "flight_sql_get_tables_reader.h" +#include "arrow/io/memory.h" +#include "utils.h" + +#include + +namespace driver { +namespace flight_sql { + +using arrow::internal::checked_pointer_cast; +using arrow::util::nullopt; + +GetTablesReader::GetTablesReader(std::shared_ptr record_batch) + : record_batch_(std::move(record_batch)), current_row_(-1) {} + +bool GetTablesReader::Next() { + return ++current_row_ < record_batch_->num_rows(); +} + +optional GetTablesReader::GetCatalogName() { + const auto &array = + checked_pointer_cast(record_batch_->column(0)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetString(current_row_); +} + +optional GetTablesReader::GetDbSchemaName() { + const auto &array = + checked_pointer_cast(record_batch_->column(1)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetString(current_row_); +} + +std::string GetTablesReader::GetTableName() { + const auto &array = + checked_pointer_cast(record_batch_->column(2)); + + return array->GetString(current_row_); +} + +std::string GetTablesReader::GetTableType() { + const auto &array = + checked_pointer_cast(record_batch_->column(3)); + + return array->GetString(current_row_); +} + +std::shared_ptr GetTablesReader::GetSchema() { + const auto &array = + checked_pointer_cast(record_batch_->column(4)); + if (array == nullptr) { + return nullptr; + } + + io::BufferReader dataset_schema_reader(array->GetView(current_row_)); + ipc::DictionaryMemo in_memo; + const Result> &result = + ReadSchema(&dataset_schema_reader, &in_memo); + ThrowIfNotOK(result.status()); + + return result.ValueOrDie(); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.h new file mode 100644 index 0000000000000..119af90082ed4 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.h @@ -0,0 +1,52 @@ +// 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 "record_batch_transformer.h" +#include +#include +#include +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using arrow::util::optional; + +class GetTablesReader { +private: + std::shared_ptr record_batch_; + int64_t current_row_; + +public: + explicit GetTablesReader(std::shared_ptr record_batch); + + bool Next(); + + optional GetCatalogName(); + + optional GetDbSchemaName(); + + std::string GetTableName(); + + std::string GetTableType(); + + std::shared_ptr GetSchema(); +}; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index 41cbce86f776c..ec366f7e71e4f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -54,68 +54,7 @@ size_t FlightSqlResultSetMetadata::GetScale(int column_position) { SqlDataType FlightSqlResultSetMetadata::GetDataType(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - const std::shared_ptr &type = field->type(); - - switch (type->id()) { - case arrow::Type::BOOL: - return SqlDataType_BIT; - case arrow::Type::UINT8: - case arrow::Type::INT8: - return SqlDataType_TINYINT; - case arrow::Type::UINT16: - case arrow::Type::INT16: - return SqlDataType_SMALLINT; - case arrow::Type::UINT32: - case arrow::Type::INT32: - return SqlDataType_INTEGER; - case arrow::Type::UINT64: - case arrow::Type::INT64: - return SqlDataType_BIGINT; - case arrow::Type::HALF_FLOAT: - case arrow::Type::FLOAT: - return SqlDataType_FLOAT; - case arrow::Type::DOUBLE: - return SqlDataType_DOUBLE; - case arrow::Type::BINARY: - case arrow::Type::FIXED_SIZE_BINARY: - case arrow::Type::LARGE_BINARY: - return SqlDataType_BINARY; - case arrow::Type::STRING: - case arrow::Type::LARGE_STRING: - return SqlDataType_VARCHAR; - case arrow::Type::DATE32: - case arrow::Type::DATE64: - return SqlDataType_TYPE_DATE; - case arrow::Type::TIMESTAMP: - return SqlDataType_TYPE_TIMESTAMP; - case arrow::Type::DECIMAL128: - case arrow::Type::DECIMAL256: - return SqlDataType_DECIMAL; - case arrow::Type::TIME32: - case arrow::Type::TIME64: - return SqlDataType_TYPE_TIME; - - // TODO: Handle remaining types. - case arrow::Type::INTERVAL_MONTHS: - case arrow::Type::INTERVAL_DAY_TIME: - case arrow::Type::INTERVAL_MONTH_DAY_NANO: - case arrow::Type::LIST: - case arrow::Type::STRUCT: - case arrow::Type::SPARSE_UNION: - case arrow::Type::DENSE_UNION: - case arrow::Type::DICTIONARY: - case arrow::Type::MAP: - case arrow::Type::EXTENSION: - case arrow::Type::FIXED_SIZE_LIST: - case arrow::Type::DURATION: - case arrow::Type::LARGE_LIST: - case arrow::Type::MAX_ID: - case arrow::Type::NA: - break; - } - - throw driver::odbcabstraction::DriverException("Unsupported data type: " + - type->ToString()); + return GetDataTypeFromArrowField_V3(field); } driver::odbcabstraction::Nullability diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index 8ad1507e26c11..c6878cc979d92 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -18,10 +18,12 @@ #include "flight_sql_statement.h" #include "flight_sql_result_set.h" #include "flight_sql_result_set_metadata.h" +#include "flight_sql_statement_get_columns.h" #include "flight_sql_statement_get_tables.h" #include "record_batch_transformer.h" #include "utils.h" #include +#include #include #include @@ -182,12 +184,40 @@ std::shared_ptr FlightSqlStatement::GetTables_V3( std::shared_ptr FlightSqlStatement::GetColumns_V2( const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *column_name) { + ClosePreparedStatementIfAny(prepared_statement_); + + Result> result = sql_client_.GetTables( + call_options_, catalog_name, schema_name, table_name, true, nullptr); + ThrowIfNotOK(result.status()); + + auto flight_info = result.ValueOrDie(); + + auto transformer = std::make_shared( + odbcabstraction::V_2, column_name); + + current_result_set_ = std::make_shared( + sql_client_, call_options_, flight_info, transformer); + return current_result_set_; } std::shared_ptr FlightSqlStatement::GetColumns_V3( const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *column_name) { + ClosePreparedStatementIfAny(prepared_statement_); + + Result> result = sql_client_.GetTables( + call_options_, catalog_name, schema_name, table_name, true, nullptr); + ThrowIfNotOK(result.status()); + + auto flight_info = result.ValueOrDie(); + + auto transformer = std::make_shared( + odbcabstraction::V_3, column_name); + + current_result_set_ = std::make_shared( + sql_client_, call_options_, flight_info, transformer); + return current_result_set_; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc new file mode 100644 index 0000000000000..013be277a78f7 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc @@ -0,0 +1,240 @@ +// 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 "flight_sql_statement_get_columns.h" +#include "flight_sql_get_tables_reader.h" +#include "utils.h" + +namespace driver { +namespace flight_sql { + +using arrow::util::make_optional; +using arrow::util::nullopt; +using arrow::util::optional; + +namespace { +std::shared_ptr GetColumns_V3_Schema() { + return schema({ + field("TABLE_CAT", utf8()), + field("TABLE_SCHEM", utf8()), + field("TABLE_NAME", utf8()), + field("COLUMN_NAME", utf8()), + field("DATA_TYPE", int16()), + field("TYPE_NAME", utf8()), + field("COLUMN_SIZE", int32()), + field("BUFFER_LENGTH", int32()), + field("DECIMAL_DIGITS", int16()), + field("NUM_PREC_RADIX", int16()), + field("NULLABLE", int16()), + field("REMARKS", utf8()), + field("COLUMN_DEF", utf8()), + field("SQL_DATA_TYPE", int16()), + field("SQL_DATETIME_SUB", int16()), + field("CHAR_OCTET_LENGTH", int32()), + field("ORDINAL_POSITION", int32()), + field("IS_NULLABLE", int32()), + }); +} + +std::shared_ptr GetColumns_V2_Schema() { + return schema({ + field("TABLE_QUALIFIER", utf8()), + field("TABLE_OWNER", utf8()), + field("TABLE_NAME", utf8()), + field("COLUMN_NAME", utf8()), + field("DATA_TYPE", int16()), + field("TYPE_NAME", utf8()), + field("PRECISION", int32()), + field("LENGTH", int32()), + field("SCALE", int16()), + field("RADIX", int16()), + field("NULLABLE", int16()), + field("REMARKS", utf8()), + field("COLUMN_DEF", utf8()), + field("SQL_DATA_TYPE", int16()), + field("SQL_DATETIME_SUB", int16()), + field("CHAR_OCTET_LENGTH", int32()), + field("ORDINAL_POSITION", int32()), + field("IS_NULLABLE", int32()), + }); +} + +Result> +Transform_inner(const odbcabstraction::OdbcVersion odbc_version, + const std::shared_ptr &original, + const optional &column_name_pattern) { + GetColumns_RecordBatchBuilder builder(odbc_version); + GetColumns_RecordBatchBuilder::Data data; + + GetTablesReader reader(original); + + optional column_name_regex = + column_name_pattern.has_value() ? make_optional(ConvertSqlPatternToRegex( + column_name_pattern.value())) + : nullopt; + + while (reader.Next()) { + const auto &table_catalog = reader.GetCatalogName(); + const auto &table_schema = reader.GetDbSchemaName(); + const auto &table_name = reader.GetTableName(); + const std::shared_ptr &schema = reader.GetSchema(); + for (int i = 0; i < schema->num_fields(); ++i) { + const std::shared_ptr &field = schema->field(i); + + if (column_name_regex.has_value() && + !boost::xpressive::regex_match(field->name(), + column_name_regex.value())) { + continue; + } + + odbcabstraction::SqlDataType data_type_v3 = + GetDataTypeFromArrowField_V3(field); + + data.table_cat = table_catalog; + data.table_schem = table_schema; + data.table_name = table_name; + data.column_name = field->name(); + data.data_type = odbc_version == odbcabstraction::V_3 + ? data_type_v3 + : GetDataTypeFromArrowField_V2(field); + data.type_name = GetTypeNameFromSqlDataType(data_type_v3); + // TODO: Get from field's metadata "ARROW:FLIGHT:SQL:PRECISION" + data.column_size = nullopt; + // TODO: Get from column_size + data.buffer_length = nullopt; + // TODO: Get from field's metadata "ARROW:FLIGHT:SQL:SCALE" + data.decimal_digits = nullopt; + data.num_prec_radix = GetRadixFromSqlDataType(data_type_v3); + data.nullable = field->nullable(); + data.remarks = nullopt; + data.column_def = nullopt; + data.sql_data_type = GetNonConciseDataType(data_type_v3); + data.sql_datetime_sub = GetSqlDateTimeSubCode(data_type_v3); + // TODO: Get from column_size + data.char_octet_length = nullopt; + data.ordinal_position = i + 1; + data.is_nullable = field->nullable() ? "YES" : "NO"; + + ARROW_RETURN_NOT_OK(builder.Append(data)); + } + } + + return builder.Build(); +} +} // namespace + +GetColumns_RecordBatchBuilder::GetColumns_RecordBatchBuilder( + odbcabstraction::OdbcVersion odbc_version) + : odbc_version_(odbc_version) {} + +Result> GetColumns_RecordBatchBuilder::Build() { + ARROW_ASSIGN_OR_RAISE(auto TABLE_CAT_Array, TABLE_CAT_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto TABLE_SCHEM_Array, TABLE_SCHEM_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto TABLE_NAME_Array, TABLE_NAME_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto COLUMN_NAME_Array, COLUMN_NAME_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto DATA_TYPE_Array, DATA_TYPE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto TYPE_NAME_Array, TYPE_NAME_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto COLUMN_SIZE_Array, COLUMN_SIZE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto BUFFER_LENGTH_Array, + BUFFER_LENGTH_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto DECIMAL_DIGITS_Array, + DECIMAL_DIGITS_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto NUM_PREC_RADIX_Array, + NUM_PREC_RADIX_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto NULLABLE_Array, NULLABLE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto REMARKS_Array, REMARKS_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto COLUMN_DEF_Array, COLUMN_DEF_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto SQL_DATA_TYPE_Array, + SQL_DATA_TYPE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto SQL_DATETIME_SUB_Array, + SQL_DATETIME_SUB_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto CHAR_OCTET_LENGTH_Array, + CHAR_OCTET_LENGTH_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto ORDINAL_POSITION_Array, + ORDINAL_POSITION_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto IS_NULLABLE_Array, IS_NULLABLE_Builder_.Finish()) + + std::vector> arrays = { + TABLE_CAT_Array, TABLE_SCHEM_Array, TABLE_NAME_Array, + COLUMN_NAME_Array, DATA_TYPE_Array, TYPE_NAME_Array, + COLUMN_SIZE_Array, BUFFER_LENGTH_Array, DECIMAL_DIGITS_Array, + NUM_PREC_RADIX_Array, NULLABLE_Array, REMARKS_Array, + COLUMN_DEF_Array, SQL_DATA_TYPE_Array, SQL_DATETIME_SUB_Array, + CHAR_OCTET_LENGTH_Array, ORDINAL_POSITION_Array, IS_NULLABLE_Array}; + + const std::shared_ptr &schema = odbc_version_ == odbcabstraction::V_3 + ? GetColumns_V3_Schema() + : GetColumns_V2_Schema(); + return RecordBatch::Make(schema, num_rows_, arrays); +} + +Status GetColumns_RecordBatchBuilder::Append( + const GetColumns_RecordBatchBuilder::Data &data) { + ARROW_RETURN_NOT_OK(AppendToBuilder(TABLE_CAT_Builder_, data.table_cat)); + ARROW_RETURN_NOT_OK(AppendToBuilder(TABLE_SCHEM_Builder_, data.table_schem)); + ARROW_RETURN_NOT_OK(AppendToBuilder(TABLE_NAME_Builder_, data.table_name)); + ARROW_RETURN_NOT_OK(AppendToBuilder(COLUMN_NAME_Builder_, data.column_name)); + ARROW_RETURN_NOT_OK(AppendToBuilder(DATA_TYPE_Builder_, data.data_type)); + ARROW_RETURN_NOT_OK(AppendToBuilder(TYPE_NAME_Builder_, data.type_name)); + ARROW_RETURN_NOT_OK(AppendToBuilder(COLUMN_SIZE_Builder_, data.column_size)); + ARROW_RETURN_NOT_OK( + AppendToBuilder(BUFFER_LENGTH_Builder_, data.buffer_length)); + ARROW_RETURN_NOT_OK( + AppendToBuilder(DECIMAL_DIGITS_Builder_, data.decimal_digits)); + ARROW_RETURN_NOT_OK( + AppendToBuilder(NUM_PREC_RADIX_Builder_, data.num_prec_radix)); + ARROW_RETURN_NOT_OK(AppendToBuilder(NULLABLE_Builder_, data.nullable)); + ARROW_RETURN_NOT_OK(AppendToBuilder(REMARKS_Builder_, data.remarks)); + ARROW_RETURN_NOT_OK(AppendToBuilder(COLUMN_DEF_Builder_, data.column_def)); + ARROW_RETURN_NOT_OK( + AppendToBuilder(SQL_DATA_TYPE_Builder_, data.sql_data_type)); + ARROW_RETURN_NOT_OK( + AppendToBuilder(SQL_DATETIME_SUB_Builder_, data.sql_datetime_sub)); + ARROW_RETURN_NOT_OK( + AppendToBuilder(CHAR_OCTET_LENGTH_Builder_, data.char_octet_length)); + ARROW_RETURN_NOT_OK( + AppendToBuilder(ORDINAL_POSITION_Builder_, data.ordinal_position)); + ARROW_RETURN_NOT_OK(AppendToBuilder(IS_NULLABLE_Builder_, data.is_nullable)); + num_rows_++; + + return Status::OK(); +} + +GetColumns_Transformer::GetColumns_Transformer( + const odbcabstraction::OdbcVersion odbc_version, + const std::string *column_name_pattern) + : odbc_version_(odbc_version), + column_name_pattern_( + column_name_pattern ? make_optional(*column_name_pattern) : nullopt) { +} + +std::shared_ptr GetColumns_Transformer::Transform( + const std::shared_ptr &original) { + const Result> &result = + Transform_inner(odbc_version_, original, column_name_pattern_); + ThrowIfNotOK(result.status()); + + return result.ValueOrDie(); +} + +std::shared_ptr GetColumns_Transformer::GetTransformedSchema() { + return odbc_version_ == odbcabstraction::V_3 ? GetColumns_V3_Schema() + : GetColumns_V2_Schema(); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.h new file mode 100644 index 0000000000000..bc46aaade5139 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.h @@ -0,0 +1,100 @@ +// 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 "record_batch_transformer.h" +#include +#include +#include +#include +#include + +namespace driver { +namespace flight_sql { + +using arrow::util::optional; + +class GetColumns_RecordBatchBuilder { +private: + odbcabstraction::OdbcVersion odbc_version_; + + StringBuilder TABLE_CAT_Builder_; + StringBuilder TABLE_SCHEM_Builder_; + StringBuilder TABLE_NAME_Builder_; + StringBuilder COLUMN_NAME_Builder_; + Int16Builder DATA_TYPE_Builder_; + StringBuilder TYPE_NAME_Builder_; + Int32Builder COLUMN_SIZE_Builder_; + Int32Builder BUFFER_LENGTH_Builder_; + Int16Builder DECIMAL_DIGITS_Builder_; + Int16Builder NUM_PREC_RADIX_Builder_; + Int16Builder NULLABLE_Builder_; + StringBuilder REMARKS_Builder_; + StringBuilder COLUMN_DEF_Builder_; + Int16Builder SQL_DATA_TYPE_Builder_; + Int16Builder SQL_DATETIME_SUB_Builder_; + Int32Builder CHAR_OCTET_LENGTH_Builder_; + Int32Builder ORDINAL_POSITION_Builder_; + StringBuilder IS_NULLABLE_Builder_; + int64_t num_rows_{0}; + +public: + struct Data { + optional table_cat; + optional table_schem; + std::string table_name; + std::string column_name; + std::string type_name; + optional column_size; + optional buffer_length; + optional decimal_digits; + optional num_prec_radix; + optional remarks; + optional column_def; + int16_t sql_data_type{}; + optional sql_datetime_sub; + optional char_octet_length; + optional is_nullable; + int16_t data_type; + int16_t nullable; + int32_t ordinal_position; + }; + + explicit GetColumns_RecordBatchBuilder( + odbcabstraction::OdbcVersion odbc_version); + + Result> Build(); + + Status Append(const Data &data); +}; + +class GetColumns_Transformer : public RecordBatchTransformer { +private: + odbcabstraction::OdbcVersion odbc_version_; + optional column_name_pattern_; + +public: + explicit GetColumns_Transformer(odbcabstraction::OdbcVersion odbc_version_, + const std::string *column_name_pattern); + + std::shared_ptr + Transform(const std::shared_ptr &original) override; + + std::shared_ptr GetTransformedSchema() override; +}; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index fac76d2d5a9b6..1b7ccce6c385f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -169,6 +169,33 @@ void TestGetTablesV2(const std::shared_ptr &connection) { std::cout << column_count << std::endl; } +void TestGetColumnsV3(const std::shared_ptr &connection) { + const std::shared_ptr &statement = connection->CreateStatement(); + std::string column_name = "%"; + const std::shared_ptr &result_set = + statement->GetColumns_V3(nullptr, nullptr, nullptr, &column_name); + + const std::shared_ptr &metadata = + result_set->GetMetadata(); + size_t column_count = metadata->GetColumnCount(); + + int buffer_length = 1024; + char result[buffer_length]; + ssize_t result_length; + + while (result_set->Move(1) == 1) { + for (int i = 0; i < column_count; ++i) { + result_set->GetData(1 + i, driver::odbcabstraction::CDataType_CHAR, 0, 0, + result, buffer_length, &result_length); + std::cout << result << '\t'; + } + + std::cout << std::endl; + } + + std::cout << column_count << std::endl; +} + int main() { FlightSqlDriver driver; @@ -186,8 +213,9 @@ int main() { // TestBindColumnBigInt(connection); // TestBindColumn(connection); - // TestGetData(connection); - TestGetTablesV2(connection); + // TestGetData(connection); + // TestGetTablesV2(connection); + TestGetColumnsV3(connection); connection->Close(); return 0; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc index 914cc068fabf4..f0dabb0110fda 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc @@ -129,13 +129,12 @@ TEST(Transformer, TransformerChangingOrderOfArrayTest) { auto original_record_batch = RecordBatch::Make(schema, 5, {first_array, second_array, third_array}); - auto transformer = - RecordBatchTransformerWithTasksBuilder(schema) - .RenameField("third_array", "test3") - .RenameField("second_array", "test2") - .RenameField("first_array", "test1") - .AddFieldOfNulls("empty", int32()) - .Build(); + auto transformer = RecordBatchTransformerWithTasksBuilder(schema) + .RenameField("third_array", "test3") + .RenameField("second_array", "test2") + .RenameField("first_array", "test1") + .AddFieldOfNulls("empty", int32()) + .Build(); const std::shared_ptr &transformed_record_batch = transformer->Transform(original_record_batch); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc new file mode 100644 index 0000000000000..b68a0e0ac3fc1 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -0,0 +1,312 @@ +// 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 "utils.h" +#include +#include + +namespace driver { +namespace flight_sql { + +using namespace odbcabstraction; + +SqlDataType +GetDataTypeFromArrowField_V3(const std::shared_ptr &field) { + const std::shared_ptr &type = field->type(); + + switch (type->id()) { + case arrow::Type::BOOL: + return odbcabstraction::SqlDataType_BIT; + case arrow::Type::UINT8: + case arrow::Type::INT8: + return odbcabstraction::SqlDataType_TINYINT; + case arrow::Type::UINT16: + case arrow::Type::INT16: + return odbcabstraction::SqlDataType_SMALLINT; + case arrow::Type::UINT32: + case arrow::Type::INT32: + return odbcabstraction::SqlDataType_INTEGER; + case arrow::Type::UINT64: + case arrow::Type::INT64: + return odbcabstraction::SqlDataType_BIGINT; + case arrow::Type::HALF_FLOAT: + case arrow::Type::FLOAT: + return odbcabstraction::SqlDataType_FLOAT; + case arrow::Type::DOUBLE: + return odbcabstraction::SqlDataType_DOUBLE; + case arrow::Type::BINARY: + case arrow::Type::FIXED_SIZE_BINARY: + case arrow::Type::LARGE_BINARY: + return odbcabstraction::SqlDataType_BINARY; + case arrow::Type::STRING: + case arrow::Type::LARGE_STRING: + return odbcabstraction::SqlDataType_VARCHAR; + case arrow::Type::DATE32: + case arrow::Type::DATE64: + return odbcabstraction::SqlDataType_TYPE_DATE; + case arrow::Type::TIMESTAMP: + return odbcabstraction::SqlDataType_TYPE_TIMESTAMP; + case arrow::Type::DECIMAL128: + case arrow::Type::DECIMAL256: + return odbcabstraction::SqlDataType_DECIMAL; + case arrow::Type::TIME32: + case arrow::Type::TIME64: + return odbcabstraction::SqlDataType_TYPE_TIME; + + // TODO: Handle remaining types. + case arrow::Type::INTERVAL_MONTHS: + case arrow::Type::INTERVAL_DAY_TIME: + case arrow::Type::INTERVAL_MONTH_DAY_NANO: + case arrow::Type::LIST: + case arrow::Type::STRUCT: + case arrow::Type::SPARSE_UNION: + case arrow::Type::DENSE_UNION: + case arrow::Type::DICTIONARY: + case arrow::Type::MAP: + case arrow::Type::EXTENSION: + case arrow::Type::FIXED_SIZE_LIST: + case arrow::Type::DURATION: + case arrow::Type::LARGE_LIST: + case arrow::Type::MAX_ID: + case arrow::Type::NA: + break; + } + + throw driver::odbcabstraction::DriverException("Unsupported data type: " + + type->ToString()); +} + +int16_t +GetDataTypeFromArrowField_V2(const std::shared_ptr &field) { + SqlDataType type = GetDataTypeFromArrowField_V3(field); + switch (type) { + case SqlDataType_TYPE_DATE: + return 9; // Same as SQL_DATE from sqlext.h + case SqlDataType_TYPE_TIME: + return 10; // Same as SQL_TIME from sqlext.h + case SqlDataType_TYPE_TIMESTAMP: + return 11; // Same as SQL_TIMESTAMP from sqlext.h + default: + return type; + } +} + +std::string GetTypeNameFromSqlDataType(int16_t data_type) { + switch (data_type) { + case SqlDataType_CHAR: + return "CHAR"; + case SqlDataType_VARCHAR: + return "VARCHAR"; + case SqlDataType_LONGVARCHAR: + return "LONGVARCHAR"; + case SqlDataType_WCHAR: + return "WCHAR"; + case SqlDataType_WVARCHAR: + return "WVARCHAR"; + case SqlDataType_WLONGVARCHAR: + return "WLONGVARCHAR"; + case SqlDataType_DECIMAL: + return "DECIMAL"; + case SqlDataType_NUMERIC: + return "NUMERIC"; + case SqlDataType_SMALLINT: + return "SMALLINT"; + case SqlDataType_INTEGER: + return "INTEGER"; + case SqlDataType_REAL: + return "REAL"; + case SqlDataType_FLOAT: + return "FLOAT"; + case SqlDataType_DOUBLE: + return "DOUBLE"; + case SqlDataType_BIT: + return "BIT"; + case SqlDataType_TINYINT: + return "TINYINT"; + case SqlDataType_BIGINT: + return "BIGINT"; + case SqlDataType_BINARY: + return "BINARY"; + case SqlDataType_VARBINARY: + return "VARBINARY"; + case SqlDataType_LONGVARBINARY: + return "LONGVARBINARY"; + case SqlDataType_TYPE_DATE: + case 9: + return "DATE"; + case SqlDataType_TYPE_TIME: + case 10: + return "TIME"; + case SqlDataType_TYPE_TIMESTAMP: + case 11: + return "TIMESTAMP"; + case SqlDataType_INTERVAL_MONTH: + return "INTERVAL_MONTH"; + case SqlDataType_INTERVAL_YEAR: + return "INTERVAL_YEAR"; + case SqlDataType_INTERVAL_YEAR_TO_MONTH: + return "INTERVAL_YEAR_TO_MONTH"; + case SqlDataType_INTERVAL_DAY: + return "INTERVAL_DAY"; + case SqlDataType_INTERVAL_HOUR: + return "INTERVAL_HOUR"; + case SqlDataType_INTERVAL_MINUTE: + return "INTERVAL_MINUTE"; + case SqlDataType_INTERVAL_SECOND: + return "INTERVAL_SECOND"; + case SqlDataType_INTERVAL_DAY_TO_HOUR: + return "INTERVAL_DAY_TO_HOUR"; + case SqlDataType_INTERVAL_DAY_TO_MINUTE: + return "INTERVAL_DAY_TO_MINUTE"; + case SqlDataType_INTERVAL_DAY_TO_SECOND: + return "INTERVAL_DAY_TO_SECOND"; + case SqlDataType_INTERVAL_HOUR_TO_MINUTE: + return "INTERVAL_HOUR_TO_MINUTE"; + case SqlDataType_INTERVAL_HOUR_TO_SECOND: + return "INTERVAL_HOUR_TO_SECOND"; + case SqlDataType_INTERVAL_MINUTE_TO_SECOND: + return "INTERVAL_MINUTE_TO_SECOND"; + case SqlDataType_GUID: + return "GUID"; + } + + throw driver::odbcabstraction::DriverException("Unsupported data type: " + + std::to_string(data_type)); +} + +optional GetRadixFromSqlDataType(int16_t data_type) { + switch (data_type) { + case SqlDataType_DECIMAL: + case SqlDataType_NUMERIC: + case SqlDataType_SMALLINT: + case SqlDataType_TINYINT: + case SqlDataType_INTEGER: + case SqlDataType_BIGINT: + return 10; + case SqlDataType_REAL: + case SqlDataType_FLOAT: + case SqlDataType_DOUBLE: + return 2; + default: + return arrow::util::nullopt; + } +} + +int16_t GetNonConciseDataType(int16_t data_type) { + switch (data_type) { + case SqlDataType_TYPE_DATE: + case SqlDataType_TYPE_TIME: + case SqlDataType_TYPE_TIMESTAMP: + return 9; // Same as SQL_DATETIME on sql.h + case SqlDataType_INTERVAL_YEAR: + case SqlDataType_INTERVAL_MONTH: + case SqlDataType_INTERVAL_DAY: + case SqlDataType_INTERVAL_HOUR: + case SqlDataType_INTERVAL_MINUTE: + case SqlDataType_INTERVAL_SECOND: + case SqlDataType_INTERVAL_YEAR_TO_MONTH: + case SqlDataType_INTERVAL_DAY_TO_HOUR: + case SqlDataType_INTERVAL_DAY_TO_MINUTE: + case SqlDataType_INTERVAL_DAY_TO_SECOND: + case SqlDataType_INTERVAL_HOUR_TO_MINUTE: + case SqlDataType_INTERVAL_HOUR_TO_SECOND: + case SqlDataType_INTERVAL_MINUTE_TO_SECOND: + return 10; // Same as SQL_INTERVAL on sqlext.h + default: + return data_type; + } +} + +optional GetSqlDateTimeSubCode(int16_t data_type) { + switch (data_type) { + case SqlDataType_TYPE_DATE: + return SqlDateTimeSubCode_DATE; + case SqlDataType_TYPE_TIME: + return SqlDateTimeSubCode_TIME; + case SqlDataType_TYPE_TIMESTAMP: + return SqlDateTimeSubCode_TIMESTAMP; + case SqlDataType_INTERVAL_YEAR: + return SqlDateTimeSubCode_YEAR; + case SqlDataType_INTERVAL_MONTH: + return SqlDateTimeSubCode_MONTH; + case SqlDataType_INTERVAL_DAY: + return SqlDateTimeSubCode_DAY; + case SqlDataType_INTERVAL_HOUR: + return SqlDateTimeSubCode_HOUR; + case SqlDataType_INTERVAL_MINUTE: + return SqlDateTimeSubCode_MINUTE; + case SqlDataType_INTERVAL_SECOND: + return SqlDateTimeSubCode_SECOND; + case SqlDataType_INTERVAL_YEAR_TO_MONTH: + return SqlDateTimeSubCode_YEAR_TO_MONTH; + case SqlDataType_INTERVAL_DAY_TO_HOUR: + return SqlDateTimeSubCode_DAY_TO_HOUR; + case SqlDataType_INTERVAL_DAY_TO_MINUTE: + return SqlDateTimeSubCode_DAY_TO_MINUTE; + case SqlDataType_INTERVAL_DAY_TO_SECOND: + return SqlDateTimeSubCode_DAY_TO_SECOND; + case SqlDataType_INTERVAL_HOUR_TO_MINUTE: + return SqlDateTimeSubCode_HOUR_TO_MINUTE; + case SqlDataType_INTERVAL_HOUR_TO_SECOND: + return SqlDateTimeSubCode_HOUR_TO_SECOND; + case SqlDataType_INTERVAL_MINUTE_TO_SECOND: + return SqlDateTimeSubCode_MINUTE_TO_SECOND; + default: + return arrow::util::nullopt; + } +} + +std::string ConvertSqlPatternToRegexString(const std::string &pattern) { + static const std::string specials = "[]()|^-+*?{}$\\."; + + std::string regex_str; + bool escape = false; + for (const auto &c : pattern) { + if (escape) { + regex_str += c; + escape = false; + continue; + } + + switch (c) { + case '\\': + escape = true; + break; + case '_': + regex_str += '.'; + break; + case '%': + regex_str += ".*"; + break; + default: + if (specials.find(c) != std::string::npos) { + regex_str += '\\'; + } + regex_str += c; + break; + } + } + return regex_str; +} + +boost::xpressive::sregex ConvertSqlPatternToRegex(const std::string &pattern) { + const std::string ®ex_str = ConvertSqlPatternToRegexString(pattern); + return boost::xpressive::sregex(boost::xpressive::sregex::compile(regex_str)); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index 7c74613efc225..b844c29e97ef0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -18,16 +18,53 @@ #pragma once #include +#include +#include #include +#include namespace driver { namespace flight_sql { +using arrow::util::optional; + inline void ThrowIfNotOK(const arrow::Status &status) { if (!status.ok()) { throw odbcabstraction::DriverException(status.ToString()); } } +template +arrow::Status AppendToBuilder(BUILDER &builder, optional opt_value) { + if (opt_value.has_value()) { + return builder.Append(opt_value.value()); + } else { + return builder.AppendNull(); + } +} + +template +arrow::Status AppendToBuilder(BUILDER &builder, T value) { + return builder.Append(value); +} + +odbcabstraction::SqlDataType +GetDataTypeFromArrowField_V3(const std::shared_ptr &field); + +int16_t +GetDataTypeFromArrowField_V2(const std::shared_ptr &field); + +std::string GetTypeNameFromSqlDataType(int16_t data_type); + +optional GetRadixFromSqlDataType(int16_t data_type); + +int16_t GetNonConciseDataType(int16_t data_type); + +optional GetSqlDateTimeSubCode(int16_t data_type); + +std::string ConvertSqlPatternToRegexString(const std::string &pattern); + +boost::xpressive::sregex ConvertSqlPatternToRegex(const std::string &pattern); + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc new file mode 100644 index 0000000000000..189edf0414723 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc @@ -0,0 +1,33 @@ +// 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 "utils.h" +#include "gtest/gtest.h" + +namespace driver { +namespace flight_sql { + +TEST(Utils, ConvertSqlPatternToRegexString) { + ASSERT_EQ(std::string("XY"), ConvertSqlPatternToRegexString("XY")); + ASSERT_EQ(std::string("X.Y"), ConvertSqlPatternToRegexString("X_Y")); + ASSERT_EQ(std::string("X.*Y"), ConvertSqlPatternToRegexString("X%Y")); + ASSERT_EQ(std::string("X%Y"), ConvertSqlPatternToRegexString("X\\%Y")); + ASSERT_EQ(std::string("X_Y"), ConvertSqlPatternToRegexString("X\\_Y")); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 5e5cbad44d8d2..2172477050f2a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -24,7 +24,7 @@ namespace odbcabstraction { enum OdbcVersion { V_2, V_3, V_4 }; // Based on ODBC sql.h and sqlext.h definitions. -enum SqlDataType { +enum SqlDataType : int16_t { SqlDataType_CHAR = 1, SqlDataType_VARCHAR = 12, SqlDataType_LONGVARCHAR = (-1), @@ -63,6 +63,25 @@ enum SqlDataType { SqlDataType_GUID = (-11), }; +enum SqlDateTimeSubCode : int16_t { + SqlDateTimeSubCode_DATE = 1, + SqlDateTimeSubCode_TIME = 2, + SqlDateTimeSubCode_TIMESTAMP = 3, + SqlDateTimeSubCode_YEAR = 1, + SqlDateTimeSubCode_MONTH = 2, + SqlDateTimeSubCode_DAY = 3, + SqlDateTimeSubCode_HOUR = 4, + SqlDateTimeSubCode_MINUTE = 5, + SqlDateTimeSubCode_SECOND = 6, + SqlDateTimeSubCode_YEAR_TO_MONTH = 7, + SqlDateTimeSubCode_DAY_TO_HOUR = 8, + SqlDateTimeSubCode_DAY_TO_MINUTE = 9, + SqlDateTimeSubCode_DAY_TO_SECOND = 10, + SqlDateTimeSubCode_HOUR_TO_MINUTE = 11, + SqlDateTimeSubCode_HOUR_TO_SECOND = 12, + SqlDateTimeSubCode_MINUTE_TO_SECOND = 13, +}; + // Based on ODBC sql.h and sqlext.h definitions. enum CDataType { CDataType_CHAR = 1, From 3a69a142e85acdb9da31877b72c8f33d6bb0e2a8 Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 28 Mar 2022 15:45:55 -0700 Subject: [PATCH 075/183] Implement connection attributes - Add support for connection attributes - Clarify typing and purpose of attributes - Support reporting attributes where only a single value are permitted - Report when attributes are not supported Change-Id: Iee3009199b9dedd0abf135666f0f0e00eb62fbd1 --- .../flight_sql/flight_sql_auth_method.cc | 2 +- .../flight_sql/flight_sql_connection.cc | 56 +++++++++++++++---- .../flight_sql/flight_sql_connection.h | 2 +- .../flight_sql/flight_sql_connection_test.cc | 10 ++-- .../flight_sql/record_batch_transformer.cc | 2 +- .../include/odbcabstraction/connection.h | 22 ++++---- 6 files changed, 62 insertions(+), 32 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index f55ceabb81c31..c3f7c2201e950 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -61,7 +61,7 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { if (login_timeout.has_value()) { // ODBC's LOGIN_TIMEOUT attribute and FlightCallOptions.timeout use // seconds as time unit. - double timeout_seconds = boost::get(login_timeout.value()); + double timeout_seconds = static_cast(boost::get(login_timeout.value())); if (timeout_seconds > 0) { auth_call_options.timeout = TimeoutDuration{timeout_seconds}; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index eaa9ec08b7c14..d13a11708af82 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -68,6 +68,11 @@ TrackMissingRequiredProperty(const std::string &property, return prop_iter; } +template +bool CheckIfSetToOnlyValidValue(const Connection::Attribute &value, T allowed_value) { + return boost::get(value) == allowed_value; +} + } // namespace void FlightSqlConnection::Connect(const ConnPropertyMap &properties, @@ -90,16 +95,17 @@ void FlightSqlConnection::Connect(const ConnPropertyMap &properties, auth_method->Authenticate(*this, call_options_); sql_client_.reset(new FlightSqlClient(std::move(flight_client))); + closed_ = false; // Note: This should likely come from Flight instead of being from the // connection properties to allow reporting a user for other auth mechanisms // and also decouple the database user from user credentials. info_.SetProperty(SQL_USER_NAME, auth_method->GetUser()); - SetAttribute(CONNECTION_DEAD, false); + attribute_[CONNECTION_DEAD] = static_cast(SQL_FALSE); PopulateCallOptionsFromAttributes(); } catch (...) { - SetAttribute(CONNECTION_DEAD, true); + attribute_[CONNECTION_DEAD] = static_cast(SQL_TRUE); sql_client_.reset(); throw; @@ -108,12 +114,13 @@ void FlightSqlConnection::Connect(const ConnPropertyMap &properties, const FlightCallOptions & FlightSqlConnection::PopulateCallOptionsFromAttributes() { - // Set CONNECTION_TIMEOUT attribute - const boost::optional &connection_timeout = - GetAttribute(CONNECTION_TIMEOUT); + // Set CONNECTION_TIMEOUT attribute or LOGIN_TIMEOUT depending on if this + // is the first request. + const boost::optional &connection_timeout = closed_ ? + GetAttribute(LOGIN_TIMEOUT) : GetAttribute(CONNECTION_TIMEOUT); if (connection_timeout.has_value()) { call_options_.timeout = - TimeoutDuration{boost::get(connection_timeout.value())}; + TimeoutDuration{static_cast(boost::get(connection_timeout.value()))}; } return call_options_; @@ -166,6 +173,7 @@ void FlightSqlConnection::Close() { sql_client_.reset(); closed_ = true; + attribute_[CONNECTION_DEAD] = static_cast(SQL_TRUE); } std::shared_ptr FlightSqlConnection::CreateStatement() { @@ -173,15 +181,36 @@ std::shared_ptr FlightSqlConnection::CreateStatement() { new FlightSqlStatement(*sql_client_, call_options_)); } -void FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, +bool FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, const Connection::Attribute &value) { - attribute_[attribute] = value; + switch (attribute) { + case ACCESS_MODE: + // We will always return read-write. + return CheckIfSetToOnlyValidValue(value, static_cast(SQL_MODE_READ_WRITE)); + case METADATA_ID: + return CheckIfSetToOnlyValidValue(value, static_cast(SQL_FALSE)); + case PACKET_SIZE: + return CheckIfSetToOnlyValidValue(value, static_cast(0)); + default: + attribute_[attribute] = value; + return true; + } } boost::optional FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { - const auto &it = attribute_.find(attribute); - return boost::make_optional(it != attribute_.end(), it->second); + switch (attribute) { + case ACCESS_MODE: + // FlightSQL does not provide this metadata. + return boost::make_optional(Attribute(static_cast(SQL_MODE_READ_WRITE))); + case METADATA_ID: + return boost::make_optional(Attribute(static_cast(SQL_FALSE))); + case PACKET_SIZE: + return boost::make_optional(Attribute(static_cast(0))); + default: + const auto &it = attribute_.find(attribute); + return boost::make_optional(it != attribute_.end(), it->second); + } } Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { @@ -190,7 +219,10 @@ Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version) : odbc_version_(odbc_version), info_(call_options_, sql_client_), - closed_(false) {} - + closed_(true) { + attribute_[CONNECTION_DEAD] = static_cast(SQL_TRUE); + attribute_[LOGIN_TIMEOUT] = static_cast(0); + attribute_[CONNECTION_TIMEOUT] = static_cast(0); +} } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index b09b48881862f..e827b9cb31b4f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -55,7 +55,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { std::shared_ptr CreateStatement() override; - void SetAttribute(AttributeId attribute, const Attribute &value) override; + bool SetAttribute(AttributeId attribute, const Attribute &value) override; boost::optional GetAttribute(Connection::AttributeId attribute) override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 435fcff0450ab..430050d1adac0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -29,21 +29,21 @@ using odbcabstraction::Connection; TEST(AttributeTests, SetAndGetAttribute) { FlightSqlConnection connection(odbcabstraction::V_3); - connection.SetAttribute(Connection::CONNECTION_TIMEOUT, 200); + connection.SetAttribute(Connection::CONNECTION_TIMEOUT, static_cast(200)); const boost::optional firstValue = connection.GetAttribute(Connection::CONNECTION_TIMEOUT); EXPECT_TRUE(firstValue.has_value()); - EXPECT_EQ(boost::get(firstValue.value()), 200); + EXPECT_EQ(boost::get(firstValue.value()), static_cast(200)); - connection.SetAttribute(Connection::CONNECTION_TIMEOUT, 300); + connection.SetAttribute(Connection::CONNECTION_TIMEOUT, static_cast(300)); const boost::optional changeValue = connection.GetAttribute(Connection::CONNECTION_TIMEOUT); EXPECT_TRUE(changeValue.has_value()); - EXPECT_EQ(boost::get(changeValue.value()), 300); + EXPECT_EQ(boost::get(changeValue.value()), static_cast(300)); connection.Close(); } @@ -112,7 +112,7 @@ TEST(PopulateCallOptionsTest, ConnectionTimeout) { ASSERT_EQ(TimeoutDuration{-1.0}, connection.PopulateCallOptionsFromAttributes().timeout); - connection.SetAttribute(Connection::CONNECTION_TIMEOUT, 10.0); + connection.SetAttribute(Connection::CONNECTION_TIMEOUT, static_cast(10)); ASSERT_EQ(TimeoutDuration{10.0}, connection.PopulateCallOptionsFromAttributes().timeout); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc index 3f6bc54b609a2..d51696f3dd313 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc @@ -113,7 +113,7 @@ RecordBatchTransformerWithTasksBuilder::RenameField( original_fields->metadata())); } else { new_fields_.push_back( - field(transformed_name, original_fields->type(), nullptr)); + field(transformed_name, original_fields->type(), std::shared_ptr())); } return *this; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index 7f78781de6e24..2cfa0acb0dcfa 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -40,16 +40,12 @@ class Connection { /// \brief Connection attributes enum AttributeId { - ACCESS_MODE, // Tells if it should support write operations - AUTO_IPD, // Relevant to parameter binding on statements - AUTOCOMMIT, // Do not support transactions yet - CONNECTION_DEAD, // Tells if connection is still alive - CONNECTION_TIMEOUT, // Matters to Connect() - DBC_INFO_TOKEN, // Lookup - LOGIN_TIMEOUT, // Matters to Connect() - METADATA_ID, // Pass to statement - PACKET_SIZE, // Lookup if there is a packet size on Flight - QUIET_MODE, // Lookup + ACCESS_MODE, // uint32_t - Tells if it should support write operations + CONNECTION_DEAD, // uint32_t - Tells if connection is still alive + CONNECTION_TIMEOUT, // uint32_t - The timeout for connection functions after connecting. + LOGIN_TIMEOUT, // uint32_t - The timeout for the initial connection + METADATA_ID, // uint32_t - Modifies catalog function arguments to be identifiers + PACKET_SIZE, // uint32_t - The Packet Size }; /// \brief Case insensitive comparator @@ -60,7 +56,7 @@ class Connection { } }; - typedef boost::variant Attribute; + typedef boost::variant Attribute; typedef std::string Property; typedef boost::variant Info; // ConnPropertyMap is case-insensitive for keys. @@ -82,7 +78,9 @@ class Connection { /// \brief Set a connection attribute (may be called at any time). /// \param attribute[in] Which attribute to set. /// \param value The value to be set. - virtual void SetAttribute(AttributeId attribute, const Attribute &value) = 0; + /// \return true if the value was set successfully or false if it was substituted with + /// a similar value. + virtual bool SetAttribute(AttributeId attribute, const Attribute &value) = 0; /// \brief Retrieve a connection attribute /// \param attribute[in] Attribute to be retrieved. From cd53e4ce522cbddc613007be91c8a64b323d5a1c Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 31 Mar 2022 04:26:31 -0700 Subject: [PATCH 076/183] Fix rebase error in connection Add missing CURRENT_CATALOG connection attribute Change-Id: I5a5eb9d5494c94994c34a5739b01d9d04e26856b --- .../odbcabstraction/include/odbcabstraction/connection.h | 1 + 1 file changed, 1 insertion(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index 2cfa0acb0dcfa..4cb6828e0563d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -43,6 +43,7 @@ class Connection { ACCESS_MODE, // uint32_t - Tells if it should support write operations CONNECTION_DEAD, // uint32_t - Tells if connection is still alive CONNECTION_TIMEOUT, // uint32_t - The timeout for connection functions after connecting. + CURRENT_CATALOG, // std::string - The current catalog LOGIN_TIMEOUT, // uint32_t - The timeout for the initial connection METADATA_ID, // uint32_t - Modifies catalog function arguments to be identifiers PACKET_SIZE, // uint32_t - The Packet Size From 83ca5e64efcadd61fb22dbbb34fc1efedc605ce6 Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 31 Mar 2022 10:21:50 -0700 Subject: [PATCH 077/183] Fix timeout attributes - Fix bug where connections used timeouts when timeouts should be disabled. - Add missing current_catalog attribute Change-Id: I26e6b84fc5807a6623caafc507a77d85ceeb0716 --- .../flightsql-odbc/flight_sql/flight_sql_auth_method.cc | 4 ++-- .../flightsql-odbc/flight_sql/flight_sql_connection.cc | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index c3f7c2201e950..0c7b2e5339183 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -58,10 +58,10 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { FlightCallOptions auth_call_options; const boost::optional &login_timeout = connection.GetAttribute(Connection::LOGIN_TIMEOUT); - if (login_timeout.has_value()) { + if (login_timeout && boost::get(*login_timeout) > 0) { // ODBC's LOGIN_TIMEOUT attribute and FlightCallOptions.timeout use // seconds as time unit. - double timeout_seconds = static_cast(boost::get(login_timeout.value())); + double timeout_seconds = static_cast(boost::get(*login_timeout)); if (timeout_seconds > 0) { auth_call_options.timeout = TimeoutDuration{timeout_seconds}; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index d13a11708af82..c6ea24efffc16 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -118,9 +118,9 @@ FlightSqlConnection::PopulateCallOptionsFromAttributes() { // is the first request. const boost::optional &connection_timeout = closed_ ? GetAttribute(LOGIN_TIMEOUT) : GetAttribute(CONNECTION_TIMEOUT); - if (connection_timeout.has_value()) { + if (connection_timeout && boost::get(*connection_timeout) > 0) { call_options_.timeout = - TimeoutDuration{static_cast(boost::get(connection_timeout.value()))}; + TimeoutDuration{static_cast(boost::get(*connection_timeout))}; } return call_options_; @@ -223,6 +223,7 @@ FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version) attribute_[CONNECTION_DEAD] = static_cast(SQL_TRUE); attribute_[LOGIN_TIMEOUT] = static_cast(0); attribute_[CONNECTION_TIMEOUT] = static_cast(0); + attribute_[CURRENT_CATALOG] = ""; } } // namespace flight_sql } // namespace driver From bbaaca9594d82c2f57164e8935f824e46cd5fc6e Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 29 Mar 2022 17:21:33 -0300 Subject: [PATCH 078/183] Fix warpdrive build - Get the build to work on CentOS7 - Build ODBCAbstraction with -fPIC. - Avoid use of boost::optional::has_value() which isn't available on some versions of boost. - Add missing default for CURRENT_CATALOG Change-Id: Ia93eeff0755477105333c7be9272bf1fcbf2bec1 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 58 ++++++++++++------- .../flight_sql/flight_sql_connection_test.cc | 10 ++-- .../flight_sql_statement_get_columns.cc | 8 +-- .../flightsql-odbc/flight_sql/utils.h | 4 +- .../odbcabstraction/CMakeLists.txt | 2 + 5 files changed, 49 insertions(+), 33 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 6ee08d8193ebc..f9286fad23000 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -18,10 +18,37 @@ cmake_minimum_required(VERSION 3.11) set(CMAKE_CXX_STANDARD 11) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + include_directories( include ${CMAKE_SOURCE_DIR}/odbcabstraction/include) +# Add Protobuf dependencies needed by Arrow Flight. Should be pre-installed. +set(Protobuf_USE_STATIC_LIBS ON) +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) + 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. +set(OpenSSL_USE_STATIC_LIBS ON) +set(OPENSSL_USE_STATIC_LIBS ON) +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) + SET(Arrow_STATIC ON) # Get Arrow using git. @@ -38,6 +65,7 @@ set(ARROW_CMAKE_ARGS -DARROW_BUILD_TESTS=OFF -DARROW_DEPENDENCY_USE_SHARED=OFF -DCMAKE_DEPENDS_USE_COMPILER=FALSE + -DOPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install ${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow/cpp ) @@ -56,31 +84,16 @@ ExternalProject_Add(ApacheArrow CMAKE_ARGS ${ARROW_CMAKE_ARGS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install/include) -link_directories(${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install/lib) +IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + set(ARROW_LIB_DIR lib64) +else() + set(ARROW_LIB_DIR lib) +endif() +link_directories(${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install/${ARROW_LIB_DIR}) # Add Zlib dependencies needed by Arrow Flight. Should be pre-installed. find_package(ZLIB REQUIRED) -# Add Protobuf dependencies needed by Arrow Flight. Should be pre-installed. -set(Protobuf_USE_STATIC_LIBS ON) -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) - 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. -set(OpenSSL_USE_STATIC_LIBS ON) -set(OPENSSL_USE_STATIC_LIBS ON) -find_package(OpenSSL REQUIRED) - -# Add gRPC dependencies needed by Arrow Flight. Should be pre-installed. -find_package(gRPC 1.36 CONFIG REQUIRED) - if (APPLE) add_compile_definitions(WITH_IODBC) endif() @@ -115,9 +128,10 @@ set(ARROW_ODBC_SPI_THIRDPARTY_LIBS arrow_flight arrow arrow_bundled_dependencies + gRPC::grpc++ ${ZLIB_LIBRARIES} ${Protobuf_LIBRARIES} - gRPC::grpc++ + ${OPENSSL_LIBRARIES} ) add_library(arrow_odbc_spi_impl ${ARROW_ODBC_SPI_SOURCES}) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 430050d1adac0..94300b79046ae 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -33,17 +33,17 @@ TEST(AttributeTests, SetAndGetAttribute) { const boost::optional firstValue = connection.GetAttribute(Connection::CONNECTION_TIMEOUT); - EXPECT_TRUE(firstValue.has_value()); + EXPECT_TRUE(firstValue); - EXPECT_EQ(boost::get(firstValue.value()), static_cast(200)); + EXPECT_EQ(boost::get(*firstValue), static_cast(200)); connection.SetAttribute(Connection::CONNECTION_TIMEOUT, static_cast(300)); const boost::optional changeValue = connection.GetAttribute(Connection::CONNECTION_TIMEOUT); - EXPECT_TRUE(changeValue.has_value()); - EXPECT_EQ(boost::get(changeValue.value()), static_cast(300)); + EXPECT_TRUE(changeValue); + EXPECT_EQ(boost::get(*changeValue), static_cast(300)); connection.Close(); } @@ -54,7 +54,7 @@ TEST(AttributeTests, GetAttributeWithoutSetting) { const boost::optional anOptional = connection.GetAttribute(Connection::CONNECTION_TIMEOUT); - EXPECT_FALSE(anOptional.has_value()); + EXPECT_FALSE(anOptional); connection.Close(); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc index 013be277a78f7..3c8dde33e0b01 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc @@ -83,8 +83,8 @@ Transform_inner(const odbcabstraction::OdbcVersion odbc_version, GetTablesReader reader(original); optional column_name_regex = - column_name_pattern.has_value() ? make_optional(ConvertSqlPatternToRegex( - column_name_pattern.value())) + column_name_pattern ? make_optional(ConvertSqlPatternToRegex( + *column_name_pattern)) : nullopt; while (reader.Next()) { @@ -95,9 +95,9 @@ Transform_inner(const odbcabstraction::OdbcVersion odbc_version, for (int i = 0; i < schema->num_fields(); ++i) { const std::shared_ptr &field = schema->field(i); - if (column_name_regex.has_value() && + if (column_name_regex && !boost::xpressive::regex_match(field->name(), - column_name_regex.value())) { + *column_name_regex)) { continue; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index b844c29e97ef0..5881cdd4000fa 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -36,8 +36,8 @@ inline void ThrowIfNotOK(const arrow::Status &status) { template arrow::Status AppendToBuilder(BUILDER &builder, optional opt_value) { - if (opt_value.has_value()) { - return builder.Append(opt_value.value()); + if (opt_value) { + return builder.Append(*opt_value); } else { return builder.AppendNull(); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index d7ef830f383e9..d7be3aefb772e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -17,6 +17,8 @@ include(FindODBC) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + include_directories(include) add_library(odbcabstraction From f4c13854a3b6b003da1746c964f29da954d6b2e8 Mon Sep 17 00:00:00 2001 From: Alex McRae Date: Wed, 30 Mar 2022 08:38:39 -0700 Subject: [PATCH 079/183] Modifications to support windows build * Removes non-std c++ which prevents building on Windows * modifies the cmake to build on Windows * Pulls dependencies using vcpkg on Windows * Adds win32/win64 build batch files. Change-Id: I3bf6bfc3fda5b450f98e413119d790175aadcf0e --- .../flightsql-odbc/.gitignore | 2 + .../flightsql-odbc/build_win32.bat | 47 ++++++++++ .../flightsql-odbc/build_win64.bat | 47 ++++++++++ .../flightsql-odbc/flight_sql/CMakeLists.txt | 93 ++++++++++++++----- .../accessors/binary_array_accessor.cc | 2 + .../accessors/binary_array_accessor_test.cc | 23 ++--- .../accessors/boolean_array_accessor_test.cc | 8 +- .../flight_sql/accessors/common.h | 2 + .../primitive_array_accessor_test.cc | 8 +- .../accessors/string_array_accessor_test.cc | 40 ++++---- .../flight_sql/accessors/types.h | 1 + .../flight_sql/flight_sql_auth_method.cc | 2 + .../flight_sql/flight_sql_connection.cc | 3 + .../flight_sql/flight_sql_connection_test.cc | 3 + .../flight_sql/flight_sql_driver.cc | 1 + .../flight_sql_get_tables_reader.cc | 1 + .../flight_sql/flight_sql_result_set.cc | 1 + .../flight_sql/flight_sql_result_set.h | 1 + .../flight_sql_result_set_accessors.cc | 2 + .../flight_sql_result_set_column.cc | 1 + .../flight_sql_result_set_metadata.cc | 1 + .../flight_sql/flight_sql_statement.cc | 1 + .../flight_sql_statement_get_columns.cc | 1 + .../flight_sql_statement_get_tables.cc | 1 + .../flight_sql_stream_chunk_iterator.cc | 1 + .../flight_sql/get_info_cache.cc | 6 +- .../flightsql-odbc/flight_sql/main.cc | 41 ++++---- .../flight_sql/parse_table_types_test.cc | 1 + .../flight_sql/record_batch_transformer.cc | 1 + .../record_batch_transformer_test.cc | 1 + .../flight_sql/scalar_function_reporter.cc | 2 + .../flightsql-odbc/flight_sql/utils.cc | 1 + .../flightsql-odbc/flight_sql/utils_test.cc | 1 + .../odbcabstraction/exceptions.cc | 1 + .../include/odbcabstraction/platform.h | 28 ++++++ .../include/odbcabstraction/result_set.h | 2 + .../flightsql-odbc/vcpkg.json | 17 +++- 37 files changed, 310 insertions(+), 85 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win32.bat create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win64.bat create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore index f2f4387daf9eb..65a03f3058fc9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore @@ -26,6 +26,8 @@ cmake-build-*/ *.swp .idea +.vs +.vscode vcpkg_installed *-prefix _deps diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win32.bat b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win32.bat new file mode 100644 index 0000000000000..902eaeff4d874 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win32.bat @@ -0,0 +1,47 @@ + +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@REM Please define ARROW_GIT_REPOSITORY to be the arrow repository. If this is a local repo, +@REM use forward slashes instead of backslashes. + +@REM Please define VCPKG_ROOT to be the directory with a built vcpkg. This path should use +@REM forward slashes instead of backslashes. + +@ECHO OFF + +%VCPKG_ROOT%\vcpkg.exe install --triplet x86-windows --x-install-root=%VCPKG_ROOT%/installed + +if exist ".\build" del build /q + +mkdir build + +cd build + +if NOT DEFINED ARROW_GIT_REPOSITORY SET ARROW_GIT_REPOSITORY = "https://github.com/apache/arrow" + +cmake ..^ + -DARROW_GIT_REPOSITORY=%ARROW_GIT_REPOSITORY%^ + -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake^ + -DVCPKG_TARGET_TRIPLET=x86-windows^ + -DVCPKG_MANIFEST_MODE=OFF^ + -G"Visual Studio 17 2022"^ + -A Win32^ + -DCMAKE_BUILD_TYPE=release + +cmake --build . --parallel 8 --config Release + +cd .. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win64.bat b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win64.bat new file mode 100644 index 0000000000000..29a0fe01f04f1 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win64.bat @@ -0,0 +1,47 @@ + +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@REM Please define ARROW_GIT_REPOSITORY to be the arrow repository. If this is a local repo, +@REM use forward slashes instead of backslashes. + +@REM Please define VCPKG_ROOT to be the directory with a built vcpkg. This path should use +@REM forward slashes instead of backslashes. + +@ECHO OFF + +%VCPKG_ROOT%\vcpkg.exe install --triplet x64-windows --x-install-root=%VCPKG_ROOT%/installed + +if exist ".\build" del build /q + +mkdir build + +cd build + +if NOT DEFINED ARROW_GIT_REPOSITORY SET ARROW_GIT_REPOSITORY = "https://github.com/apache/arrow" + +cmake ..^ + -DARROW_GIT_REPOSITORY=%ARROW_GIT_REPOSITORY%^ + -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake^ + -DVCPKG_TARGET_TRIPLET=x64-windows^ + -DVCPKG_MANIFEST_MODE=OFF^ + -G"Visual Studio 17 2022"^ + -A x64^ + -DCMAKE_BUILD_TYPE=release + +cmake --build . --parallel 8 --config Release + +cd .. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index f9286fad23000..aed4b573ecb7f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -24,6 +24,9 @@ include_directories( include ${CMAKE_SOURCE_DIR}/odbcabstraction/include) +# Add Zlib dependencies needed by Arrow Flight. Should be pre-installed. +find_package(ZLIB REQUIRED) + # Add Protobuf dependencies needed by Arrow Flight. Should be pre-installed. set(Protobuf_USE_STATIC_LIBS ON) find_package(Protobuf REQUIRED) @@ -37,8 +40,10 @@ if (NOT DEFINED OPENSSL_ROOT_DIR AND DEFINED APPLE) endif() # This is based on Arrow's FindOpenSSL module. It's not clear if both variables # need to be set. -set(OpenSSL_USE_STATIC_LIBS ON) -set(OPENSSL_USE_STATIC_LIBS ON) +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 @@ -54,21 +59,41 @@ SET(Arrow_STATIC ON) # Get Arrow using git. include(ExternalProject) -set(ARROW_CMAKE_ARGS - -DARROW_FLIGHT=ON - -DARROW_FLIGHT_SQL=ON - -DARROW_IPC=ON - -DARROW_BUILD_SHARED=OFF - -DARROW_BUILD_STATIC=ON - -DARROW_COMPUTE=ON - -DARROW_WITH_UTF8PROC=OFF - -DARROW_BUILD_TESTS=OFF - -DARROW_DEPENDENCY_USE_SHARED=OFF - -DCMAKE_DEPENDS_USE_COMPILER=FALSE - -DOPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} - -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install - ${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow/cpp -) +if (MSVC) + set(ARROW_CMAKE_ARGS + -DARROW_FLIGHT=ON + -DARROW_FLIGHT_SQL=ON + -DARROW_COMPUTE=ON + -DARROW_IPC=ON + -DARROW_BUILD_SHARED=OFF + -DARROW_BUILD_STATIC=ON + -DARROW_WITH_UTF8PROC=OFF + -DARROW_BUILD_TESTS=OFF + -DARROW_DEPENDENCY_SOURCE=VCPKG + -DVCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET} + -DVCPKG_MANIFEST_MODE=${VCPKG_MANIFEST_MODE} + -DCMAKE_DEPENDS_USE_COMPILER=FALSE + -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install + -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} + ${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow/cpp + ) +else() + set(ARROW_CMAKE_ARGS + -DARROW_FLIGHT=ON + -DARROW_FLIGHT_SQL=ON + -DARROW_IPC=ON + -DARROW_BUILD_SHARED=OFF + -DARROW_BUILD_STATIC=ON + -DARROW_COMPUTE=ON + -DARROW_WITH_UTF8PROC=OFF + -DARROW_BUILD_TESTS=OFF + -DARROW_DEPENDENCY_USE_SHARED=OFF + -DCMAKE_DEPENDS_USE_COMPILER=FALSE + -DOPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} + -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install + ${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow/cpp + ) +endif() if(NOT ARROW_GIT_REPOSITORY) set(ARROW_GIT_REPOSITORY https://github.com/apache/arrow.git) @@ -91,13 +116,15 @@ else() endif() link_directories(${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install/${ARROW_LIB_DIR}) -# Add Zlib dependencies needed by Arrow Flight. Should be pre-installed. -find_package(ZLIB REQUIRED) - if (APPLE) add_compile_definitions(WITH_IODBC) endif() +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() set(ARROW_ODBC_SPI_SOURCES @@ -123,11 +150,26 @@ set(ARROW_ODBC_SPI_SOURCES utils.cc ) + +if (MSVC) + set(CMAKE_CXX_FLAGS_RELEASE "/MD") + set(CMAKE_CXX_FLAGS_DEBUG "/MDd") + set(ARROW_LIBS + arrow_flight_sql_static + arrow_flight_static + arrow_static + ) +else() + set(ARROW_LIBS + arrow_flight_sql + arrow_flight + arrow + arrow_bundled_dependencies + ) +endif() + set(ARROW_ODBC_SPI_THIRDPARTY_LIBS - arrow_flight_sql - arrow_flight - arrow - arrow_bundled_dependencies + ${ARROW_LIBS} gRPC::grpc++ ${ZLIB_LIBRARIES} ${Protobuf_LIBRARIES} @@ -135,6 +177,7 @@ set(ARROW_ODBC_SPI_THIRDPARTY_LIBS ) add_library(arrow_odbc_spi_impl ${ARROW_ODBC_SPI_SOURCES}) + add_dependencies(arrow_odbc_spi_impl ApacheArrow) set_target_properties(arrow_odbc_spi_impl @@ -171,7 +214,9 @@ set(ARROW_ODBC_SPI_TEST_SOURCES ) add_executable(arrow_odbc_spi_impl_test ${ARROW_ODBC_SPI_TEST_SOURCES}) + add_dependencies(arrow_odbc_spi_impl_test ApacheArrow) + set_target_properties(arrow_odbc_spi_impl_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test/$/bin diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc index d3a02e1f94ce9..faff231746c49 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc @@ -18,6 +18,8 @@ #include "binary_array_accessor.h" #include +#include +#include namespace driver { namespace flight_sql { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc index 1dd590b550d55..c3830b7f9f05d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License. +#include "arrow/testing/gtest_util.h" #include "arrow/testing/builder.h" #include "binary_array_accessor.h" #include "gtest/gtest.h" @@ -33,11 +34,11 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Basic) { BinaryArrayFlightSqlAccessor accessor(array.get()); size_t max_strlen = 64; - char buffer[values.size() * max_strlen]; - ssize_t strlen_buffer[values.size()]; + std::vector buffer(values.size() * max_strlen); + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_BINARY, 0, 0, buffer, max_strlen, - strlen_buffer); + ColumnBinding binding(CDataType_BINARY, 0, 0, buffer.data(), max_strlen, + strlen_buffer.data()); ASSERT_EQ(values.size(), accessor.GetColumnarData(&binding, 0, values.size(), 0)); @@ -48,8 +49,8 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Basic) { // It's safe to create a std::string from this data because we know it's // ASCII, this doesn't work with arbitrary binary data. ASSERT_EQ(values[i], - std::string(buffer + i * max_strlen, - buffer + i * max_strlen + strlen_buffer[i])); + std::string(buffer.data() + i * max_strlen, + buffer.data() + i * max_strlen + strlen_buffer[i])); } } @@ -62,11 +63,11 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Truncation) { BinaryArrayFlightSqlAccessor accessor(array.get()); size_t max_strlen = 8; - char buffer[values.size() * max_strlen]; - ssize_t strlen_buffer[values.size()]; + std::vector buffer(values.size() * max_strlen); + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_BINARY, 0, 0, buffer, max_strlen, - strlen_buffer); + ColumnBinding binding(CDataType_BINARY, 0, 0, buffer.data(), max_strlen, + strlen_buffer.data()); std::stringstream ss; int64_t value_offset = 0; @@ -83,7 +84,7 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Truncation) { // 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 // ASCII, this doesn't work with arbitrary binary data. - ss << std::string(buffer, buffer + chunk_length); + ss << std::string(buffer.data(), buffer.data() + chunk_length); value_offset += chunk_length; } while (value_offset < strlen_buffer[0]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc index d23fd9f7bc857..eb22686d9e17a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc @@ -26,16 +26,16 @@ using namespace arrow; using namespace odbcabstraction; TEST(BooleanArrayFlightSqlAccessor, Test_BooleanArray_CDataType_BIT) { - std::vector values = {true, false, true}; + const std::vector values = {true, false, true}; std::shared_ptr array; ArrayFromVector(values, &array); BooleanArrayFlightSqlAccessor accessor(array.get()); - char buffer[values.size()]; - ssize_t strlen_buffer[values.size()]; + std::vector buffer(values.size()); + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_BIT, 0, 0, buffer, 0, strlen_buffer); + ColumnBinding binding(CDataType_BIT, 0, 0, buffer.data(), 0, strlen_buffer.data()); ASSERT_EQ(values.size(), accessor.GetColumnarData(&binding, 0, values.size(), 0)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h index 7a74bd82def8a..6f2223013f7ee 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h @@ -21,6 +21,8 @@ #include #include #include +#include +#include namespace driver { namespace flight_sql { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc index 5ff49ae26bb2a..8adf8454c7d6e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc @@ -37,11 +37,11 @@ void TestPrimitiveArraySqlAccessor() { PrimitiveArrayFlightSqlAccessor accessor( array.get()); - c_type buffer[values.size()]; - ssize_t strlen_buffer[values.size()]; + std::vector buffer(values.size()); + std::vector strlen_buffer(values.size()); - ColumnBinding binding(TARGET_TYPE, 0, 0, buffer, values.size(), - strlen_buffer); + ColumnBinding binding(TARGET_TYPE, 0, 0, buffer.data(), values.size(), + strlen_buffer.data()); ASSERT_EQ(values.size(), accessor.GetColumnarData(&binding, 0, values.size(), 0)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc index c8e901d4ed038..14fee9f4f3cff 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc @@ -33,18 +33,18 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Basic) { StringArrayFlightSqlAccessor accessor(array.get()); size_t max_strlen = 64; - char buffer[values.size() * max_strlen]; - ssize_t strlen_buffer[values.size()]; + std::vector buffer(values.size() * max_strlen); + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_CHAR, 0, 0, buffer, max_strlen, - strlen_buffer); + ColumnBinding binding(CDataType_CHAR, 0, 0, buffer.data(), max_strlen, + strlen_buffer.data()); ASSERT_EQ(values.size(), accessor.GetColumnarData(&binding, 0, values.size(), 0)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(values[i].length(), strlen_buffer[i]); - ASSERT_EQ(values[i], std::string(buffer + i * max_strlen)); + ASSERT_EQ(values[i], std::string(buffer.data() + i * max_strlen)); } } @@ -57,11 +57,11 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Truncation) { StringArrayFlightSqlAccessor accessor(array.get()); size_t max_strlen = 8; - char buffer[values.size() * max_strlen]; - ssize_t strlen_buffer[values.size()]; + std::vector buffer(values.size() * max_strlen); + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_CHAR, 0, 0, buffer, max_strlen, - strlen_buffer); + ColumnBinding binding(CDataType_CHAR, 0, 0, buffer.data(), max_strlen, + strlen_buffer.data()); std::stringstream ss; int64_t value_offset = 0; @@ -74,7 +74,7 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Truncation) { int64_t chunk_length = std::min(static_cast(max_strlen), strlen_buffer[0] - value_offset); - ss << buffer; + ss << buffer.data(); value_offset += chunk_length - 1; } while (value_offset < strlen_buffer[0] - 1); @@ -89,11 +89,11 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Basic) { StringArrayFlightSqlAccessor accessor(array.get()); size_t max_strlen = 64; - SqlWChar buffer[values.size() * max_strlen]; - ssize_t strlen_buffer[values.size()]; + std::vector buffer(values.size() * max_strlen); + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_WCHAR, 0, 0, buffer, max_strlen, - strlen_buffer); + ColumnBinding binding(CDataType_WCHAR, 0, 0, buffer.data(), max_strlen, + strlen_buffer.data()); ASSERT_EQ(values.size(), accessor.GetColumnarData(&binding, 0, values.size(), 0)); @@ -101,7 +101,7 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Basic) { for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(values[i].length() * sizeof(SqlWChar), strlen_buffer[i]); auto expected = CharToWStrConverter().from_bytes(values[i].c_str()); - auto actual = SqlWString(buffer + i * max_strlen / sizeof(SqlWChar)); + auto actual = SqlWString(buffer.data() + i * max_strlen / sizeof(SqlWChar)); ASSERT_EQ(0, expected.compare(actual)); } } @@ -115,11 +115,11 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Truncation) { StringArrayFlightSqlAccessor accessor(array.get()); size_t max_strlen = 8; - SqlWChar buffer[values.size() * max_strlen]; - ssize_t strlen_buffer[values.size()]; + std::vector buffer(values.size() * max_strlen); + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_WCHAR, 0, 0, buffer, - max_strlen * sizeof(SqlWChar), strlen_buffer); + ColumnBinding binding(CDataType_WCHAR, 0, 0, buffer.data(), + max_strlen * sizeof(SqlWChar), strlen_buffer.data()); std::basic_stringstream ss; int64_t value_offset = 0; @@ -134,7 +134,7 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Truncation) { int64_t chunk_length = std::min(static_cast(max_strlen * sizeof(SqlWChar)), strlen_buffer[0] - value_offset); - finalStr += std::basic_string(buffer, chunk_length); + finalStr += std::basic_string(buffer.data(), chunk_length); value_offset += chunk_length - sizeof(SqlWChar); } while (value_offset < strlen_buffer[0] - sizeof(SqlWChar)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h index 3bab8764b869a..e31acef5bd94a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 0c7b2e5339183..3802a2882d3cf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -17,6 +17,8 @@ #include "flight_sql_auth_method.h" +#include + #include "flight_sql_connection.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index c6ea24efffc16..1a3ff420d9c5e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -17,11 +17,14 @@ #include "flight_sql_connection.h" +#include + #include #include #include #include #include + #include #include "flight_sql_auth_method.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 94300b79046ae..95ef89810134b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -16,6 +16,9 @@ // under the License. #include "flight_sql_connection.h" + +#include + #include "gtest/gtest.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index 49f18b4211406..d8329afbe140d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -16,6 +16,7 @@ // under the License. #include "flight_sql_connection.h" +#include #include namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc index e105c7f1f660a..6e08fbad3042a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc @@ -16,6 +16,7 @@ // under the License. #include "flight_sql_get_tables_reader.h" +#include #include "arrow/io/memory.h" #include "utils.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index 996f41ba94dba..cea8cbf96ea23 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -16,6 +16,7 @@ // under the License. #include "flight_sql_result_set.h" +#include #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index 77dbbb758b215..c4f47ac4b38fa 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index 6e5ed809ebb74..8e6350de66d4b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -16,6 +16,8 @@ // under the License. #include "accessors/main.h" + +#include #include "boost/functional/hash.hpp" namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index 01327dd1a8daa..c213f38b599fe 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -16,6 +16,7 @@ // under the License. #include "flight_sql_result_set_column.h" +#include #include "flight_sql_result_set.h" #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index ec366f7e71e4f..15592fdf21925 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -16,6 +16,7 @@ // under the License. #include "flight_sql_result_set_metadata.h" +#include #include "arrow/util/key_value_metadata.h" #include "utils.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index c6878cc979d92..9a1cfe2d100e9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -16,6 +16,7 @@ // under the License. #include "flight_sql_statement.h" +#include #include "flight_sql_result_set.h" #include "flight_sql_result_set_metadata.h" #include "flight_sql_statement_get_columns.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc index 3c8dde33e0b01..decb806a6d104 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc @@ -16,6 +16,7 @@ // under the License. #include "flight_sql_statement_get_columns.h" +#include #include "flight_sql_get_tables_reader.h" #include "utils.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc index f9469dfc058f3..d29870f7b15ba 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc @@ -16,6 +16,7 @@ // under the License. #include "flight_sql_statement_get_tables.h" +#include #include "arrow/flight/api.h" #include "arrow/flight/types.h" #include "flight_sql_result_set.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc index b5d1ee0e22f2e..af2c959345229 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc @@ -16,6 +16,7 @@ // under the License. #include "flight_sql_stream_chunk_iterator.h" +#include #include "utils.h" namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc index 36eaa8c239ac5..16c72b73b05ff 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc @@ -17,6 +17,8 @@ #include "get_info_cache.h" +#include + #include #include #include @@ -838,7 +840,7 @@ bool GetInfoCache::LoadInfoFromServer() { // java. constexpr int32_t COMPARISONS = 0; constexpr int32_t EXISTS = 1; - constexpr int32_t IN = 2; + constexpr int32_t INN = 2; constexpr int32_t QUANTIFIEDS = 3; uint32_t result = 0; if ((scalar_value & (1 << COMPARISONS)) != 0) { @@ -847,7 +849,7 @@ bool GetInfoCache::LoadInfoFromServer() { if ((scalar_value & (1 << EXISTS)) != 0) { result |= SQL_SQ_EXISTS; } - if ((scalar_value & (1 << IN)) != 0) { + if ((scalar_value & (1 << INN)) != 0) { result |= SQL_SQ_IN; } if ((scalar_value & (1 << QUANTIFIEDS)) != 0) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 1b7ccce6c385f..53d2592bf83d1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -16,6 +16,7 @@ // under the License. #include +#include #include "flight_sql_connection.h" #include "flight_sql_result_set.h" @@ -46,8 +47,8 @@ void TestBindColumn(const std::shared_ptr &connection) { const std::shared_ptr &result_set = statement->GetResultSet(); - int batch_size = 100; - int max_strlen = 1000; + const int batch_size = 100; + const int max_strlen = 1000; char IncidntNum[batch_size][max_strlen]; ssize_t IncidntNum_length[batch_size]; @@ -86,7 +87,7 @@ void TestGetData(const std::shared_ptr &connection) { const std::shared_ptr &result_set = statement->GetResultSet(); while (result_set->Move(1) == 1) { - int buffer_length = 1024; + const int buffer_length = 1024; char result[buffer_length]; ssize_t result_length; result_set->GetData(1, driver::odbcabstraction::CDataType_CHAR, 0, 0, @@ -110,8 +111,8 @@ void TestBindColumnBigInt(const std::shared_ptr &connection) { const std::shared_ptr &result_set = statement->GetResultSet(); - int batch_size = 100; - int max_strlen = 1000; + const int batch_size = 100; + const int max_strlen = 1000; char IncidntNum[batch_size][max_strlen]; ssize_t IncidntNum_length[batch_size]; @@ -159,11 +160,11 @@ void TestGetTablesV2(const std::shared_ptr &connection) { while (result_set->Move(1) == 1) { int buffer_length = 1024; - char result[buffer_length]; + std::vector result(buffer_length); ssize_t result_length; result_set->GetData(1, driver::odbcabstraction::CDataType_CHAR, 0, 0, - result, buffer_length, &result_length); - std::cout << result << std::endl; + result.data(), buffer_length, &result_length); + std::cout << result.data() << std::endl; } std::cout << column_count << std::endl; @@ -180,14 +181,14 @@ void TestGetColumnsV3(const std::shared_ptr &connection) { size_t column_count = metadata->GetColumnCount(); int buffer_length = 1024; - char result[buffer_length]; + std::vector result(buffer_length); ssize_t result_length; while (result_set->Move(1) == 1) { for (int i = 0; i < column_count; ++i) { result_set->GetData(1 + i, driver::odbcabstraction::CDataType_CHAR, 0, 0, - result, buffer_length, &result_length); - std::cout << result << '\t'; + result.data(), buffer_length, &result_length); + std::cout << result.data() << '\t'; } std::cout << std::endl; @@ -209,13 +210,17 @@ int main() { {FlightSqlConnection::PASSWORD, std::string("dremio123")}, }; std::vector missing_attr; - connection->Connect(properties, missing_attr); - - // TestBindColumnBigInt(connection); - // TestBindColumn(connection); - // TestGetData(connection); - // TestGetTablesV2(connection); - TestGetColumnsV3(connection); + try { + connection->Connect(properties, missing_attr); + + // TestBindColumnBigInt(connection); + // TestBindColumn(connection); + // TestGetData(connection); + // TestGetTablesV2(connection); + TestGetColumnsV3(connection); + } catch (...) { + std::cout << "error occured" << std::endl; + } connection->Close(); return 0; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/parse_table_types_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/parse_table_types_test.cc index 888fdb0eda99c..e08c9df1da824 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/parse_table_types_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/parse_table_types_test.cc @@ -16,6 +16,7 @@ // under the License #include "flight_sql_statement_get_tables.h" +#include #include "gtest/gtest.h" namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc index d51696f3dd313..69d7087bb012c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc @@ -16,6 +16,7 @@ // under the License. #include "record_batch_transformer.h" +#include #include "utils.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc index f0dabb0110fda..b1150c0fdff9c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License. +#include #include "arrow/testing/builder.h" #include "record_batch_transformer.h" #include "gtest/gtest.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.cc index 09827ad5a8ff8..26e859e282a33 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.cc @@ -17,6 +17,8 @@ #include "scalar_function_reporter.h" +#include + #include #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index b68a0e0ac3fc1..a0bd3d8e775d7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -16,6 +16,7 @@ // under the License. #include "utils.h" +#include #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc index 189edf0414723..28f6ad5c8f315 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc @@ -16,6 +16,7 @@ // under the License. #include "utils.h" +#include #include "gtest/gtest.h" namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc index 9bed126ea09ca..fdf84af7d037c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc @@ -16,6 +16,7 @@ // under the License. #include +#include #include namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h new file mode 100644 index 0000000000000..04f0480a4af1b --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h @@ -0,0 +1,28 @@ +// 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. + +#pragma once + +#if defined(_WIN32) + // NOMINMAX avoids std::min/max being defined as a c macro + #define NOMINMAX + #include + + #include + typedef SSIZE_T ssize_t; + +#endif diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h index a6f35a4d8f236..92b32d279686a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h @@ -20,6 +20,8 @@ #include #include +#include + #include namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json index ba9d3f088cd5d..22e94806a0376 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json @@ -2,13 +2,26 @@ "name": "flightsql-odbc", "version-string": "1.0.0", "dependencies": [ + "abseil", + "benchmark", + "boost-filesystem", + "boost-multiprecision", + "boost-process", + "boost-system", + "boost-crc", + "boost-optional", + "boost-variant", + "boost-xpressive", + "brotli", + "gflags", "openssl", "protobuf", "zlib", "re2", "grpc", "utf8proc", - "gtest" + "zlib", + "zstd" ], - "builtin-baseline": "b5865bfeba430cd44063fc54a45a8861195a715f" + "builtin-baseline": "4e485c34f5e056327ef00c14e2e3620bc50de098" } From 5e765b79454eae55dd5de414d3334d68d6f3aebb Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Thu, 14 Apr 2022 17:31:04 -0300 Subject: [PATCH 080/183] Fix empty cells when testing with isql This fixes the empty cells problem on isql by implementing GetColumnLabel() on flight_sql_result_set_metadata.cc. There are other metadata methods yet to implement but I will leave those to a separate PR. Change-Id: I36b6c85b96a1c518e8a659c69e12c3d59fc826dd --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 8 ++------ .../flight_sql/flight_sql_get_tables_reader.cc | 6 +++++- .../flight_sql/flight_sql_result_set_metadata.cc | 11 +++++------ .../flight_sql/flight_sql_statement_get_columns.cc | 7 +++++++ 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index aed4b573ecb7f..febdca091e4ed 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -95,12 +95,8 @@ else() ) endif() -if(NOT ARROW_GIT_REPOSITORY) - set(ARROW_GIT_REPOSITORY https://github.com/apache/arrow.git) -endif() -if(NOT ARROW_GIT_TAG) - set(ARROW_GIT_TAG master) -endif() +set(ARROW_GIT_REPOSITORY "https://github.com/apache/arrow.git" CACHE STRING "Arrow repository path or URL") +set(ARROW_GIT_TAG "master" CACHE STRING "Tag for the Arrow repository") message("Using Arrow from ${ARROW_GIT_REPOSITORY} on tag ${ARROW_GIT_TAG}") ExternalProject_Add(ApacheArrow diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc index 6e08fbad3042a..0fe3f9ea16c3b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc @@ -80,7 +80,11 @@ std::shared_ptr GetTablesReader::GetSchema() { ipc::DictionaryMemo in_memo; const Result> &result = ReadSchema(&dataset_schema_reader, &in_memo); - ThrowIfNotOK(result.status()); + if (!result.ok()) { + // TODO: Ignoring this error until we fix the problem on Dremio server + // The problem is that complex types columns are being returned without the children types. + return nullptr; + } return result.ValueOrDie(); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index 15592fdf21925..94925d73067b5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -17,6 +17,7 @@ #include "flight_sql_result_set_metadata.h" #include +#include "arrow/flight/sql/column_metadata.h" #include "arrow/util/key_value_metadata.h" #include "utils.h" @@ -39,7 +40,6 @@ std::string FlightSqlResultSetMetadata::GetColumnName(int column_position) { } std::string FlightSqlResultSetMetadata::GetName(int column_position) { - // TODO Get column alias from column metadata return schema_->field(column_position - 1)->name(); } @@ -60,8 +60,8 @@ SqlDataType FlightSqlResultSetMetadata::GetDataType(int column_position) { driver::odbcabstraction::Nullability FlightSqlResultSetMetadata::IsNullable(int column_position) { - // TODO Implement after the PR from column metadata is merged - return odbcabstraction::NULLABILITY_NO_NULLS; + const std::shared_ptr &field = schema_->field(column_position - 1); + return field->nullable() ? odbcabstraction::NULLABILITY_NULLABLE : odbcabstraction::NULLABILITY_NO_NULLS } std::string FlightSqlResultSetMetadata::GetSchemaName(int column_position) { @@ -80,13 +80,12 @@ std::string FlightSqlResultSetMetadata::GetTableName(int column_position) { } std::string FlightSqlResultSetMetadata::GetColumnLabel(int column_position) { - // TODO Implement after the PR from column metadata is merged - return ""; + return schema_->field(column_position - 1)->name(); } size_t FlightSqlResultSetMetadata::GetColumnDisplaySize( - // TODO Implement after the PR from column metadata is merged int column_position) { + // TODO Implement after the PR from column metadata is merged return 0; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc index decb806a6d104..1933b77c1ad46 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc @@ -93,6 +93,13 @@ Transform_inner(const odbcabstraction::OdbcVersion odbc_version, const auto &table_schema = reader.GetDbSchemaName(); const auto &table_name = reader.GetTableName(); const std::shared_ptr &schema = reader.GetSchema(); + if (schema == nullptr) { + // TODO: Remove this if after fixing TODO on GetTablesReader::GetSchema() + // This is because of a problem on Dremio server, where complex types columns + // are being returned without the children types, so we are simply ignoring + // it by now. + continue; + } for (int i = 0; i < schema->num_fields(); ++i) { const std::shared_ptr &field = schema->field(i); From caadfe59e262c83c2971390309f74fee7c958b4e Mon Sep 17 00:00:00 2001 From: James Duong Date: Wed, 13 Apr 2022 14:46:57 -0700 Subject: [PATCH 081/183] Statement attributes - Add support for statement attributes. - Most statement attributes are not settable for Flight, except for the query timeout - Clean-up of FlightSqlConnection and FlightSqlStatement classes. Change-Id: I15aa9d0fead7f80473cabb43e0417d84ad84d818 --- .../flight_sql/flight_sql_connection.cc | 11 +------ .../flight_sql/flight_sql_statement.cc | 33 +++++++++++++++++-- .../flight_sql/flight_sql_statement.h | 24 +++++++------- .../flightsql-odbc/flight_sql/utils.h | 5 +++ .../include/odbcabstraction/connection.h | 1 - .../include/odbcabstraction/statement.h | 15 +++++---- 6 files changed, 56 insertions(+), 33 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 1a3ff420d9c5e..11647c9a87b10 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -25,6 +25,7 @@ #include #include +#include #include #include "flight_sql_auth_method.h" @@ -70,12 +71,6 @@ TrackMissingRequiredProperty(const std::string &property, } return prop_iter; } - -template -bool CheckIfSetToOnlyValidValue(const Connection::Attribute &value, T allowed_value) { - return boost::get(value) == allowed_value; -} - } // namespace void FlightSqlConnection::Connect(const ConnPropertyMap &properties, @@ -190,8 +185,6 @@ bool FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, case ACCESS_MODE: // We will always return read-write. return CheckIfSetToOnlyValidValue(value, static_cast(SQL_MODE_READ_WRITE)); - case METADATA_ID: - return CheckIfSetToOnlyValidValue(value, static_cast(SQL_FALSE)); case PACKET_SIZE: return CheckIfSetToOnlyValidValue(value, static_cast(0)); default: @@ -206,8 +199,6 @@ FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { case ACCESS_MODE: // FlightSQL does not provide this metadata. return boost::make_optional(Attribute(static_cast(SQL_MODE_READ_WRITE))); - case METADATA_ID: - return boost::make_optional(Attribute(static_cast(SQL_FALSE))); case PACKET_SIZE: return boost::make_optional(Attribute(static_cast(0))); default: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index 9a1cfe2d100e9..21b1e14c64639 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -25,8 +25,11 @@ #include "utils.h" #include #include +#include +#include #include +#include #include namespace driver { @@ -62,11 +65,35 @@ void ClosePreparedStatementIfAny( FlightSqlStatement::FlightSqlStatement(FlightSqlClient &sql_client, FlightCallOptions call_options) - : sql_client_(sql_client), call_options_(call_options) {} + : sql_client_(sql_client), call_options_(std::move(call_options)) { + attribute_[METADATA_ID] = static_cast(SQL_FALSE); + attribute_[MAX_LENGTH] = static_cast(0); + attribute_[NOSCAN] = static_cast(SQL_NOSCAN_OFF); + attribute_[QUERY_TIMEOUT] = static_cast(0); + call_options_.timeout = TimeoutDuration{-1}; +} -void FlightSqlStatement::SetAttribute(StatementAttributeId attribute, +bool FlightSqlStatement::SetAttribute(StatementAttributeId attribute, const Attribute &value) { - attribute_[attribute] = value; + switch (attribute) { + case METADATA_ID: + return CheckIfSetToOnlyValidValue(value, static_cast(SQL_FALSE)); + case NOSCAN: + return CheckIfSetToOnlyValidValue(value, static_cast(SQL_NOSCAN_OFF)); + case MAX_LENGTH: + return CheckIfSetToOnlyValidValue(value, static_cast(0)); + case QUERY_TIMEOUT: + if (boost::get(value) > 0) { + call_options_.timeout = + TimeoutDuration{static_cast(boost::get(value))}; + } else { + call_options_.timeout = TimeoutDuration{-1}; + // Intentional fall-through. + } + default: + attribute_[attribute] = value; + return true; + } } boost::optional diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h index b51f2f7e1de52..c1ad8ce51345b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h @@ -46,38 +46,38 @@ class FlightSqlStatement : public odbcabstraction::Statement { FlightSqlStatement(arrow::flight::sql::FlightSqlClient &sql_client, arrow::flight::FlightCallOptions call_options); - void SetAttribute(StatementAttributeId attribute, const Attribute &value); + bool SetAttribute(StatementAttributeId attribute, const Attribute &value); - boost::optional GetAttribute(StatementAttributeId attribute); + boost::optional GetAttribute(StatementAttributeId attribute) override; boost::optional> - Prepare(const std::string &query); + Prepare(const std::string &query) override; - bool ExecutePrepared(); + bool ExecutePrepared() override; - bool Execute(const std::string &query); + bool Execute(const std::string &query) override; - std::shared_ptr GetResultSet(); + std::shared_ptr GetResultSet() override; - long GetUpdateCount(); + long GetUpdateCount() override; std::shared_ptr GetTables_V2(const std::string *catalog_name, const std::string *schema_name, - const std::string *table_name, const std::string *table_type); + const std::string *table_name, const std::string *table_type) override; std::shared_ptr GetTables_V3(const std::string *catalog_name, const std::string *schema_name, - const std::string *table_name, const std::string *table_type); + const std::string *table_name, const std::string *table_type) override; std::shared_ptr GetColumns_V2(const std::string *catalog_name, const std::string *schema_name, - const std::string *table_name, const std::string *column_name); + const std::string *table_name, const std::string *column_name) override; std::shared_ptr GetColumns_V3(const std::string *catalog_name, const std::string *schema_name, - const std::string *table_name, const std::string *column_name); + const std::string *table_name, const std::string *column_name) override; - std::shared_ptr GetTypeInfo(int dataType); + std::shared_ptr GetTypeInfo(int dataType) override; }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index 5881cdd4000fa..cb716c8cc2482 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -34,6 +34,11 @@ inline void ThrowIfNotOK(const arrow::Status &status) { } } +template +inline bool CheckIfSetToOnlyValidValue(const AttributeTypeT &value, T allowed_value) { + return boost::get(value) == allowed_value; +} + template arrow::Status AppendToBuilder(BUILDER &builder, optional opt_value) { if (opt_value) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index 4cb6828e0563d..2952536125d8d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -45,7 +45,6 @@ class Connection { CONNECTION_TIMEOUT, // uint32_t - The timeout for connection functions after connecting. CURRENT_CATALOG, // std::string - The current catalog LOGIN_TIMEOUT, // uint32_t - The timeout for the initial connection - METADATA_ID, // uint32_t - Modifies catalog function arguments to be identifiers PACKET_SIZE, // uint32_t - The Packet Size }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h index 650d40afe3b6d..e728a86f90cb1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h @@ -42,14 +42,13 @@ class Statement { /// \brief Statement attributes that can be called at anytime. ////TODO: Document attributes enum StatementAttributeId { - MAX_LENGTH, - MAX_ROWS, - METADATA_ID, - NOSCAN, - QUERY_TIMEOUT, + MAX_LENGTH, // size_t - The maximum length when retrieving variable length data. 0 means no limit. + METADATA_ID, // size_t - Modifies catalog function arguments to be identifiers. SQL_TRUE or SQL_FALSE. + NOSCAN, // size_t - Indicates that the driver does not scan for escape sequences. Default to SQL_NOSCAN_OFF + QUERY_TIMEOUT, // size_t - The time to wait in seconds for queries to execute. 0 to have no timeout. }; - typedef boost::variant Attribute; + typedef boost::variant Attribute; /// \brief Set a statement attribute (may be called at any time) /// @@ -57,7 +56,9 @@ class Statement { /// /// \param attribute Attribute identifier to set. /// \param value Value to be associated with the attribute. - virtual void SetAttribute(StatementAttributeId attribute, + /// \return true if the value was set successfully or false if it was substituted with + /// a similar value. + virtual bool SetAttribute(StatementAttributeId attribute, const Attribute &value) = 0; /// \brief Retrieve a statement attribute. From ad404b926f71abef4797353be8acc4c9e4f5d96e Mon Sep 17 00:00:00 2001 From: Alex McRae Date: Wed, 6 Apr 2022 14:12:43 -0700 Subject: [PATCH 082/183] Add token authentication Change-Id: I9f0cafcada5195a75f3b262eeb0a51561d2601b1 --- .../flight_sql/flight_sql_auth_method.cc | 61 ++++++++++++++++--- .../flight_sql/flight_sql_connection.cc | 1 + .../flight_sql/flight_sql_connection.h | 1 + 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 3802a2882d3cf..90d556b2c8de1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -24,6 +24,7 @@ #include #include +#include #include @@ -48,6 +49,20 @@ class NoOpAuthMethod : public FlightSqlAuthMethod { } }; +class NoOpClientAuthHandler : public arrow::flight::ClientAuthHandler { +public: + NoOpClientAuthHandler() {} + + arrow::Status Authenticate(arrow::flight::ClientAuthSender* outgoing, arrow::flight::ClientAuthReader* incoming) override { + return arrow::Status::OK(); + } + + arrow::Status GetToken(std::string* token) override { + *token = ""; + return arrow::Status::OK(); + } +}; + class UserPasswordAuthMethod : public FlightSqlAuthMethod { public: UserPasswordAuthMethod(FlightClient &client, std::string user, @@ -87,6 +102,32 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { std::string user_; std::string password_; }; + + class TokenAuthMethod : public FlightSqlAuthMethod { + private: + FlightClient &client_; + std::string token_; // this is the token the user provides + + public: + TokenAuthMethod(FlightClient &client, std::string token): client_{client}, token_{std::move(token)} {} + + void Authenticate(FlightSqlConnection &connection, FlightCallOptions &call_options) override { + // add the token to the headers + const std::pair token_header("authorization", "Bearer " + token_); + call_options.headers.push_back(token_header); + + const arrow::Status status = client_.Authenticate(call_options, std::unique_ptr(new NoOpClientAuthHandler())); + if (!status.ok()) { + const auto& flightStatus = arrow::flight::FlightStatusDetail::UnwrapStatus(status); + if (flightStatus != nullptr) { + if (flightStatus->code() == arrow::flight::FlightStatusCode::Unauthenticated) { + throw AuthenticationException("Failed to authenticate with token: " + token_ + " Message: " + status.message()); + } + } + throw odbcabstraction::DriverException(status.message()); + } + } + }; } // namespace std::unique_ptr FlightSqlAuthMethod::FromProperties( @@ -96,6 +137,8 @@ std::unique_ptr FlightSqlAuthMethod::FromProperties( // Check if should use user-password authentication auto it_user = properties.find(FlightSqlConnection::USER); auto it_password = properties.find(FlightSqlConnection::PASSWORD); + auto it_token = properties.find(FlightSqlConnection::TOKEN); + if (it_user == properties.end() || it_password == properties.end()) { // Accept UID/PWD as aliases for User/Password. These are suggested as // standard properties in the documentation for SQLDriverConnect. @@ -103,16 +146,20 @@ std::unique_ptr FlightSqlAuthMethod::FromProperties( it_password = properties.find(FlightSqlConnection::PWD); } if (it_user != properties.end() || it_password != properties.end()) { - const std::string &user = it_user != properties.end() - ? boost::get(it_user->second) - : ""; - const std::string &password = - it_password != properties.end() - ? boost::get(it_password->second) - : ""; + const std::string &user = + it_user != properties.end() + ? it_user->second + : ""; + const std::string &password = + it_password != properties.end() + ? it_password->second + : ""; return std::unique_ptr( new UserPasswordAuthMethod(*client, user, password)); + } else if (it_token != properties.end()) { + const auto& token = it_token->second; + return std::unique_ptr(new TokenAuthMethod(*client, token)); } return std::unique_ptr(new NoOpAuthMethod); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 11647c9a87b10..6549d6d706045 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -54,6 +54,7 @@ const std::string FlightSqlConnection::USER = "user"; const std::string FlightSqlConnection::UID = "uid"; const std::string FlightSqlConnection::PASSWORD = "password"; const std::string FlightSqlConnection::PWD = "pwd"; +const std::string FlightSqlConnection::TOKEN = "token"; const std::string FlightSqlConnection::USE_TLS = "useTls"; namespace { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index e827b9cb31b4f..f1ecb2c1a5708 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -44,6 +44,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { static const std::string UID; static const std::string PASSWORD; static const std::string PWD; + static const std::string TOKEN; static const std::string USE_TLS; explicit FlightSqlConnection(odbcabstraction::OdbcVersion odbc_version); From de68b5e787c38d4b9973d8b3d42bbc157f587cbb Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Mon, 28 Mar 2022 14:47:15 -0300 Subject: [PATCH 083/183] Enhance GetColumns with more metadata This enhances GetColumns response with more accurate metadata, such as: * COLUMN_SIZE / PRECISION * CHAR_OCTET_LENGTH * BUFFER_LENGTH * DECIMAL_DIGITS / SCALE Change-Id: Ibd39f634bc59acc7d75ab0f24c234d61d841aaf6 --- .../accessors/string_array_accessor.h | 12 +- .../flight_sql/flight_sql_result_set.cc | 2 +- .../flight_sql_result_set_metadata.cc | 2 +- .../flight_sql_statement_get_columns.cc | 39 ++++-- .../flightsql-odbc/flight_sql/main.cc | 2 +- .../flightsql-odbc/flight_sql/utils.cc | 119 +++++++++++++++--- .../flightsql-odbc/flight_sql/utils.h | 24 +++- .../include/odbcabstraction/types.h | 1 + 8 files changed, 154 insertions(+), 47 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h index fdc2c710a7409..960ab6bb7667a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h @@ -19,20 +19,10 @@ #include "arrow/type_fwd.h" #include "types.h" -#include +#include "utils.h" #include #include -#ifdef WITH_IODBC -typedef char32_t SqlWChar; -typedef std::u32string SqlWString; -#else -typedef char16_t SqlWChar; -typedef std::u16string SqlWString; -#endif -typedef std::wstring_convert, SqlWChar> - CharToWStrConverter; - namespace driver { namespace flight_sql { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index cea8cbf96ea23..da9242945762c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -148,7 +148,7 @@ bool FlightSqlResultSet::GetData(int column_n, CDataType target_type, // fetched, we need to subtract one from the current row. accessor->GetColumnarData(&binding, current_row_ - 1, 1, value_offset); - if (strlen_buffer) { + if (strlen_buffer && strlen_buffer[0] != odbcabstraction::NULL_DATA) { bool has_more = value_offset + buffer_length <= strlen_buffer[0]; value_offset += static_cast(buffer_length); return has_more; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index 94925d73067b5..d152c0adaca12 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -61,7 +61,7 @@ SqlDataType FlightSqlResultSetMetadata::GetDataType(int column_position) { driver::odbcabstraction::Nullability FlightSqlResultSetMetadata::IsNullable(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - return field->nullable() ? odbcabstraction::NULLABILITY_NULLABLE : odbcabstraction::NULLABILITY_NO_NULLS + return field->nullable() ? odbcabstraction::NULLABILITY_NULLABLE : odbcabstraction::NULLABILITY_NO_NULLS; } std::string FlightSqlResultSetMetadata::GetSchemaName(int column_position) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc index 1933b77c1ad46..5fdee198b3a95 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc @@ -19,10 +19,12 @@ #include #include "flight_sql_get_tables_reader.h" #include "utils.h" +#include namespace driver { namespace flight_sql { +using arrow::flight::sql::ColumnMetadata; using arrow::util::make_optional; using arrow::util::nullopt; using arrow::util::optional; @@ -84,9 +86,9 @@ Transform_inner(const odbcabstraction::OdbcVersion odbc_version, GetTablesReader reader(original); optional column_name_regex = - column_name_pattern ? make_optional(ConvertSqlPatternToRegex( - *column_name_pattern)) - : nullopt; + column_name_pattern + ? make_optional(ConvertSqlPatternToRegex(*column_name_pattern)) + : nullopt; while (reader.Next()) { const auto &table_catalog = reader.GetCatalogName(); @@ -112,6 +114,8 @@ Transform_inner(const odbcabstraction::OdbcVersion odbc_version, odbcabstraction::SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + ColumnMetadata metadata(field->metadata()); + data.table_cat = table_catalog; data.table_schem = table_schema; data.table_name = table_name; @@ -119,21 +123,32 @@ Transform_inner(const odbcabstraction::OdbcVersion odbc_version, data.data_type = odbc_version == odbcabstraction::V_3 ? data_type_v3 : GetDataTypeFromArrowField_V2(field); - data.type_name = GetTypeNameFromSqlDataType(data_type_v3); - // TODO: Get from field's metadata "ARROW:FLIGHT:SQL:PRECISION" - data.column_size = nullopt; - // TODO: Get from column_size - data.buffer_length = nullopt; - // TODO: Get from field's metadata "ARROW:FLIGHT:SQL:SCALE" - data.decimal_digits = nullopt; + + // TODO: Use `metadata.GetTypeName()` when ARROW-16064 is merged. + const auto &type_name_result = field->metadata()->Get("ARROW:FLIGHT:SQL:TYPE_NAME"); + data.type_name = type_name_result.ok() ? + type_name_result.ValueOrDie() : + GetTypeNameFromSqlDataType(data_type_v3); + + const Result &precision_result = metadata.GetPrecision(); + data.column_size = precision_result.ok() + ? make_optional(precision_result.ValueOrDie()) + : nullopt; + data.char_octet_length = + GetCharOctetLength(data_type_v3, data.column_size); + + data.buffer_length = GetBufferLength(data_type_v3, data.column_size); + + const Result &scale_result = metadata.GetScale(); + data.decimal_digits = scale_result.ok() + ? make_optional(scale_result.ValueOrDie()) + : nullopt; data.num_prec_radix = GetRadixFromSqlDataType(data_type_v3); data.nullable = field->nullable(); data.remarks = nullopt; data.column_def = nullopt; data.sql_data_type = GetNonConciseDataType(data_type_v3); data.sql_datetime_sub = GetSqlDateTimeSubCode(data_type_v3); - // TODO: Get from column_size - data.char_octet_length = nullopt; data.ordinal_position = i + 1; data.is_nullable = field->nullable() ? "YES" : "NO"; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 53d2592bf83d1..f6ee52d405ee8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -188,7 +188,7 @@ void TestGetColumnsV3(const std::shared_ptr &connection) { for (int i = 0; i < column_count; ++i) { result_set->GetData(1 + i, driver::odbcabstraction::CDataType_CHAR, 0, 0, result.data(), buffer_length, &result_length); - std::cout << result.data() << '\t'; + std::cout << (result_length != -1 ? result.data() : "NULL") << '\t'; } std::cout << std::endl; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index a0bd3d8e775d7..6c00f218bc65f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -189,7 +189,8 @@ std::string GetTypeNameFromSqlDataType(int16_t data_type) { std::to_string(data_type)); } -optional GetRadixFromSqlDataType(int16_t data_type) { +optional +GetRadixFromSqlDataType(odbcabstraction::SqlDataType data_type) { switch (data_type) { case SqlDataType_DECIMAL: case SqlDataType_NUMERIC: @@ -207,7 +208,7 @@ optional GetRadixFromSqlDataType(int16_t data_type) { } } -int16_t GetNonConciseDataType(int16_t data_type) { +int16_t GetNonConciseDataType(odbcabstraction::SqlDataType data_type) { switch (data_type) { case SqlDataType_TYPE_DATE: case SqlDataType_TYPE_TIME: @@ -232,7 +233,7 @@ int16_t GetNonConciseDataType(int16_t data_type) { } } -optional GetSqlDateTimeSubCode(int16_t data_type) { +optional GetSqlDateTimeSubCode(SqlDataType data_type) { switch (data_type) { case SqlDataType_TYPE_DATE: return SqlDateTimeSubCode_DATE; @@ -271,6 +272,88 @@ optional GetSqlDateTimeSubCode(int16_t data_type) { } } +optional GetCharOctetLength(SqlDataType data_type, + const optional& column_size) { + switch (data_type) { + case SqlDataType_CHAR: + case SqlDataType_VARCHAR: + case SqlDataType_LONGVARCHAR: + return column_size.has_value() ? column_size.value() : NO_TOTAL; + case SqlDataType_WCHAR: + case SqlDataType_WVARCHAR: + case SqlDataType_WLONGVARCHAR: + return column_size.has_value() ? (column_size.value() * sizeof(SqlWChar)) + : NO_TOTAL; + case SqlDataType_BINARY: + case SqlDataType_VARBINARY: + case SqlDataType_LONGVARBINARY: + return column_size.has_value() ? column_size.value() : NO_TOTAL; + default: + return arrow::util::nullopt; + } +} + +optional GetBufferLength(SqlDataType data_type, + const optional& column_size) { + switch (data_type) { + case SqlDataType_CHAR: + case SqlDataType_VARCHAR: + case SqlDataType_LONGVARCHAR: + return column_size; + case SqlDataType_WCHAR: + case SqlDataType_WVARCHAR: + case SqlDataType_WLONGVARCHAR: + return column_size.has_value() ? arrow::util::make_optional(column_size.value() * sizeof(SqlWChar)) + : arrow::util::nullopt; + case SqlDataType_BINARY: + case SqlDataType_VARBINARY: + case SqlDataType_LONGVARBINARY: + return column_size; + case SqlDataType_DECIMAL: + return 19; // The same as sizeof(SQL_NUMERIC_STRUCT) + case SqlDataType_NUMERIC: + return 19; // The same as sizeof(SQL_NUMERIC_STRUCT) + case SqlDataType_BIT: + case SqlDataType_TINYINT: + return 1; + case SqlDataType_SMALLINT: + return 2; + case SqlDataType_INTEGER: + return 4; + case SqlDataType_BIGINT: + return 8; + case SqlDataType_REAL: + return 4; + case SqlDataType_FLOAT: + case SqlDataType_DOUBLE: + return 8; + case SqlDataType_TYPE_DATE: + return 6; // The same as sizeof(SQL_DATE_STRUCT) + case SqlDataType_TYPE_TIME: + return 6; // The same as sizeof(SQL_TIME_STRUCT) + case SqlDataType_TYPE_TIMESTAMP: + return 16; // The same as sizeof(SQL_TIME_STRUCT) + case SqlDataType_INTERVAL_MONTH: + case SqlDataType_INTERVAL_YEAR: + case SqlDataType_INTERVAL_YEAR_TO_MONTH: + case SqlDataType_INTERVAL_DAY: + case SqlDataType_INTERVAL_HOUR: + case SqlDataType_INTERVAL_MINUTE: + case SqlDataType_INTERVAL_SECOND: + case SqlDataType_INTERVAL_DAY_TO_HOUR: + case SqlDataType_INTERVAL_DAY_TO_MINUTE: + case SqlDataType_INTERVAL_DAY_TO_SECOND: + case SqlDataType_INTERVAL_HOUR_TO_MINUTE: + case SqlDataType_INTERVAL_HOUR_TO_SECOND: + case SqlDataType_INTERVAL_MINUTE_TO_SECOND: + return 28; // The same as sizeof(SQL_INTERVAL_STRUCT) + case SqlDataType_GUID: + return 16; + default: + return arrow::util::nullopt; + } +} + std::string ConvertSqlPatternToRegexString(const std::string &pattern) { static const std::string specials = "[]()|^-+*?{}$\\."; @@ -284,21 +367,21 @@ std::string ConvertSqlPatternToRegexString(const std::string &pattern) { } switch (c) { - case '\\': - escape = true; - break; - case '_': - regex_str += '.'; - break; - case '%': - regex_str += ".*"; - break; - default: - if (specials.find(c) != std::string::npos) { - regex_str += '\\'; - } - regex_str += c; - break; + case '\\': + escape = true; + break; + case '_': + regex_str += '.'; + break; + case '%': + regex_str += ".*"; + break; + default: + if (specials.find(c) != std::string::npos) { + regex_str += '\\'; + } + regex_str += c; + break; } } return regex_str; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index cb716c8cc2482..e960819397964 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,16 @@ namespace flight_sql { using arrow::util::optional; +#ifdef WITH_IODBC +using SqlWChar = char32_t; +using SqlWString = std::u32string; +#else +using SqlWChar = char16_t; +using SqlWString = std::u16string; +#endif +using CharToWStrConverter = + std::wstring_convert, SqlWChar>; + inline void ThrowIfNotOK(const arrow::Status &status) { if (!status.ok()) { throw odbcabstraction::DriverException(status.ToString()); @@ -61,11 +72,18 @@ GetDataTypeFromArrowField_V2(const std::shared_ptr &field); std::string GetTypeNameFromSqlDataType(int16_t data_type); -optional GetRadixFromSqlDataType(int16_t data_type); +optional +GetRadixFromSqlDataType(odbcabstraction::SqlDataType data_type); + +int16_t GetNonConciseDataType(odbcabstraction::SqlDataType data_type); + +optional GetSqlDateTimeSubCode(odbcabstraction::SqlDataType data_type); -int16_t GetNonConciseDataType(int16_t data_type); +optional GetCharOctetLength(odbcabstraction::SqlDataType data_type, + const optional& column_size); -optional GetSqlDateTimeSubCode(int16_t data_type); +optional GetBufferLength(odbcabstraction::SqlDataType data_type, + const optional& column_size); std::string ConvertSqlPatternToRegexString(const std::string &pattern); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 2172477050f2a..c73da7a01e093 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -120,6 +120,7 @@ enum Updatability { }; constexpr int NULL_DATA = -1; +constexpr int NO_TOTAL = -4; } // namespace odbcabstraction } // namespace driver From d4d41de6e5fac5359398f5ac021919f37ebb9ed1 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Wed, 20 Apr 2022 14:43:02 -0300 Subject: [PATCH 084/183] DX-49087: Convert complex type scalars to JSON This adds to the ODBC driver the capability of handling complex/nested Arrow arrays as strings, allowing ODBC application to retrieve them as C type CHAR or WCHAR. Change-Id: I4ee73cb27972eb204c8d705c9dcf0e8ce663590a --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 5 + .../flight_sql_result_set_column.cc | 12 + .../flight_sql_stream_chunk_iterator.cc | 4 +- .../flight_sql/json_converter.cc | 335 ++++++++++++++++++ .../flight_sql/json_converter.h | 31 ++ .../flight_sql/json_converter_test.cc | 189 ++++++++++ .../flightsql-odbc/flight_sql/utils.cc | 3 +- .../flightsql-odbc/vcpkg.json | 3 +- 8 files changed, 578 insertions(+), 4 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index febdca091e4ed..b84be839a81ed 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -54,6 +54,8 @@ endif() # Add gRPC dependencies needed by Arrow Flight. Should be pre-installed. find_package(gRPC 1.36 CONFIG REQUIRED) +find_package(RapidJSON CONFIG REQUIRED) + SET(Arrow_STATIC ON) # Get Arrow using git. @@ -141,6 +143,7 @@ set(ARROW_ODBC_SPI_SOURCES flight_sql_get_tables_reader.cc flight_sql_stream_chunk_iterator.cc get_info_cache.cc + json_converter.cc record_batch_transformer.cc scalar_function_reporter.cc utils.cc @@ -170,6 +173,7 @@ set(ARROW_ODBC_SPI_THIRDPARTY_LIBS ${ZLIB_LIBRARIES} ${Protobuf_LIBRARIES} ${OPENSSL_LIBRARIES} + ${RapidJSON_LIBRARIES} ) add_library(arrow_odbc_spi_impl ${ARROW_ODBC_SPI_SOURCES}) @@ -205,6 +209,7 @@ set(ARROW_ODBC_SPI_TEST_SOURCES accessors/string_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 ) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index c213f38b599fe..ac0c76f901ac9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -18,6 +18,7 @@ #include "flight_sql_result_set_column.h" #include #include "flight_sql_result_set.h" +#include "json_converter.h" #include #include #include @@ -63,6 +64,17 @@ ConvertCToArrowDataType(odbcabstraction::CDataType data_type) { std::shared_ptr CastArray(const std::shared_ptr &original_array, CDataType target_type) { + Type::type type = original_array->type_id(); + auto is_complex = type == Type::LIST || type == Type::FIXED_SIZE_LIST || type == Type::LARGE_LIST + || type == Type::MAP || type == Type::STRUCT; + if (is_complex && + (target_type == odbcabstraction::CDataType_CHAR || target_type == odbcabstraction::CDataType_WCHAR)) { + const auto &result = ConvertToJson(original_array); + ThrowIfNotOK(result.status()); + + return result.ValueOrDie(); + } + const std::shared_ptr &target_arrow_type = ConvertCToArrowDataType(target_type); if (original_array->type()->Equals(target_arrow_type)) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc index af2c959345229..24dcf509a7716 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc @@ -46,7 +46,9 @@ FlightStreamChunkIterator::~FlightStreamChunkIterator() { Close(); } bool FlightStreamChunkIterator::GetNext(FlightStreamChunk *chunk) { chunk->data = nullptr; while (stream_readers_it_ != stream_readers_.end()) { - ThrowIfNotOK((*stream_readers_it_)->Next(chunk)); + const auto &chunk_result = (*stream_readers_it_)->Next(); + ThrowIfNotOK(chunk_result.status()); + chunk->data = chunk_result.ValueOrDie().data; if (chunk->data != nullptr) { return true; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc new file mode 100644 index 0000000000000..71381ad9129ec --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc @@ -0,0 +1,335 @@ +// 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 "json_converter.h" + +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include + +using namespace arrow; +using namespace boost::beast::detail; +using driver::flight_sql::ThrowIfNotOK; + +namespace { +class ScalarToJson : public arrow::ScalarVisitor { +private: + rapidjson::StringBuffer string_buffer_; + rapidjson::Writer writer_{string_buffer_}; + +public: + void Reset() { + string_buffer_.Clear(); + writer_.Reset(string_buffer_); + } + + std::string ToString() { + return string_buffer_.GetString(); + } + + Status Visit(const NullScalar &scalar) override { + writer_.Null(); + + return Status::OK(); + } + + Status Visit(const BooleanScalar &scalar) override { + writer_.Bool(scalar.value); + + return Status::OK(); + } + + Status Visit(const Int8Scalar &scalar) override { + writer_.Int(scalar.value); + + return Status::OK(); + } + + Status Visit(const Int16Scalar &scalar) override { + writer_.Int(scalar.value); + + return Status::OK(); + } + + Status Visit(const Int32Scalar &scalar) override { + writer_.Int(scalar.value); + + return Status::OK(); + } + + Status Visit(const Int64Scalar &scalar) override { + writer_.Int64(scalar.value); + + return Status::OK(); + } + + Status Visit(const UInt8Scalar &scalar) override { + writer_.Uint(scalar.value); + + return Status::OK(); + } + + Status Visit(const UInt16Scalar &scalar) override { + writer_.Uint(scalar.value); + + return Status::OK(); + } + + Status Visit(const UInt32Scalar &scalar) override { + writer_.Uint(scalar.value); + + return Status::OK(); + } + + Status Visit(const UInt64Scalar &scalar) override { + writer_.Uint64(scalar.value); + + return Status::OK(); + } + + Status Visit(const HalfFloatScalar &scalar) override { + return Status::NotImplemented("Cannot convert HalfFloatScalar to JSON."); + } + + Status Visit(const FloatScalar &scalar) override { + writer_.Double(scalar.value); + + return Status::OK(); + } + + Status Visit(const DoubleScalar &scalar) override { + writer_.Double(scalar.value); + + return Status::OK(); + } + + Status Visit(const StringScalar &scalar) override { + const auto &view = scalar.view(); + writer_.String(view.data(), view.length()); + + return Status::OK(); + } + + Status Visit(const BinaryScalar &scalar) override { + const auto &view = scalar.view(); + size_t encoded_size = base64::encoded_size(view.length()); + char* encoded = new char[encoded_size]; + base64::encode(encoded, view.data(), view.length()); + writer_.String(encoded, encoded_size); + + return Status::OK(); + } + + Status Visit(const LargeStringScalar &scalar) override { + const auto &view = scalar.view(); + writer_.String(view.data(), view.length()); + + return Status::OK(); + } + + Status Visit(const LargeBinaryScalar &scalar) override { + const auto &view = scalar.view(); + size_t encoded_size = base64::encoded_size(view.length()); + char* encoded = new char[encoded_size]; + base64::encode(encoded, view.data(), view.length()); + writer_.String(encoded, encoded_size); + + return Status::OK(); + } + + Status Visit(const FixedSizeBinaryScalar &scalar) override { + const auto &view = scalar.view(); + size_t encoded_size = base64::encoded_size(view.length()); + char* encoded = new char[encoded_size]; + base64::encode(encoded, view.data(), view.length()); + writer_.String(encoded, encoded_size); + + return Status::OK(); + } + + Status Visit(const Date64Scalar &scalar) override { + ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) + return string_scalar->Accept(this); + } + + Status Visit(const Date32Scalar &scalar) override { + ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) + return string_scalar->Accept(this); + } + + Status Visit(const Time32Scalar &scalar) override { + ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) + return string_scalar->Accept(this); + } + + Status Visit(const Time64Scalar &scalar) override { + ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) + return string_scalar->Accept(this); + } + + Status Visit(const TimestampScalar &scalar) override { + ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) + return string_scalar->Accept(this); + } + + Status Visit(const DayTimeIntervalScalar &scalar) override { + ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) + return string_scalar->Accept(this); + } + + Status Visit(const MonthDayNanoIntervalScalar &scalar) override { + ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) + return string_scalar->Accept(this); + } + + Status Visit(const MonthIntervalScalar &scalar) override { + ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) + return string_scalar->Accept(this); + } + + Status Visit(const DurationScalar &scalar) override { + // TODO: Append TimeUnit on conversion + ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) + return string_scalar->Accept(this); + } + + Status Visit(const Decimal128Scalar &scalar) override { + return Status::NotImplemented("Cannot convert Decimal128Scalar to JSON."); + } + + Status Visit(const Decimal256Scalar &scalar) override { + return Status::NotImplemented("Cannot convert Decimal256Scalar to JSON."); + } + + Status Visit(const ListScalar &scalar) override { + writer_.StartArray(); + for (int i = 0; i < scalar.value->length(); ++i) { + const auto &result = scalar.value->GetScalar(i); + ThrowIfNotOK(result.status()); + ThrowIfNotOK(result.ValueOrDie()->Accept(this)); + } + + writer_.EndArray(); + + return Status::OK(); + } + + Status Visit(const LargeListScalar &scalar) override { + writer_.StartArray(); + for (int i = 0; i < scalar.value->length(); ++i) { + const auto &result = scalar.value->GetScalar(i); + ThrowIfNotOK(result.status()); + ThrowIfNotOK(result.ValueOrDie()->Accept(this)); + } + + writer_.EndArray(); + + return Status::OK(); + } + + Status Visit(const MapScalar &scalar) override { + writer_.StartArray(); + for (int i = 0; i < scalar.value->length(); ++i) { + const auto &result = scalar.value->GetScalar(i); + ThrowIfNotOK(result.status()); + ThrowIfNotOK(result.ValueOrDie()->Accept(this)); + } + + writer_.EndArray(); + + return Status::OK(); + } + + Status Visit(const FixedSizeListScalar &scalar) override { + writer_.StartArray(); + for (int i = 0; i < scalar.value->length(); ++i) { + const auto &result = scalar.value->GetScalar(i); + ThrowIfNotOK(result.status()); + ThrowIfNotOK(result.ValueOrDie()->Accept(this)); + } + + writer_.EndArray(); + + return Status::OK(); + } + + Status Visit(const StructScalar &scalar) override { + writer_.StartObject(); + + const std::shared_ptr &data_type = std::static_pointer_cast(scalar.type); + for (int i = 0; i < data_type->num_fields(); ++i) { + writer_.Key(data_type->field(i)->name().c_str()); + + const auto &result = scalar.field(i); + ThrowIfNotOK(result.status()); + ThrowIfNotOK(result.ValueOrDie()->Accept(this)); + } + + writer_.EndObject(); + + return Status::OK(); + } + + Status Visit(const DictionaryScalar &scalar) override { + return Status::NotImplemented("Cannot convert DictionaryScalar to JSON."); + } + + Status Visit(const SparseUnionScalar &scalar) override { + return scalar.value->Accept(this); + } + + Status Visit(const DenseUnionScalar &scalar) override { + return scalar.value->Accept(this); + } + + Status Visit(const ExtensionScalar &scalar) override { + return Status::NotImplemented("Cannot convert ExtensionScalar to JSON."); + } +}; +} + +namespace driver { +namespace flight_sql { + +std::string ConvertToJson(const arrow::Scalar &scalar) { + static thread_local ScalarToJson converter; + converter.Reset(); + ThrowIfNotOK(scalar.Accept(&converter)); + + return converter.ToString(); +} + +arrow::Result> ConvertToJson(const std::shared_ptr& input) { + arrow::StringBuilder builder; + int64_t length = input->length(); + RETURN_NOT_OK(builder.ReserveData(length)); + + for (int i = 0; i < length; ++i) { + ARROW_ASSIGN_OR_RAISE(auto scalar, input->GetScalar(i)) + RETURN_NOT_OK(builder.Append(ConvertToJson(*scalar))); + } + + return builder.Finish(); +} + +} +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.h new file mode 100644 index 0000000000000..590785cefbc8d --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.h @@ -0,0 +1,31 @@ +// 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. + +#pragma once + +#include +#include + +namespace driver { +namespace flight_sql { + +std::string ConvertToJson(const arrow::Scalar& scalar); + +arrow::Result> ConvertToJson(const std::shared_ptr& input); + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc new file mode 100644 index 0000000000000..2d090f31720c2 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc @@ -0,0 +1,189 @@ +// 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 "json_converter.h" + +#include "gtest/gtest.h" +#include "arrow/testing/builder.h" +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; + +TEST(ConvertToJson, String) { + ASSERT_EQ("\"\"", ConvertToJson(StringScalar(""))); + ASSERT_EQ("\"string\"", ConvertToJson(StringScalar("string"))); + ASSERT_EQ("\"string\\\"\"", ConvertToJson(StringScalar("string\""))); +} + +TEST(ConvertToJson, LargeString) { + ASSERT_EQ("\"\"", ConvertToJson(LargeStringScalar(""))); + ASSERT_EQ("\"string\"", ConvertToJson(LargeStringScalar("string"))); + ASSERT_EQ("\"string\\\"\"", ConvertToJson(LargeStringScalar("string\""))); +} + +TEST(ConvertToJson, Binary) { + ASSERT_EQ("\"\"", ConvertToJson(BinaryScalar(""))); + ASSERT_EQ("\"c3RyaW5n\"", ConvertToJson(BinaryScalar("string"))); + ASSERT_EQ("\"c3RyaW5nIg==\"", ConvertToJson(BinaryScalar("string\""))); +} + +TEST(ConvertToJson, LargeBinary) { + ASSERT_EQ("\"\"", ConvertToJson(LargeBinaryScalar(""))); + ASSERT_EQ("\"c3RyaW5n\"", ConvertToJson(LargeBinaryScalar("string"))); + ASSERT_EQ("\"c3RyaW5nIg==\"", ConvertToJson(LargeBinaryScalar("string\""))); +} + +TEST(ConvertToJson, FixedSizeBinary) { + ASSERT_EQ("\"\"", ConvertToJson(FixedSizeBinaryScalar(""))); + ASSERT_EQ("\"c3RyaW5n\"", ConvertToJson(FixedSizeBinaryScalar("string"))); + ASSERT_EQ("\"c3RyaW5nIg==\"", ConvertToJson(FixedSizeBinaryScalar("string\""))); +} + +TEST(ConvertToJson, Int8) { + ASSERT_EQ("127", ConvertToJson(Int8Scalar(127))); + ASSERT_EQ("-128", ConvertToJson(Int8Scalar(-128))); +} + +TEST(ConvertToJson, Int16) { + ASSERT_EQ("32767", ConvertToJson(Int16Scalar(32767))); + ASSERT_EQ("-32768", ConvertToJson(Int16Scalar(-32768))); +} + +TEST(ConvertToJson, Int32) { + ASSERT_EQ("2147483647", ConvertToJson(Int32Scalar(2147483647))); + ASSERT_EQ("-2147483648", ConvertToJson(Int32Scalar(-2147483648))); +} + +TEST(ConvertToJson, Int64) { + ASSERT_EQ("9223372036854775807", ConvertToJson(Int64Scalar(9223372036854775807LL))); + ASSERT_EQ("-9223372036854775808", ConvertToJson(Int64Scalar(-9223372036854775808ULL))); +} + +TEST(ConvertToJson, UInt8) { + ASSERT_EQ("127", ConvertToJson(UInt8Scalar(127))); + ASSERT_EQ("255", ConvertToJson(UInt8Scalar(255))); +} + +TEST(ConvertToJson, UInt16) { + ASSERT_EQ("32767", ConvertToJson(UInt16Scalar(32767))); + ASSERT_EQ("65535", ConvertToJson(UInt16Scalar(65535))); +} + +TEST(ConvertToJson, UInt32) { + ASSERT_EQ("2147483647", ConvertToJson(UInt32Scalar(2147483647))); + ASSERT_EQ("4294967295", ConvertToJson(UInt32Scalar(4294967295))); +} + +TEST(ConvertToJson, UInt64) { + ASSERT_EQ("9223372036854775807", ConvertToJson(UInt64Scalar(9223372036854775807LL))); + ASSERT_EQ("18446744073709551615", ConvertToJson(UInt64Scalar(18446744073709551615ULL))); +} + +TEST(ConvertToJson, Float) { + ASSERT_EQ("1.5", ConvertToJson(FloatScalar(1.5))); + ASSERT_EQ("-1.5", ConvertToJson(FloatScalar(-1.5))); +} + +TEST(ConvertToJson, Double) { + ASSERT_EQ("1.5", ConvertToJson(DoubleScalar(1.5))); + ASSERT_EQ("-1.5", ConvertToJson(DoubleScalar(-1.5))); +} + +TEST(ConvertToJson, Boolean) { + ASSERT_EQ("true", ConvertToJson(BooleanScalar(true))); + ASSERT_EQ("false", ConvertToJson(BooleanScalar(false))); +} + +TEST(ConvertToJson, Null) { + ASSERT_EQ("null", ConvertToJson(NullScalar())); +} + +TEST(ConvertToJson, Date32) { + ASSERT_EQ("\"1969-12-31\"", ConvertToJson(Date32Scalar(-1))); + ASSERT_EQ("\"1970-01-01\"", ConvertToJson(Date32Scalar(0))); + ASSERT_EQ("\"2022-01-01\"", ConvertToJson(Date32Scalar(18993))); +} + +TEST(ConvertToJson, Date64) { + ASSERT_EQ("\"1969-12-31\"", ConvertToJson(Date64Scalar(-86400000))); + ASSERT_EQ("\"1970-01-01\"", ConvertToJson(Date64Scalar(0))); + ASSERT_EQ("\"2022-01-01\"", ConvertToJson(Date64Scalar(1640995200000))); +} + +TEST(ConvertToJson, Time32) { + ASSERT_EQ("\"00:00:00\"", ConvertToJson(Time32Scalar(0, TimeUnit::SECOND))); + ASSERT_EQ("\"01:02:03\"", ConvertToJson(Time32Scalar(3723, TimeUnit::SECOND))); + ASSERT_EQ("\"00:00:00.123\"", ConvertToJson(Time32Scalar(123, TimeUnit::MILLI))); +} + +TEST(ConvertToJson, Time64) { + ASSERT_EQ("\"00:00:00.123456\"", ConvertToJson(Time64Scalar(123456, TimeUnit::MICRO))); + ASSERT_EQ("\"00:00:00.123456789\"", ConvertToJson(Time64Scalar(123456789, TimeUnit::NANO))); +} + +TEST(ConvertToJson, Timestamp) { + ASSERT_EQ("\"1969-12-31 00:00:00.000\"", ConvertToJson(TimestampScalar(-86400000, TimeUnit::MILLI))); + ASSERT_EQ("\"1970-01-01 00:00:00.000\"", ConvertToJson(TimestampScalar(0, TimeUnit::MILLI))); + ASSERT_EQ("\"2022-01-01 00:00:00.000\"", ConvertToJson(TimestampScalar(1640995200000, TimeUnit::MILLI))); + ASSERT_EQ("\"2022-01-01 00:00:01.234\"", ConvertToJson(TimestampScalar(1640995201234, TimeUnit::MILLI))); +} + +TEST(ConvertToJson, DayTimeInterval) { + ASSERT_EQ("\"123d0ms\"", ConvertToJson(DayTimeIntervalScalar({123, 0}))); + ASSERT_EQ("\"1d234ms\"", ConvertToJson(DayTimeIntervalScalar({1, 234}))); +} + +TEST(ConvertToJson, MonthDayNanoInterval) { + ASSERT_EQ("\"12M34d56ns\"", ConvertToJson(MonthDayNanoIntervalScalar({12, 34, 56}))); +} + +TEST(ConvertToJson, MonthInterval) { + ASSERT_EQ("\"1M\"", ConvertToJson(MonthIntervalScalar(1))); +} + +TEST(ConvertToJson, Duration) { + // TODO: Append TimeUnit on conversion + ASSERT_EQ("\"123\"", ConvertToJson(DurationScalar(123, TimeUnit::SECOND))); + ASSERT_EQ("\"123\"", ConvertToJson(DurationScalar(123, TimeUnit::MILLI))); + ASSERT_EQ("\"123\"", ConvertToJson(DurationScalar(123, TimeUnit::MICRO))); + ASSERT_EQ("\"123\"", ConvertToJson(DurationScalar(123, TimeUnit::NANO))); +} + +TEST(ConvertToJson, Lists) { + std::vector values = {"ABC", "DEF", "XYZ"}; + std::shared_ptr array; + ArrayFromVector(values, &array); + + const char *expected_string = R"(["ABC","DEF","XYZ"])"; + ASSERT_EQ(expected_string, ConvertToJson(ListScalar{array})); + ASSERT_EQ(expected_string, ConvertToJson(FixedSizeListScalar{array})); + ASSERT_EQ(expected_string, ConvertToJson(LargeListScalar{array})); +} + +TEST(ConvertToJson, Struct) { + auto i32 = MakeScalar(1); + auto f64 = MakeScalar(2.5); + auto str = MakeScalar("yo"); + ASSERT_OK_AND_ASSIGN(auto scalar, StructScalar::Make({i32, f64, str}, {"i", "f", "s"})); + ASSERT_EQ("{\"i\":1,\"f\":2.5,\"s\":\"yo\"}", ConvertToJson(*scalar)); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 6c00f218bc65f..096f010c723a4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -87,8 +87,7 @@ GetDataTypeFromArrowField_V3(const std::shared_ptr &field) { break; } - throw driver::odbcabstraction::DriverException("Unsupported data type: " + - type->ToString()); + return odbcabstraction::SqlDataType_VARCHAR; } int16_t diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json index 22e94806a0376..3dc1ad7a558ca 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json @@ -21,7 +21,8 @@ "grpc", "utf8proc", "zlib", - "zstd" + "zstd", + "rapidjson" ], "builtin-baseline": "4e485c34f5e056327ef00c14e2e3620bc50de098" } From 6c5b83d91e4b4682eb7cca1db76b47413ca66ed3 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Fri, 29 Apr 2022 13:55:51 -0300 Subject: [PATCH 085/183] Implement more accurate info on ResultSetMetadata This implements the rest of methods on FlightSqlResultSetMetadata class using the metadata available on Arrow schemas from Flight SQL queries Change-Id: Ifbe9b6b329cab28089081d108ebc7f246bb08688 --- .../flight_sql_result_set_metadata.cc | 121 ++++++++++++------ .../flightsql-odbc/flight_sql/utils.cc | 61 +++++++++ .../flightsql-odbc/flight_sql/utils.h | 3 + 3 files changed, 147 insertions(+), 38 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index d152c0adaca12..13a2ec2e66561 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -30,6 +30,10 @@ namespace flight_sql { using namespace odbcabstraction; using arrow::DataType; using arrow::Field; +using arrow::util::make_optional; +using arrow::util::nullopt; + +constexpr int32_t StringColumnLength = 1024; // TODO: Get from connection size_t FlightSqlResultSetMetadata::GetColumnCount() { return schema_->num_fields(); @@ -44,13 +48,17 @@ std::string FlightSqlResultSetMetadata::GetName(int column_position) { } size_t FlightSqlResultSetMetadata::GetPrecision(int column_position) { - // TODO Implement after the PR from column metadata is merged - return 0; + arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + const auto &result = metadata.GetPrecision(); + ThrowIfNotOK(result.status()); + return result.ValueOrDie(); } size_t FlightSqlResultSetMetadata::GetScale(int column_position) { - // TODO Implement after the PR from column metadata is merged - return 0; + arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + const auto &result = metadata.GetScale(); + ThrowIfNotOK(result.status()); + return result.ValueOrDie(); } SqlDataType FlightSqlResultSetMetadata::GetDataType(int column_position) { @@ -65,18 +73,21 @@ FlightSqlResultSetMetadata::IsNullable(int column_position) { } std::string FlightSqlResultSetMetadata::GetSchemaName(int column_position) { - // TODO Implement after the PR from column metadata is merged - return ""; + arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + + return metadata.GetSchemaName().ValueOrElse([] { return ""; }); } std::string FlightSqlResultSetMetadata::GetCatalogName(int column_position) { - // TODO Implement after the PR from column metadata is merged - return ""; + arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + + return metadata.GetCatalogName().ValueOrElse([] { return ""; }); } std::string FlightSqlResultSetMetadata::GetTableName(int column_position) { - // TODO Implement after the PR from column metadata is merged - return ""; + arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + + return metadata.GetTableName().ValueOrElse([] { return ""; }); } std::string FlightSqlResultSetMetadata::GetColumnLabel(int column_position) { @@ -85,18 +96,22 @@ std::string FlightSqlResultSetMetadata::GetColumnLabel(int column_position) { size_t FlightSqlResultSetMetadata::GetColumnDisplaySize( int column_position) { - // TODO Implement after the PR from column metadata is merged - return 0; + const std::shared_ptr &field = schema_->field(column_position - 1); + arrow::flight::sql::ColumnMetadata metadata(field->metadata()); + + int32_t column_size = metadata.GetPrecision().ValueOrElse([] { return StringColumnLength; }); + SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + + return GetDisplaySize(data_type_v3, column_size).value_or(NO_TOTAL); } std::string FlightSqlResultSetMetadata::GetBaseColumnName(int column_position) { - // TODO Implement after the PR from column metadata is merged - return ""; + return schema_->field(column_position - 1)->name(); } std::string FlightSqlResultSetMetadata::GetBaseTableName(int column_position) { - // TODO Implement after the PR from column metadata is merged - return ""; + arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + return metadata.GetTableName().ValueOrElse([] { return ""; }); } std::string FlightSqlResultSetMetadata::GetConciseType(int column_position) { @@ -105,69 +120,99 @@ std::string FlightSqlResultSetMetadata::GetConciseType(int column_position) { } size_t FlightSqlResultSetMetadata::GetLength(int column_position) { - // TODO Implement after the PR from column metadata is merged - return 0; + const std::shared_ptr &field = schema_->field(column_position - 1); + arrow::flight::sql::ColumnMetadata metadata(field->metadata()); + + int32_t column_size = metadata.GetPrecision().ValueOrElse([] { return StringColumnLength; }); + SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + + return GetBufferLength(data_type_v3, column_size).value_or(NO_TOTAL); } std::string FlightSqlResultSetMetadata::GetLiteralPrefix(int column_position) { - // TODO Implement after the PR from column metadata is merged + // TODO: Flight SQL column metadata does not have this, should we add to the spec? return ""; } std::string FlightSqlResultSetMetadata::GetLiteralSuffix(int column_position) { - // TODO Implement after the PR from column metadata is merged + // TODO: Flight SQL column metadata does not have this, should we add to the spec? return ""; } std::string FlightSqlResultSetMetadata::GetLocalTypeName(int column_position) { - // TODO Implement after the PR from column metadata is merged - return ""; + arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + + // TODO: Is local type name the same as type name? + return metadata.GetTypeName().ValueOrElse([] { return ""; }); } size_t FlightSqlResultSetMetadata::GetNumPrecRadix(int column_position) { - // TODO Implement after the PR from column metadata is merged - return 0; + const std::shared_ptr &field = schema_->field(column_position - 1); + arrow::flight::sql::ColumnMetadata metadata(field->metadata()); + + SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + + return GetRadixFromSqlDataType(data_type_v3).value_or(NO_TOTAL); } size_t FlightSqlResultSetMetadata::GetOctetLength(int column_position) { - // TODO Implement after the PR from column metadata is merged - return 0; + const std::shared_ptr &field = schema_->field(column_position - 1); + arrow::flight::sql::ColumnMetadata metadata(field->metadata()); + + int32_t column_size = metadata.GetPrecision().ValueOrElse([] { return StringColumnLength; }); + SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + + return GetCharOctetLength(data_type_v3, column_size).value_or(NO_TOTAL); } std::string FlightSqlResultSetMetadata::GetTypeName(int column_position) { - // TODO Implement after the PR from column metadata is merged - return ""; + arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + + return metadata.GetTypeName().ValueOrElse([] { return ""; }); } driver::odbcabstraction::Updatability FlightSqlResultSetMetadata::GetUpdatable(int column_position) { - // TODO Implement after the PR from column metadata is merged return odbcabstraction::UPDATABILITY_READWRITE_UNKNOWN; } bool FlightSqlResultSetMetadata::IsAutoUnique(int column_position) { - // TODO Implement after the PR from column metadata is merged - return false; + arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + + // TODO: Is AutoUnique equivalent to AutoIncrement? + return metadata.GetIsAutoIncrement().ValueOrElse([] { return false; }); } bool FlightSqlResultSetMetadata::IsCaseSensitive(int column_position) { - // TODO Implement after the PR from column metadata is merged - return false; + arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + + return metadata.GetIsCaseSensitive().ValueOrElse([] { return false; }); } driver::odbcabstraction::Searchability FlightSqlResultSetMetadata::IsSearchable(int column_position) { - // TODO Implement after the PR from column metadata is merged - return odbcabstraction::SEARCHABILITY_NONE; + arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + + bool is_searchable = metadata.GetIsSearchable().ValueOrElse([] { return false; }); + return is_searchable ? odbcabstraction::SEARCHABILITY_ALL : odbcabstraction::SEARCHABILITY_NONE; } bool FlightSqlResultSetMetadata::IsUnsigned(int column_position) { - // TODO Implement after the PR from column metadata is merged - return false; + const std::shared_ptr &field = schema_->field(column_position - 1); + + switch (field->type()->id()) { + case arrow::Type::UINT8: + case arrow::Type::UINT16: + case arrow::Type::UINT32: + case arrow::Type::UINT64: + return true; + default: + return false; + } } bool FlightSqlResultSetMetadata::IsFixedPrecScale(int column_position) { - // TODO Implement after the PR from column metadata is merged + // TODO: Flight SQL column metadata does not have this, should we add to the spec? return false; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 096f010c723a4..a0fc39f371c96 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -24,6 +24,8 @@ namespace driver { namespace flight_sql { using namespace odbcabstraction; +using arrow::util::make_optional; +using arrow::util::nullopt; SqlDataType GetDataTypeFromArrowField_V3(const std::shared_ptr &field) { @@ -353,6 +355,65 @@ optional GetBufferLength(SqlDataType data_type, } } +optional GetDisplaySize(SqlDataType data_type, + const optional& column_size) { + switch (data_type) { + case SqlDataType_CHAR: + case SqlDataType_VARCHAR: + case SqlDataType_LONGVARCHAR: + case SqlDataType_WCHAR: + case SqlDataType_WVARCHAR: + case SqlDataType_WLONGVARCHAR: + return column_size; + case SqlDataType_BINARY: + case SqlDataType_VARBINARY: + case SqlDataType_LONGVARBINARY: + return column_size ? make_optional(*column_size * 2) : nullopt; + case SqlDataType_DECIMAL: + case SqlDataType_NUMERIC: + return column_size ? make_optional(*column_size + 2) : nullopt; + case SqlDataType_BIT: + return 1; + case SqlDataType_TINYINT: + return 4; + case SqlDataType_SMALLINT: + return 6; + case SqlDataType_INTEGER: + return 11; + case SqlDataType_BIGINT: + return 20; + case SqlDataType_REAL: + return 14; + case SqlDataType_FLOAT: + case SqlDataType_DOUBLE: + return 24; + case SqlDataType_TYPE_DATE: + return 10; + case SqlDataType_TYPE_TIME: + return 12; // Assuming format "hh:mm:ss.fff" + case SqlDataType_TYPE_TIMESTAMP: + return 23; // Assuming format "yyyy-mm-dd hh:mm:ss.fff" + case SqlDataType_INTERVAL_MONTH: + case SqlDataType_INTERVAL_YEAR: + case SqlDataType_INTERVAL_YEAR_TO_MONTH: + case SqlDataType_INTERVAL_DAY: + case SqlDataType_INTERVAL_HOUR: + case SqlDataType_INTERVAL_MINUTE: + case SqlDataType_INTERVAL_SECOND: + case SqlDataType_INTERVAL_DAY_TO_HOUR: + case SqlDataType_INTERVAL_DAY_TO_MINUTE: + case SqlDataType_INTERVAL_DAY_TO_SECOND: + case SqlDataType_INTERVAL_HOUR_TO_MINUTE: + case SqlDataType_INTERVAL_HOUR_TO_SECOND: + case SqlDataType_INTERVAL_MINUTE_TO_SECOND: + return nullopt; // TODO: Implement for INTERVAL types + case SqlDataType_GUID: + return 36; + default: + return nullopt; + } +} + std::string ConvertSqlPatternToRegexString(const std::string &pattern) { static const std::string specials = "[]()|^-+*?{}$\\."; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index e960819397964..43da84a92f7b9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -85,6 +85,9 @@ optional GetCharOctetLength(odbcabstraction::SqlDataType data_type, optional GetBufferLength(odbcabstraction::SqlDataType data_type, const optional& column_size); +optional GetDisplaySize(odbcabstraction::SqlDataType data_type, + const optional& column_size); + std::string ConvertSqlPatternToRegexString(const std::string &pattern); boost::xpressive::sregex ConvertSqlPatternToRegex(const std::string &pattern); From 84152b69b34bbe600175fe0bfde09249461aeb32 Mon Sep 17 00:00:00 2001 From: James Duong Date: Tue, 19 Apr 2022 14:55:47 -0700 Subject: [PATCH 086/183] Implement diagnostics management - Add the Diagnostics class for tracking ODBC exceptions and warnings, and managing ODBC versions. - Add enums for tracking native error codes. - Update accessors to throw exceptions when null is retrieved but the indicator was null. - Update accessors to post truncation warnings. Change-Id: I5e012ed762484ec6d1d8b02a3a59ff26c12cf78d --- .../flightsql-odbc/.gitignore | 2 + .../accessors/binary_array_accessor.cc | 9 +- .../accessors/binary_array_accessor.h | 2 +- .../accessors/binary_array_accessor_test.cc | 7 +- .../accessors/boolean_array_accessor.cc | 2 +- .../accessors/boolean_array_accessor.h | 3 +- .../accessors/boolean_array_accessor_test.cc | 3 +- .../flight_sql/accessors/common.h | 28 +++-- .../accessors/primitive_array_accessor.cc | 2 +- .../accessors/primitive_array_accessor.h | 2 +- .../primitive_array_accessor_test.cc | 4 +- .../accessors/string_array_accessor.cc | 13 +- .../accessors/string_array_accessor.h | 3 +- .../accessors/string_array_accessor_test.cc | 13 +- .../flight_sql/accessors/types.h | 32 +++-- .../flight_sql/flight_sql_connection.cc | 16 ++- .../flight_sql/flight_sql_connection.h | 3 + .../flight_sql/flight_sql_driver.cc | 8 ++ .../flight_sql/flight_sql_result_set.cc | 23 ++-- .../flight_sql/flight_sql_result_set.h | 5 +- .../flight_sql/flight_sql_statement.cc | 29 +++-- .../flight_sql/flight_sql_statement.h | 12 +- .../flight_sql_statement_get_tables.cc | 20 +-- .../flight_sql_statement_get_tables.h | 15 ++- .../include/flight_sql/flight_sql_driver.h | 8 ++ .../flightsql-odbc/flight_sql/utils.h | 2 +- .../odbcabstraction/CMakeLists.txt | 3 + .../odbcabstraction/diagnostics.cc | 90 ++++++++++++++ .../odbcabstraction/exceptions.cc | 20 ++- .../include/odbcabstraction/connection.h | 9 +- .../include/odbcabstraction/diagnostics.h | 114 ++++++++++++++++++ .../include/odbcabstraction/driver.h | 5 + .../include/odbcabstraction/error_codes.h | 36 ++++++ .../include/odbcabstraction/exceptions.h | 23 +++- .../include/odbcabstraction/statement.h | 8 +- .../include/odbcabstraction/types.h | 4 +- 36 files changed, 477 insertions(+), 101 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/diagnostics.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/diagnostics.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/error_codes.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore index 65a03f3058fc9..3f410c6aa761a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/.gitignore @@ -38,3 +38,5 @@ build.* *lib*.a *arrow_odbc_spi_impl_cli *arrow_odbc_spi_impl_test +.cmake/ +.cache/ \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc index faff231746c49..872aca7417711 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc @@ -31,7 +31,7 @@ namespace { inline void MoveSingleCellToBinaryBuffer(ColumnBinding *binding, BinaryArray *array, int64_t i, - int64_t value_offset) { + int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { const char *value = array->Value(i).data(); size_t size_in_bytes = array->value_length(i); @@ -40,6 +40,9 @@ inline void MoveSingleCellToBinaryBuffer(ColumnBinding *binding, size_t value_length = std::min(static_cast(size_in_bytes - value_offset), binding->buffer_length); + if (size_in_bytes - value_offset > binding->buffer_length) { + diagnostics.AddTruncationWarning(); + } auto *byte_buffer = static_cast(binding->buffer) + i * binding->buffer_length; @@ -61,8 +64,8 @@ BinaryArrayFlightSqlAccessor::BinaryArrayFlightSqlAccessor( template <> void BinaryArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, BinaryArray *array, int64_t i, - int64_t value_offset) { - MoveSingleCellToBinaryBuffer(binding, array, i, value_offset); + int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { + MoveSingleCellToBinaryBuffer(binding, array, i, value_offset, diagnostics); } template class BinaryArrayFlightSqlAccessor; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h index 57689eeff76ad..eb760d5253ad9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h @@ -35,7 +35,7 @@ class BinaryArrayFlightSqlAccessor explicit BinaryArrayFlightSqlAccessor(Array *array); void MoveSingleCell_impl(ColumnBinding *binding, BinaryArray *array, - int64_t i, int64_t value_offset); + int64_t i, int64_t value_offset, odbcabstraction::Diagnostics &diagnostics); }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc index c3830b7f9f05d..9c0cd19af16b7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc @@ -40,8 +40,9 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Basic) { ColumnBinding binding(CDataType_BINARY, 0, 0, buffer.data(), max_strlen, strlen_buffer.data()); + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0)); + accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(values[i].length(), strlen_buffer[i]); @@ -74,8 +75,10 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Truncation) { // Construct the whole string by concatenating smaller chunks from // GetColumnarData + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); do { - ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset)); + diagnostics.Clear(); + ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, diagnostics)); ASSERT_EQ(values[0].length(), strlen_buffer[0]); int64_t chunk_length = std::min(static_cast(max_strlen), diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc index 2a86787b1d547..8912164671e76 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc @@ -32,7 +32,7 @@ BooleanArrayFlightSqlAccessor::BooleanArrayFlightSqlAccessor( template void BooleanArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, BooleanArray *array, int64_t i, - int64_t value_offset) { + int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { typedef unsigned char c_type; bool value = array->Value(i); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h index 59f1ca6f5a618..af476ccaa64b8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h @@ -20,6 +20,7 @@ #include "arrow/type_fwd.h" #include "types.h" #include +#include namespace driver { namespace flight_sql { @@ -35,7 +36,7 @@ class BooleanArrayFlightSqlAccessor explicit BooleanArrayFlightSqlAccessor(Array *array); void MoveSingleCell_impl(ColumnBinding *binding, BooleanArray *array, - int64_t i, int64_t value_offset); + int64_t i, int64_t value_offset, odbcabstraction::Diagnostics &diagnostics); }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc index eb22686d9e17a..6e5d9ea3764ef 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc @@ -37,8 +37,9 @@ TEST(BooleanArrayFlightSqlAccessor, Test_BooleanArray_CDataType_BIT) { ColumnBinding binding(CDataType_BIT, 0, 0, buffer.data(), 0, strlen_buffer.data()); + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0)); + accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(unsigned char), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h index 6f2223013f7ee..d6ed4afb6e4a6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -34,14 +35,23 @@ template inline size_t CopyFromArrayValuesToBinding(const std::shared_ptr &array, ColumnBinding *binding) { auto *typed_array = reinterpret_cast(array.get()); - ssize_t element_size = sizeof(typename ARRAY_TYPE::value_type); + constexpr ssize_t element_size = sizeof(typename ARRAY_TYPE::value_type); int64_t length = array->length(); - for (int64_t i = 0; i < length; ++i) { - if (array->IsNull(i)) { - binding->strlen_buffer[i] = NULL_DATA; - } else { - binding->strlen_buffer[i] = element_size; + if (binding->strlen_buffer) { + for (int64_t i = 0; i < length; ++i) { + if (array->IsNull(i)) { + binding->strlen_buffer[i] = NULL_DATA; + } else { + binding->strlen_buffer[i] = element_size; + } + } + } else { + // Duplicate this loop to avoid null checks within the loop. + for (int64_t i = 0; i < length; ++i) { + if (array->IsNull(i)) { + throw odbcabstraction::NullWithoutIndicatorException(); + } } } @@ -54,7 +64,7 @@ inline size_t CopyFromArrayValuesToBinding(const std::shared_ptr &array, } inline void MoveToCharBuffer(ColumnBinding *binding, Array *array, int64_t i, - int64_t value_offset) { + int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { const std::shared_ptr &scalar = array->GetScalar(i).ValueOrDie(); const std::shared_ptr &utf8_scalar = internal::checked_pointer_cast( @@ -66,6 +76,10 @@ inline void MoveToCharBuffer(ColumnBinding *binding, Array *array, int64_t i, std::min(static_cast(utf8_scalar->value->size() - value_offset), binding->buffer_length); + if (value_length <= static_cast(utf8_scalar->value->size() - value_offset)) { + diagnostics.AddTruncationWarning(); + } + char *char_buffer = static_cast(binding->buffer); memcpy(&char_buffer[i * binding->buffer_length], value + value_offset, value_length); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc index d932757461c37..3b95087aca8c4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc @@ -34,7 +34,7 @@ template size_t PrimitiveArrayFlightSqlAccessor::GetColumnarData_impl( const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset) { + int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { return CopyFromArrayValuesToBinding(sliced_array, binding); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h index 30f7f2544736a..fa04097948bbf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h @@ -39,7 +39,7 @@ class PrimitiveArrayFlightSqlAccessor explicit PrimitiveArrayFlightSqlAccessor(Array *array); size_t GetColumnarData_impl(const std::shared_ptr &sliced_array, - ColumnBinding *binding, int64_t value_offset); + ColumnBinding *binding, int64_t value_offset, odbcabstraction::Diagnostics &diagnostics); }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc index 8adf8454c7d6e..453f7a052b073 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc @@ -17,6 +17,7 @@ #include "arrow/testing/builder.h" #include "primitive_array_accessor.h" +#include #include "gtest/gtest.h" namespace driver { @@ -43,8 +44,9 @@ void TestPrimitiveArraySqlAccessor() { ColumnBinding binding(TARGET_TYPE, 0, 0, buffer.data(), values.size(), strlen_buffer.data()); + driver::odbcabstraction::Diagnostics diagnostics("Dummy", "Dummy", odbcabstraction::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0)); + accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(c_type), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc index ed8a2627fcc02..6a3aad34711be 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -31,7 +31,8 @@ template inline void MoveSingleCellToCharBuffer(CharToWStrConverter *converter, ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset) { + int64_t value_offset, + odbcabstraction::Diagnostics &diagnostics) { const char *raw_value = array->Value(i).data(); const void *value; @@ -46,7 +47,6 @@ inline void MoveSingleCellToCharBuffer(CharToWStrConverter *converter, size_in_bytes = array->value_length(i); } - // TODO: Handle truncation size_t value_length = std::min(static_cast(size_in_bytes - value_offset), binding->buffer_length); @@ -60,6 +60,7 @@ inline void MoveSingleCellToCharBuffer(CharToWStrConverter *converter, if (binding->buffer_length > size_in_bytes + sizeof(CHAR_TYPE)) { char_buffer[size_in_bytes / sizeof(CHAR_TYPE)] = '\0'; } else { + diagnostics.AddTruncationWarning(); size_t chars_written = binding->buffer_length / sizeof(CHAR_TYPE); // If we failed to even write one char, the buffer is too small to hold a // NUL-terminator. @@ -85,17 +86,17 @@ StringArrayFlightSqlAccessor::StringArrayFlightSqlAccessor( template <> void StringArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset) { + int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { MoveSingleCellToCharBuffer(&converter_, binding, array, i, - value_offset); + value_offset, diagnostics); } template <> void StringArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset) { + int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { MoveSingleCellToCharBuffer(&converter_, binding, array, i, - value_offset); + value_offset, diagnostics); } template class StringArrayFlightSqlAccessor; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h index 960ab6bb7667a..0e1b285f61aa0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h @@ -37,7 +37,8 @@ class StringArrayFlightSqlAccessor explicit StringArrayFlightSqlAccessor(Array *array); void MoveSingleCell_impl(ColumnBinding *binding, StringArray *array, - int64_t i, int64_t value_offset); + int64_t i, int64_t value_offset, + odbcabstraction::Diagnostics &diagnostics); private: CharToWStrConverter converter_; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc index 14fee9f4f3cff..a25f3c7bcc215 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc @@ -39,8 +39,9 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Basic) { ColumnBinding binding(CDataType_CHAR, 0, 0, buffer.data(), max_strlen, strlen_buffer.data()); + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0)); + accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(values[i].length(), strlen_buffer[i]); @@ -68,8 +69,10 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Truncation) { // Construct the whole string by concatenating smaller chunks from // GetColumnarData + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); do { - ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset)); + diagnostics.Clear(); + ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, diagnostics)); ASSERT_EQ(values[0].length(), strlen_buffer[0]); int64_t chunk_length = std::min(static_cast(max_strlen), @@ -95,8 +98,9 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Basic) { ColumnBinding binding(CDataType_WCHAR, 0, 0, buffer.data(), max_strlen, strlen_buffer.data()); + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0)); + accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(values[i].length() * sizeof(SqlWChar), strlen_buffer[i]); @@ -127,8 +131,9 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Truncation) { // Construct the whole string by concatenating smaller chunks from // GetColumnarData std::basic_string finalStr; + driver::odbcabstraction::Diagnostics diagnostics("Dummy", "Dummy", odbcabstraction::V_3); do { - ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset)); + ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, diagnostics)); ASSERT_EQ(values[0].length() * sizeof(SqlWChar), strlen_buffer[0]); int64_t chunk_length = diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h index e31acef5bd94a..b59224d5b5202 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h @@ -23,6 +23,7 @@ #include #include #include +#include #include namespace driver { @@ -62,7 +63,8 @@ class Accessor { /// \brief Populates next cells virtual size_t GetColumnarData(ColumnBinding *binding, int64_t starting_row, - size_t cells, int64_t value_offset) = 0; + size_t cells, int64_t value_offset, + odbcabstraction::Diagnostics &diagnostics) = 0; }; template @@ -73,51 +75,55 @@ class FlightSqlAccessor : public Accessor { array_(arrow::internal::checked_cast(array)) {} size_t GetColumnarData(ColumnBinding *binding, int64_t starting_row, - size_t cells, int64_t value_offset) override { + size_t cells, int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) override { const std::shared_ptr &array = array_->Slice(starting_row, static_cast(cells)); return GetColumnarData( arrow::internal::checked_pointer_cast(array), binding, - value_offset); + value_offset, diagnostics); } private: ARROW_ARRAY *array_; size_t GetColumnarData(const std::shared_ptr &sliced_array, - ColumnBinding *binding, int64_t value_offset) { + ColumnBinding *binding, int64_t value_offset, + odbcabstraction::Diagnostics &diagnostics) { return static_cast(this)->GetColumnarData_impl( - sliced_array, binding, value_offset); + sliced_array, binding, value_offset, diagnostics); } size_t GetColumnarData_impl(const std::shared_ptr &sliced_array, - ColumnBinding *binding, int64_t value_offset) { + ColumnBinding *binding, int64_t value_offset, + odbcabstraction::Diagnostics &diagnostics) { int64_t length = sliced_array->length(); for (int64_t i = 0; i < length; ++i) { if (sliced_array->IsNull(i)) { if (binding->strlen_buffer) { binding->strlen_buffer[i] = odbcabstraction::NULL_DATA; } else { - // TODO: Report error when data is null bor strlen_buffer is nullptr + throw odbcabstraction::NullWithoutIndicatorException(); } - continue; + } else { + // TODO: Optimize this by creating different versions of MoveSingleCell + // depending on if strlen_buffer is null. + MoveSingleCell(binding, sliced_array.get(), i, value_offset, + diagnostics); } - - MoveSingleCell(binding, sliced_array.get(), i, value_offset); } return length; } void MoveSingleCell(ColumnBinding *binding, ARROW_ARRAY *array, int64_t i, - int64_t value_offset) { + int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { return static_cast(this)->MoveSingleCell_impl(binding, array, i, - value_offset); + value_offset, diagnostics); } void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, - int64_t i, int64_t value_offset) { + int64_t i, int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { std::stringstream ss; ss << "Unknown type conversion from StringArray to target C type " << TARGET_TYPE; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 6549d6d706045..91577964e2c73 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -177,7 +177,7 @@ void FlightSqlConnection::Close() { std::shared_ptr FlightSqlConnection::CreateStatement() { return std::shared_ptr( - new FlightSqlStatement(*sql_client_, call_options_)); + new FlightSqlStatement(diagnostics_, *sql_client_, call_options_)); } bool FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, @@ -209,16 +209,26 @@ FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { } Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { - return info_.GetInfo(info_type); + auto result = info_.GetInfo(info_type); + if (info_type == SQL_DBMS_NAME) { + // Update the database component reported in error messages. + // We do this lazily for performance reasons. + diagnostics_.SetDataSourceComponent(boost::get(result)); + } + return result; } FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version) - : odbc_version_(odbc_version), info_(call_options_, sql_client_), + : diagnostics_("Apache Arrow", "Flight SQL", odbc_version), + odbc_version_(odbc_version), info_(call_options_, sql_client_), closed_(true) { attribute_[CONNECTION_DEAD] = static_cast(SQL_TRUE); attribute_[LOGIN_TIMEOUT] = static_cast(0); attribute_[CONNECTION_TIMEOUT] = static_cast(0); attribute_[CURRENT_CATALOG] = ""; } +odbcabstraction::Diagnostics &FlightSqlConnection::GetDiagnostics() { + return diagnostics_; +} } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index f1ecb2c1a5708..e0d806ff00a9c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -34,6 +34,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { arrow::flight::FlightCallOptions call_options_; std::unique_ptr sql_client_; GetInfoCache info_; + odbcabstraction::Diagnostics diagnostics_; odbcabstraction::OdbcVersion odbc_version_; bool closed_; @@ -78,6 +79,8 @@ class FlightSqlConnection : public odbcabstraction::Connection { /// \brief Builds a FlightCallOptions used on gRPC calls. /// \note Visible for testing const arrow::flight::FlightCallOptions &PopulateCallOptionsFromAttributes(); + + odbcabstraction::Diagnostics &GetDiagnostics() override; }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index d8329afbe140d..c86f0e51688a0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -25,9 +25,17 @@ namespace flight_sql { using odbcabstraction::Connection; using odbcabstraction::OdbcVersion; +FlightSqlDriver::FlightSqlDriver() + : diagnostics_("Apache Arrow", "Flight SQL", OdbcVersion::V_3) +{} + std::shared_ptr FlightSqlDriver::CreateConnection(OdbcVersion odbc_version) { return std::make_shared(odbc_version); } + +odbcabstraction::Diagnostics &FlightSqlDriver::GetDiagnostics() { + return diagnostics_; +} } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index da9242945762c..8b7991e1c1cbe 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -44,7 +44,8 @@ FlightSqlResultSet::FlightSqlResultSet( FlightSqlClient &flight_sql_client, const arrow::flight::FlightCallOptions &call_options, const std::shared_ptr &flight_info, - const std::shared_ptr &transformer) + const std::shared_ptr &transformer, + odbcabstraction::Diagnostics& diagnostics) : num_binding_(0), current_row_(0), chunk_iterator_(flight_sql_client, call_options, flight_info), transformer_(transformer), @@ -52,7 +53,8 @@ FlightSqlResultSet::FlightSqlResultSet( transformer->GetTransformedSchema()) : new FlightSqlResultSetMetadata(flight_info)), columns_(metadata_->GetColumnCount()), - get_data_offsets_(metadata_->GetColumnCount()) { + get_data_offsets_(metadata_->GetColumnCount()), + diagnostics_(diagnostics) { current_chunk_.data = nullptr; for (int i = 0; i < columns_.size(); ++i) { @@ -112,7 +114,7 @@ size_t FlightSqlResultSet::Move(size_t rows) { continue; size_t accessor_rows = column.GetAccessorForBinding()->GetColumnarData( - &column.binding, current_row_, rows_to_fetch, 0); + &column.binding, current_row_, rows_to_fetch, 0, diagnostics_); if (rows_to_fetch != accessor_rows) { throw DriverException( @@ -141,20 +143,15 @@ bool FlightSqlResultSet::GetData(int column_n, CDataType target_type, auto &column = columns_[column_n - 1]; Accessor *accessor = column.GetAccessorForGetData(target_type); - int64_t &value_offset = get_data_offsets_[column_n - 1]; + int64_t value_offset = get_data_offsets_[column_n - 1]; // Note: current_row_ is always positioned at the index _after_ the one we are // on after calling Move(). So if we want to get data from the _last_ row // fetched, we need to subtract one from the current row. - accessor->GetColumnarData(&binding, current_row_ - 1, 1, value_offset); - - if (strlen_buffer && strlen_buffer[0] != odbcabstraction::NULL_DATA) { - bool has_more = value_offset + buffer_length <= strlen_buffer[0]; - value_offset += static_cast(buffer_length); - return has_more; - } else { - return false; - } + accessor->GetColumnarData(&binding, current_row_ - 1, 1, value_offset, diagnostics_); + + // If there was truncation, the converter would have reported it to the diagnostics. + return diagnostics_.HasWarning(); } std::shared_ptr diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index c4f47ac4b38fa..1ce9892dab424 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace driver { namespace flight_sql { @@ -61,6 +62,7 @@ class FlightSqlResultSet : public ResultSet { std::shared_ptr metadata_; std::vector columns_; std::vector get_data_offsets_; + odbcabstraction::Diagnostics &diagnostics_; public: ~FlightSqlResultSet() override; @@ -69,7 +71,8 @@ class FlightSqlResultSet : public ResultSet { FlightSqlClient &flight_sql_client, const arrow::flight::FlightCallOptions &call_options, const std::shared_ptr &flight_info, - const std::shared_ptr &transformer); + const std::shared_ptr &transformer, + odbcabstraction::Diagnostics& diagnostics); void Close() override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index 21b1e14c64639..5e033812c2bee 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -63,9 +63,12 @@ void ClosePreparedStatementIfAny( } // namespace -FlightSqlStatement::FlightSqlStatement(FlightSqlClient &sql_client, - FlightCallOptions call_options) - : sql_client_(sql_client), call_options_(std::move(call_options)) { +FlightSqlStatement::FlightSqlStatement( + const odbcabstraction::Diagnostics& diagnostics, + FlightSqlClient &sql_client, + FlightCallOptions call_options) + : diagnostics_("Apache Arrow", diagnostics.GetDataSourceComponent(), diagnostics.GetOdbcVersion()), + sql_client_(sql_client), call_options_(std::move(call_options)) { attribute_[METADATA_ID] = static_cast(SQL_FALSE); attribute_[MAX_LENGTH] = static_cast(0); attribute_[NOSCAN] = static_cast(SQL_NOSCAN_OFF); @@ -126,7 +129,7 @@ bool FlightSqlStatement::ExecutePrepared() { ThrowIfNotOK(result.status()); current_result_set_ = std::make_shared( - sql_client_, call_options_, result.ValueOrDie(), nullptr); + sql_client_, call_options_, result.ValueOrDie(), nullptr, diagnostics_); return true; } @@ -139,7 +142,7 @@ bool FlightSqlStatement::Execute(const std::string &query) { ThrowIfNotOK(result.status()); current_result_set_ = std::make_shared( - sql_client_, call_options_, result.ValueOrDie(), nullptr); + sql_client_, call_options_, result.ValueOrDie(), nullptr, diagnostics_); return true; } @@ -163,19 +166,19 @@ std::shared_ptr FlightSqlStatement::GetTables( (table_name && table_name->empty()) && (table_type && table_type->empty())) { current_result_set_ = - GetTablesForSQLAllCatalogs(column_names, call_options_, sql_client_); + GetTablesForSQLAllCatalogs(column_names, call_options_, sql_client_, diagnostics_); } else if ((catalog_name && catalog_name->empty()) && (schema_name && *schema_name == "%") && (table_name && table_name->empty()) && (table_type && table_type->empty())) { current_result_set_ = GetTablesForSQLAllDbSchemas( - column_names, call_options_, sql_client_, schema_name); + column_names, call_options_, sql_client_, schema_name, diagnostics_); } else if ((catalog_name && catalog_name->empty()) && (schema_name && schema_name->empty()) && (table_name && table_name->empty()) && (table_type && *table_type == "%")) { current_result_set_ = - GetTablesForSQLAllTableTypes(column_names, call_options_, sql_client_); + GetTablesForSQLAllTableTypes(column_names, call_options_, sql_client_, diagnostics_); } else { if (table_type) { ParseTableTypes(*table_type, table_types); @@ -183,7 +186,7 @@ std::shared_ptr FlightSqlStatement::GetTables( current_result_set_ = GetTablesForGenericUse( column_names, call_options_, sql_client_, catalog_name, schema_name, - table_name, table_types); + table_name, table_types, diagnostics_); } return current_result_set_; @@ -224,7 +227,7 @@ std::shared_ptr FlightSqlStatement::GetColumns_V2( odbcabstraction::V_2, column_name); current_result_set_ = std::make_shared( - sql_client_, call_options_, flight_info, transformer); + sql_client_, call_options_, flight_info, transformer, diagnostics_); return current_result_set_; } @@ -244,7 +247,7 @@ std::shared_ptr FlightSqlStatement::GetColumns_V3( odbcabstraction::V_3, column_name); current_result_set_ = std::make_shared( - sql_client_, call_options_, flight_info, transformer); + sql_client_, call_options_, flight_info, transformer, diagnostics_); return current_result_set_; } @@ -253,5 +256,9 @@ std::shared_ptr FlightSqlStatement::GetTypeInfo(int dataType) { return current_result_set_; } +odbcabstraction::Diagnostics &FlightSqlStatement::GetDiagnostics() { + return diagnostics_; +} + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h index c1ad8ce51345b..5073d24b6a518 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h @@ -20,6 +20,7 @@ #include "arrow/flight/sql/client.h" #include "flight_sql_statement_get_tables.h" #include +#include #include #include @@ -31,6 +32,7 @@ namespace flight_sql { class FlightSqlStatement : public odbcabstraction::Statement { private: + odbcabstraction::Diagnostics diagnostics_; std::map attribute_; arrow::flight::FlightCallOptions call_options_; arrow::flight::sql::FlightSqlClient &sql_client_; @@ -43,10 +45,12 @@ class FlightSqlStatement : public odbcabstraction::Statement { const ColumnNames &column_names); public: - FlightSqlStatement(arrow::flight::sql::FlightSqlClient &sql_client, - arrow::flight::FlightCallOptions call_options); + FlightSqlStatement( + const odbcabstraction::Diagnostics &diagnostics, + arrow::flight::sql::FlightSqlClient &sql_client, + arrow::flight::FlightCallOptions call_options); - bool SetAttribute(StatementAttributeId attribute, const Attribute &value); + bool SetAttribute(StatementAttributeId attribute, const Attribute &value) override; boost::optional GetAttribute(StatementAttributeId attribute) override; @@ -78,6 +82,8 @@ class FlightSqlStatement : public odbcabstraction::Statement { const std::string *table_name, const std::string *column_name) override; std::shared_ptr GetTypeInfo(int dataType) override; + + odbcabstraction::Diagnostics &GetDiagnostics() override; }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc index d29870f7b15ba..d29a20342ebee 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc @@ -81,7 +81,8 @@ void ParseTableTypes(const std::string &table_type, std::shared_ptr GetTablesForSQLAllCatalogs(const ColumnNames &names, FlightCallOptions &call_options, - FlightSqlClient &sql_client) { + FlightSqlClient &sql_client, + odbcabstraction::Diagnostics &diagnostics) { Result> result = sql_client.GetCatalogs(call_options); @@ -101,12 +102,13 @@ GetTablesForSQLAllCatalogs(const ColumnNames &names, .Build(); return std::make_shared(sql_client, call_options, - flight_info, transformer); + flight_info, transformer, diagnostics); } std::shared_ptr GetTablesForSQLAllDbSchemas( const ColumnNames &names, FlightCallOptions &call_options, - FlightSqlClient &sql_client, const std::string *schema_name) { + FlightSqlClient &sql_client, const std::string *schema_name, + odbcabstraction::Diagnostics &diagnostics ) { Result> result = sql_client.GetDbSchemas(call_options, nullptr, schema_name); @@ -126,13 +128,14 @@ std::shared_ptr GetTablesForSQLAllDbSchemas( .Build(); return std::make_shared(sql_client, call_options, - flight_info, transformer); + flight_info, transformer, diagnostics); } std::shared_ptr GetTablesForSQLAllTableTypes(const ColumnNames &names, FlightCallOptions &call_options, - FlightSqlClient &sql_client) { + FlightSqlClient &sql_client, + odbcabstraction::Diagnostics &diagnostics) { Result> result = sql_client.GetTableTypes(call_options); @@ -152,14 +155,15 @@ GetTablesForSQLAllTableTypes(const ColumnNames &names, .Build(); return std::make_shared(sql_client, call_options, - flight_info, transformer); + flight_info, transformer, diagnostics); } std::shared_ptr GetTablesForGenericUse( const ColumnNames &names, FlightCallOptions &call_options, FlightSqlClient &sql_client, const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, - const std::vector &table_types) { + const std::vector &table_types, + odbcabstraction::Diagnostics &diagnostics) { Result> result = sql_client.GetTables( call_options, catalog_name, schema_name, table_name, false, &table_types); @@ -179,7 +183,7 @@ std::shared_ptr GetTablesForGenericUse( .Build(); return std::make_shared(sql_client, call_options, - flight_info, transformer); + flight_info, transformer, diagnostics); } } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h index 8c14acd9a8601..9a548ed488395 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h @@ -18,7 +18,8 @@ #pragma once #include "arrow/flight/types.h" -#include "odbcabstraction/result_set.h" +#include +#include #include "record_batch_transformer.h" #include #include @@ -44,20 +45,24 @@ void ParseTableTypes(const std::string &table_type, std::shared_ptr GetTablesForSQLAllCatalogs(const ColumnNames &column_names, FlightCallOptions &call_options, - FlightSqlClient &sql_client); + FlightSqlClient &sql_client, + odbcabstraction::Diagnostics &diagnostics); std::shared_ptr GetTablesForSQLAllDbSchemas( const ColumnNames &column_names, FlightCallOptions &call_options, - FlightSqlClient &sql_client, const std::string *schema_name); + FlightSqlClient &sql_client, const std::string *schema_name, + odbcabstraction::Diagnostics &diagnostics); std::shared_ptr GetTablesForSQLAllTableTypes(const ColumnNames &column_names, FlightCallOptions &call_options, - FlightSqlClient &sql_client); + FlightSqlClient &sql_client, + odbcabstraction::Diagnostics &diagnostics); std::shared_ptr GetTablesForGenericUse( const ColumnNames &column_names, FlightCallOptions &call_options, FlightSqlClient &sql_client, const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, - const std::vector &table_types); + const std::vector &table_types, + odbcabstraction::Diagnostics &diagnostics); } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h index 506fd5c3fff04..497f1a6d79cf9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h @@ -18,14 +18,22 @@ #pragma once #include +#include namespace driver { namespace flight_sql { class FlightSqlDriver : public odbcabstraction::Driver { +private: + odbcabstraction::Diagnostics diagnostics_; + public: + FlightSqlDriver(); + std::shared_ptr CreateConnection(odbcabstraction::OdbcVersion odbc_version) override; + + odbcabstraction::Diagnostics &GetDiagnostics() override; }; }; // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index 43da84a92f7b9..1d397b1ec87ab 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -41,7 +41,7 @@ using CharToWStrConverter = inline void ThrowIfNotOK(const arrow::Status &status) { if (!status.ok()) { - throw odbcabstraction::DriverException(status.ToString()); + throw odbcabstraction::DriverException(status.message()); } } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index d7be3aefb772e..0db46d01b8c5d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -22,6 +22,9 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) include_directories(include) add_library(odbcabstraction + include/odbcabstraction/diagnostics.h + include/odbcabstraction/error_codes.h + diagnostics.cc exceptions.cc) set_target_properties(odbcabstraction diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/diagnostics.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/diagnostics.cc new file mode 100644 index 0000000000000..b9c0d6c376b37 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/diagnostics.cc @@ -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 +#include +#include + +#include + +namespace { + void RewriteSQLStateForODBC2(std::string& sql_state) { + if (sql_state[0] == 'H' && sql_state[1] == 'Y') { + sql_state[0] = 'S'; + sql_state[1] = '1'; + } + } +} + +namespace driver { +namespace odbcabstraction { + +Diagnostics::Diagnostics( + std::string vendor, std::string data_source_component, OdbcVersion version) : + vendor_(std::move(vendor)), + data_source_component_(std::move(data_source_component)), + version_(version) +{} + +void Diagnostics::SetDataSourceComponent(std::string component) { + data_source_component_ = std::move(component); +} + +std::string Diagnostics::GetDataSourceComponent() const { + return data_source_component_; +} + +std::string Diagnostics::GetVendor() const { + return vendor_; +} + +void driver::odbcabstraction::Diagnostics::AddError( + const driver::odbcabstraction::DriverException &exception) { + auto record = std::unique_ptr(new DiagnosticsRecord{ + exception.GetMessage(), exception.GetSqlState(), exception.GetNativeError()}); + if (version_ == OdbcVersion::V_2) { + RewriteSQLStateForODBC2(record->sql_state_); + } + TrackRecord(*record); + owned_records_.push_back(std::move(record)); +} + +void driver::odbcabstraction::Diagnostics::AddWarning( + std::string message, std::string sql_state, int32_t native_error) { +auto record = std::unique_ptr(new DiagnosticsRecord{ + std::move(message),std::move(sql_state), native_error}); + if (version_ == OdbcVersion::V_2) { + RewriteSQLStateForODBC2(record->sql_state_); + } + TrackRecord(*record); + owned_records_.push_back(std::move(record)); +} + +std::string driver::odbcabstraction::Diagnostics::GetMessageText( + uint32_t record_index) const { + std::string message; + if (!vendor_.empty()) { + message += std::string("[") + vendor_ + "]"; + } + const DiagnosticsRecord* rec = GetRecordAtIndex(record_index); + return message + "[" + data_source_component_ + "] (" + std::to_string(rec->native_error_) + ") " + rec->message_; +} + +OdbcVersion Diagnostics::GetOdbcVersion() const { return version_; } + +} // namespace odbcabstraction +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc index fdf84af7d037c..666dc8ee45c11 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc @@ -16,19 +16,29 @@ // under the License. #include -#include +#include #include namespace driver { namespace odbcabstraction { -DriverException::DriverException(std::string message) - : message_(std::move(message)) {} +DriverException::DriverException(std::string message, std::string sql_state, + int32_t native_error) + : message_(std::move(message)), + sql_state_(std::move(sql_state)), + native_error_(native_error) {} const char *DriverException::what() const throw() { return message_.c_str(); } +const std::string &DriverException::GetMessage() const { return message_; } +const std::string &DriverException::GetSqlState() const { return sql_state_; } +int32_t DriverException::GetNativeError() const { return native_error_; } -AuthenticationException::AuthenticationException(std::string message) - : DriverException(std::move(message)) {} +AuthenticationException::AuthenticationException(std::string message, std::string sql_state, + int32_t native_error) + : DriverException(message, sql_state, native_error) {} +NullWithoutIndicatorException::NullWithoutIndicatorException( + std::string message, std::string sql_state, int32_t native_error) + : DriverException(message, sql_state, native_error) {} } // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h index 2952536125d8d..ac219292828d1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h @@ -15,6 +15,8 @@ // specific language governing permissions and limitations // under the License. +#pragma once + #include #include #include @@ -22,8 +24,7 @@ #include #include - -#pragma once +#include namespace driver { namespace odbcabstraction { @@ -89,6 +90,10 @@ class Connection { /// \brief Retrieves info from the database (see ODBC's SQLGetInfo). virtual Info GetInfo(uint16_t info_type) = 0; + + /// \brief Gets the diagnostics for this connection. + /// \return the diagnostics + virtual Diagnostics& GetDiagnostics() = 0; }; } // namespace odbcabstraction diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/diagnostics.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/diagnostics.h new file mode 100644 index 0000000000000..7ed31558a75ac --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/diagnostics.h @@ -0,0 +1,114 @@ +// 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. + +#pragma once + +#include +#include +#include + +#include +#include + +namespace driver { +namespace odbcabstraction { + class Diagnostics { + public: + struct DiagnosticsRecord { + std::string message_; + std::string sql_state_; + int32_t native_error_; + }; + + private: + std::vector error_records_; + std::vector warning_records_; + std::vector> owned_records_; + std::string vendor_; + std::string data_source_component_; + OdbcVersion version_; + + public: + Diagnostics(std::string vendor, std::string data_source_component, OdbcVersion version); + void AddError(const DriverException& exception); + void AddWarning(std::string message, std::string sql_state, int32_t native_error); + + /// \brief Add a pre-existing truncation warning. + inline void AddTruncationWarning() { + static const std::unique_ptr TRUNCATION_WARNING(new DiagnosticsRecord { + "String or binary data, right-truncated.", "01004", + ODBCErrorCodes_TRUNCATION_WARNING + }); + warning_records_.push_back(TRUNCATION_WARNING.get()); + } + + inline void TrackRecord(const DiagnosticsRecord& record) { + if (record.sql_state_[0] == '0' && record.sql_state_[1] == '1') { + warning_records_.push_back(&record); + } else { + error_records_.push_back(&record); + } + } + + void SetDataSourceComponent(std::string component); + std::string GetDataSourceComponent() const; + + std::string GetVendor() const; + + inline void Clear() { + error_records_.clear(); + warning_records_.clear(); + owned_records_.clear(); + } + + std::string GetMessageText(uint32_t record_index) const; + std::string GetSQLState(uint32_t record_index) const { + return GetRecordAtIndex(record_index)->sql_state_; + } + + int32_t GetNativeError(uint32_t record_index) const { + return GetRecordAtIndex(record_index)->native_error_; + } + + inline size_t GetRecordCount() const { + return error_records_.size() + warning_records_.size(); + } + + inline bool HasRecord(uint32_t record_index) const { + return error_records_.size() + warning_records_.size() > record_index; + } + + inline bool HasWarning() const { + return !warning_records_.empty(); + } + + inline bool HasError() const { + return !error_records_.empty(); + } + + OdbcVersion GetOdbcVersion() const; + + private: + inline const DiagnosticsRecord* GetRecordAtIndex(uint32_t record_index) const { + if (record_index < error_records_.size()) { + return error_records_[record_index]; + } + return warning_records_[record_index - error_records_.size()]; + } + }; +} +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h index ae152a320a135..82f31a8c92b72 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h @@ -20,6 +20,7 @@ #include #include +#include namespace driver { namespace odbcabstraction { @@ -38,6 +39,10 @@ class Driver { /// \param odbc_version ODBC version to be used. virtual std::shared_ptr CreateConnection(OdbcVersion odbc_version) = 0; + + /// \brief Gets the diagnostics for this connection. + /// \return the diagnostics + virtual Diagnostics& GetDiagnostics() = 0; }; } // namespace odbcabstraction diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/error_codes.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/error_codes.h new file mode 100644 index 0000000000000..7931a07457474 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/error_codes.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. + +#pragma once + +#include + +namespace driver { +namespace odbcabstraction { + + enum ODBCErrorCodes : int32_t { + ODBCErrorCodes_GENERAL_ERROR = 100, + ODBCErrorCodes_AUTH = 200, + ODBCErrorCodes_TLS = 300, + ODBCErrorCodes_FRACTIONAL_TRUNCATION_ERROR = 400, + ODBCErrorCodes_GENERAL_WARNING = 1000000, + ODBCErrorCodes_TRUNCATION_WARNING = 1000100, + ODBCErrorCodes_FRACTIONAL_TRUNCATION_WARNING = 1000100, + ODBCErrorCodes_INDICATOR_NEEDED = 1000200 + }; +} +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h index df1193979df5f..4eff3657b088d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h @@ -19,6 +19,8 @@ #include #include +#include +#include "error_codes.h" namespace driver { namespace odbcabstraction { @@ -26,18 +28,35 @@ namespace odbcabstraction { /// \brief Base for all driver specific exceptions class DriverException : public std::exception { public: - explicit DriverException(std::string message); + explicit DriverException(std::string message, std::string sql_state = "HY000", + int32_t native_error = ODBCErrorCodes_GENERAL_ERROR); const char *what() const throw() override; + const std::string &GetMessage() const; + const std::string &GetSqlState() const; + int32_t GetNativeError() const; + private: const std::string message_; + const std::string sql_state_; + const int32_t native_error_; }; /// \brief Authentication specific exception class AuthenticationException : public DriverException { public: - explicit AuthenticationException(std::string message); + explicit AuthenticationException(std::string message, std::string sql_state = "28000", + int32_t native_error = ODBCErrorCodes_AUTH); +}; + +/// \brief Error when null is retrieved from the database but no indicator was supplied. +/// (This means the driver has no way to report ot the application that there was a NULL value). +class NullWithoutIndicatorException : public DriverException { +public: + explicit NullWithoutIndicatorException( + std::string message = "Indicator variable required but not supplied", std::string sql_state = "22002", + int32_t native_error = ODBCErrorCodes_INDICATOR_NEEDED); }; } // namespace odbcabstraction diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h index e728a86f90cb1..b5d10fea7f962 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h @@ -15,13 +15,13 @@ // specific language governing permissions and limitations // under the License. +#pragma once + #include #include #include #include -#pragma once - namespace driver { namespace odbcabstraction { @@ -168,6 +168,10 @@ class Statement { /// /// \param dataType The SQL data type. virtual std::shared_ptr GetTypeInfo(int dataType) = 0; + + /// \brief Gets the diagnostics for this statement. + /// \return the diagnostics + virtual Diagnostics& GetDiagnostics() = 0; }; } // namespace odbcabstraction diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index c73da7a01e093..02441612a36a7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -119,8 +119,8 @@ enum Updatability { UPDATABILITY_READWRITE_UNKNOWN = 2, }; -constexpr int NULL_DATA = -1; -constexpr int NO_TOTAL = -4; +constexpr ssize_t NULL_DATA = -1; +constexpr ssize_t NO_TOTAL = -4; } // namespace odbcabstraction } // namespace driver From 6473dcc90290c1aad112831a03102d82bc9d3893 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 3 May 2022 17:46:07 -0300 Subject: [PATCH 087/183] Implement GetTypeInfo This implements Statement's GetTypeInfo using Flight SQL's CommandXdbcGetTypeInfo. This handles SQLGetTypeInfo calls from warpdrive and provides important metadata for ODBC applications. Change-Id: Ice1490c9530c1090bd856b057011d8db1b7437e2 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 2 + .../flight_sql_get_type_info_reader.cc | 218 +++++++++++++++++ .../flight_sql_get_type_info_reader.h | 81 ++++++ .../flight_sql_result_set_column.cc | 2 + .../flight_sql_result_set_metadata.cc | 49 ++-- .../flight_sql/flight_sql_statement.cc | 35 ++- .../flight_sql/flight_sql_statement.h | 4 +- .../flight_sql_statement_get_columns.cc | 2 +- .../flight_sql_statement_get_type_info.cc | 231 ++++++++++++++++++ .../flight_sql_statement_get_type_info.h | 102 ++++++++ .../flightsql-odbc/flight_sql/utils.cc | 22 +- .../flightsql-odbc/flight_sql/utils.h | 3 +- .../include/odbcabstraction/statement.h | 17 +- .../include/odbcabstraction/types.h | 1 + 14 files changed, 726 insertions(+), 43 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index b84be839a81ed..543f45026a5c3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -139,8 +139,10 @@ set(ARROW_ODBC_SPI_SOURCES flight_sql_result_set_metadata.cc flight_sql_statement.cc flight_sql_statement_get_tables.cc + flight_sql_statement_get_type_info.cc flight_sql_statement_get_columns.cc flight_sql_get_tables_reader.cc + flight_sql_get_type_info_reader.cc flight_sql_stream_chunk_iterator.cc get_info_cache.cc json_converter.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.cc new file mode 100644 index 0000000000000..ec7595e147960 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.cc @@ -0,0 +1,218 @@ +// 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 "flight_sql_get_type_info_reader.h" +#include +#include "arrow/io/memory.h" +#include "arrow/array.h" +#include "utils.h" + +#include + +namespace driver { +namespace flight_sql { + +using arrow::internal::checked_pointer_cast; +using arrow::util::nullopt; + +GetTypeInfoReader::GetTypeInfoReader(std::shared_ptr record_batch) + : record_batch_(std::move(record_batch)), current_row_(-1) {} + +bool GetTypeInfoReader::Next() { + return ++current_row_ < record_batch_->num_rows(); +} + +std::string GetTypeInfoReader::GetTypeName() { + const auto &array = + checked_pointer_cast(record_batch_->column(0)); + + return array->GetString(current_row_); +} + +int32_t GetTypeInfoReader::GetDataType() { + const auto &array = + checked_pointer_cast(record_batch_->column(1)); + + return array->GetView(current_row_); +} + +optional GetTypeInfoReader::GetColumnSize() { + const auto &array = + checked_pointer_cast(record_batch_->column(2)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetView(current_row_); +} + +optional GetTypeInfoReader::GetLiteralPrefix() { + const auto &array = + checked_pointer_cast(record_batch_->column(3)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetString(current_row_); +} + +optional GetTypeInfoReader::GetLiteralSuffix() { + const auto &array = + checked_pointer_cast(record_batch_->column(4)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetString(current_row_); +} + +optional> GetTypeInfoReader::GetCreateParams() { + const auto &array = + checked_pointer_cast(record_batch_->column(5)); + + if (array->IsNull(current_row_)) + return nullopt; + + int values_length = array->value_length(current_row_); + int start_offset = array->value_offset(current_row_); + const auto &values_array = checked_pointer_cast(array->values()); + + std::vector result(values_length); + for (int i = 0; i < values_length; ++i) { + result[i] = values_array->GetString(start_offset + i); + } + + return result; +} + +int32_t GetTypeInfoReader::GetNullable() { + const auto &array = + checked_pointer_cast(record_batch_->column(6)); + + return array->GetView(current_row_); +} + +bool GetTypeInfoReader::GetCaseSensitive() { + const auto &array = + checked_pointer_cast(record_batch_->column(7)); + + return array->GetView(current_row_); +} + +int32_t GetTypeInfoReader::GetSearchable() { + const auto &array = + checked_pointer_cast(record_batch_->column(8)); + + return array->GetView(current_row_); +} + +optional GetTypeInfoReader::GetUnsignedAttribute() { + const auto &array = + checked_pointer_cast(record_batch_->column(9)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetView(current_row_); +} + +bool GetTypeInfoReader::GetFixedPrecScale() { + const auto &array = + checked_pointer_cast(record_batch_->column(10)); + + return array->GetView(current_row_); +} + +optional GetTypeInfoReader::GetAutoIncrement() { + const auto &array = + checked_pointer_cast(record_batch_->column(11)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetView(current_row_); +} + +optional GetTypeInfoReader::GetLocalTypeName() { + const auto &array = + checked_pointer_cast(record_batch_->column(12)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetString(current_row_); +} + +optional GetTypeInfoReader::GetMinimumScale() { + const auto &array = + checked_pointer_cast(record_batch_->column(13)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetView(current_row_); +} + +optional GetTypeInfoReader::GetMaximumScale() { + const auto &array = + checked_pointer_cast(record_batch_->column(14)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetView(current_row_); +} + +int32_t GetTypeInfoReader::GetSqlDataType() { + const auto &array = + checked_pointer_cast(record_batch_->column(15)); + + return array->GetView(current_row_); +} + +optional GetTypeInfoReader::GetDatetimeSubcode() { + const auto &array = + checked_pointer_cast(record_batch_->column(16)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetView(current_row_); +} + +optional GetTypeInfoReader::GetNumPrecRadix() { + const auto &array = + checked_pointer_cast(record_batch_->column(17)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetView(current_row_); +} + +optional GetTypeInfoReader::GetIntervalPrecision() { + const auto &array = + checked_pointer_cast(record_batch_->column(18)); + + if (array->IsNull(current_row_)) + return nullopt; + + return array->GetView(current_row_); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.h new file mode 100644 index 0000000000000..6349a29cf96cc --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.h @@ -0,0 +1,81 @@ +// 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 "record_batch_transformer.h" +#include +#include +#include +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using arrow::util::optional; + +class GetTypeInfoReader { +private: + std::shared_ptr record_batch_; + int64_t current_row_; + +public: + explicit GetTypeInfoReader(std::shared_ptr record_batch); + + bool Next(); + + std::string GetTypeName(); + + int32_t GetDataType(); + + optional GetColumnSize(); + + optional GetLiteralPrefix(); + + optional GetLiteralSuffix(); + + optional> GetCreateParams(); + + int32_t GetNullable(); + + bool GetCaseSensitive(); + + int32_t GetSearchable(); + + optional GetUnsignedAttribute(); + + bool GetFixedPrecScale(); + + optional GetAutoIncrement(); + + optional GetLocalTypeName(); + + optional GetMinimumScale(); + + optional GetMaximumScale(); + + int32_t GetSqlDataType(); + + optional GetDatetimeSubcode(); + + optional GetNumPrecRadix(); + + optional GetIntervalPrecision(); + +}; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index ac0c76f901ac9..76941580b7ee1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -59,6 +59,8 @@ ConvertCToArrowDataType(odbcabstraction::CDataType data_type) { case odbcabstraction::CDataType_BINARY: return arrow::binary(); } + + throw odbcabstraction::DriverException(std::string("Invalid target type: ") + std::to_string(data_type)); } std::shared_ptr diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index 13a2ec2e66561..e9ac85f1b2ce8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -35,6 +35,17 @@ using arrow::util::nullopt; constexpr int32_t StringColumnLength = 1024; // TODO: Get from connection +namespace { +std::shared_ptr empty_metadata_map(new arrow::KeyValueMetadata); + +inline arrow::flight::sql::ColumnMetadata GetMetadata(const std::shared_ptr &field) { + const auto &metadata_map = field->metadata(); + + arrow::flight::sql::ColumnMetadata metadata(metadata_map ? metadata_map : empty_metadata_map); + return metadata; +} +} + size_t FlightSqlResultSetMetadata::GetColumnCount() { return schema_->num_fields(); } @@ -48,17 +59,13 @@ std::string FlightSqlResultSetMetadata::GetName(int column_position) { } size_t FlightSqlResultSetMetadata::GetPrecision(int column_position) { - arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); - const auto &result = metadata.GetPrecision(); - ThrowIfNotOK(result.status()); - return result.ValueOrDie(); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); + return metadata.GetPrecision().ValueOrElse([] { return 0; }); } size_t FlightSqlResultSetMetadata::GetScale(int column_position) { - arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); - const auto &result = metadata.GetScale(); - ThrowIfNotOK(result.status()); - return result.ValueOrDie(); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); + return metadata.GetScale().ValueOrElse([] { return 0; }); } SqlDataType FlightSqlResultSetMetadata::GetDataType(int column_position) { @@ -73,19 +80,19 @@ FlightSqlResultSetMetadata::IsNullable(int column_position) { } std::string FlightSqlResultSetMetadata::GetSchemaName(int column_position) { - arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); return metadata.GetSchemaName().ValueOrElse([] { return ""; }); } std::string FlightSqlResultSetMetadata::GetCatalogName(int column_position) { - arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); return metadata.GetCatalogName().ValueOrElse([] { return ""; }); } std::string FlightSqlResultSetMetadata::GetTableName(int column_position) { - arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); return metadata.GetTableName().ValueOrElse([] { return ""; }); } @@ -97,7 +104,7 @@ std::string FlightSqlResultSetMetadata::GetColumnLabel(int column_position) { size_t FlightSqlResultSetMetadata::GetColumnDisplaySize( int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - arrow::flight::sql::ColumnMetadata metadata(field->metadata()); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); int32_t column_size = metadata.GetPrecision().ValueOrElse([] { return StringColumnLength; }); SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); @@ -110,7 +117,7 @@ std::string FlightSqlResultSetMetadata::GetBaseColumnName(int column_position) { } std::string FlightSqlResultSetMetadata::GetBaseTableName(int column_position) { - arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); return metadata.GetTableName().ValueOrElse([] { return ""; }); } @@ -121,7 +128,7 @@ std::string FlightSqlResultSetMetadata::GetConciseType(int column_position) { size_t FlightSqlResultSetMetadata::GetLength(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - arrow::flight::sql::ColumnMetadata metadata(field->metadata()); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); int32_t column_size = metadata.GetPrecision().ValueOrElse([] { return StringColumnLength; }); SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); @@ -140,7 +147,7 @@ std::string FlightSqlResultSetMetadata::GetLiteralSuffix(int column_position) { } std::string FlightSqlResultSetMetadata::GetLocalTypeName(int column_position) { - arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); // TODO: Is local type name the same as type name? return metadata.GetTypeName().ValueOrElse([] { return ""; }); @@ -148,8 +155,6 @@ std::string FlightSqlResultSetMetadata::GetLocalTypeName(int column_position) { size_t FlightSqlResultSetMetadata::GetNumPrecRadix(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - arrow::flight::sql::ColumnMetadata metadata(field->metadata()); - SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); return GetRadixFromSqlDataType(data_type_v3).value_or(NO_TOTAL); @@ -157,7 +162,7 @@ size_t FlightSqlResultSetMetadata::GetNumPrecRadix(int column_position) { size_t FlightSqlResultSetMetadata::GetOctetLength(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - arrow::flight::sql::ColumnMetadata metadata(field->metadata()); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); int32_t column_size = metadata.GetPrecision().ValueOrElse([] { return StringColumnLength; }); SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); @@ -166,7 +171,7 @@ size_t FlightSqlResultSetMetadata::GetOctetLength(int column_position) { } std::string FlightSqlResultSetMetadata::GetTypeName(int column_position) { - arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); return metadata.GetTypeName().ValueOrElse([] { return ""; }); } @@ -177,21 +182,21 @@ FlightSqlResultSetMetadata::GetUpdatable(int column_position) { } bool FlightSqlResultSetMetadata::IsAutoUnique(int column_position) { - arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); // TODO: Is AutoUnique equivalent to AutoIncrement? return metadata.GetIsAutoIncrement().ValueOrElse([] { return false; }); } bool FlightSqlResultSetMetadata::IsCaseSensitive(int column_position) { - arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); return metadata.GetIsCaseSensitive().ValueOrElse([] { return false; }); } driver::odbcabstraction::Searchability FlightSqlResultSetMetadata::IsSearchable(int column_position) { - arrow::flight::sql::ColumnMetadata metadata(schema_->field(column_position - 1)->metadata()); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); bool is_searchable = metadata.GetIsSearchable().ValueOrElse([] { return false; }); return is_searchable ? odbcabstraction::SEARCHABILITY_ALL : odbcabstraction::SEARCHABILITY_NONE; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index 5e033812c2bee..b9548921b6d2f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -21,6 +21,7 @@ #include "flight_sql_result_set_metadata.h" #include "flight_sql_statement_get_columns.h" #include "flight_sql_statement_get_tables.h" +#include "flight_sql_statement_get_type_info.h" #include "record_batch_transformer.h" #include "utils.h" #include @@ -252,7 +253,39 @@ std::shared_ptr FlightSqlStatement::GetColumns_V3( return current_result_set_; } -std::shared_ptr FlightSqlStatement::GetTypeInfo(int dataType) { +std::shared_ptr FlightSqlStatement::GetTypeInfo_V2(int16_t data_type) { + ClosePreparedStatementIfAny(prepared_statement_); + + Result> result = sql_client_.GetXdbcTypeInfo( + call_options_); + ThrowIfNotOK(result.status()); + + auto flight_info = result.ValueOrDie(); + + auto transformer = std::make_shared( + odbcabstraction::V_2, data_type); + + current_result_set_ = std::make_shared( + sql_client_, call_options_, flight_info, transformer, diagnostics_); + + return current_result_set_; +} + +std::shared_ptr FlightSqlStatement::GetTypeInfo_V3(int16_t data_type) { + ClosePreparedStatementIfAny(prepared_statement_); + + Result> result = sql_client_.GetXdbcTypeInfo( + call_options_); + ThrowIfNotOK(result.status()); + + auto flight_info = result.ValueOrDie(); + + auto transformer = std::make_shared( + odbcabstraction::V_3, data_type); + + current_result_set_ = std::make_shared( + sql_client_, call_options_, flight_info, transformer, diagnostics_); + return current_result_set_; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h index 5073d24b6a518..453402d0ad824 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h @@ -81,7 +81,9 @@ class FlightSqlStatement : public odbcabstraction::Statement { GetColumns_V3(const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::string *column_name) override; - std::shared_ptr GetTypeInfo(int dataType) override; + std::shared_ptr GetTypeInfo_V2(int16_t data_type) override; + + std::shared_ptr GetTypeInfo_V3(int16_t data_type) override; odbcabstraction::Diagnostics &GetDiagnostics() override; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc index 5fdee198b3a95..21780366fd037 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc @@ -122,7 +122,7 @@ Transform_inner(const odbcabstraction::OdbcVersion odbc_version, data.column_name = field->name(); data.data_type = odbc_version == odbcabstraction::V_3 ? data_type_v3 - : GetDataTypeFromArrowField_V2(field); + : ConvertSqlDataTypeFromV3ToV2(data_type_v3); // TODO: Use `metadata.GetTypeName()` when ARROW-16064 is merged. const auto &type_name_result = field->metadata()->Get("ARROW:FLIGHT:SQL:TYPE_NAME"); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc new file mode 100644 index 0000000000000..c1231a5683761 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc @@ -0,0 +1,231 @@ +// 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 "flight_sql_statement_get_type_info.h" +#include +#include "flight_sql_get_type_info_reader.h" +#include "utils.h" +#include + +namespace driver { +namespace flight_sql { + +using arrow::util::make_optional; +using arrow::util::nullopt; +using arrow::util::optional; + +namespace { +std::shared_ptr GetTypeInfo_V3_Schema() { + return schema({ + field("TYPE_NAME", utf8(), false), + field("DATA_TYPE", int16(), false), + field("COLUMN_SIZE", int32()), + field("LITERAL_PREFIX", utf8()), + field("LITERAL_SUFFIX", utf8()), + field("CREATE_PARAMS", utf8()), + field("NULLABLE", int16(), false), + field("CASE_SENSITIVE", int16(), false), + field("SEARCHABLE", int16(), false), + field("UNSIGNED_ATTRIBUTE", int16()), + field("FIXED_PREC_SCALE", int16(), false), + field("AUTO_UNIQUE_VALUE", int16()), + field("LOCAL_TYPE_NAME", utf8()), + field("MINIMUM_SCALE", int16()), + field("MAXIMUM_SCALE", int16()), + field("SQL_DATA_TYPE", int16(), false), + field("SQL_DATETIME_SUB", int16()), + field("NUM_PREC_RADIX", int32()), + field("INTERVAL_PRECISION", int16()), + }); +} + +std::shared_ptr GetTypeInfo_V2_Schema() { + return schema({ + field("TYPE_NAME", utf8(), false), + field("DATA_TYPE", int16(), false), + field("PRECISION", int32()), + field("LITERAL_PREFIX", utf8()), + field("LITERAL_SUFFIX", utf8()), + field("CREATE_PARAMS", utf8()), + field("NULLABLE", int16(), false), + field("CASE_SENSITIVE", int16(), false), + field("SEARCHABLE", int16(), false), + field("UNSIGNED_ATTRIBUTE", int16()), + field("MONEY", int16(), false), + field("AUTO_INCREMENT", int16()), + field("LOCAL_TYPE_NAME", utf8()), + field("MINIMUM_SCALE", int16()), + field("MAXIMUM_SCALE", int16()), + }); +} + +Result> +Transform_inner(const odbcabstraction::OdbcVersion odbc_version, + const std::shared_ptr &original, + int data_type) { + GetTypeInfo_RecordBatchBuilder builder(odbc_version); + GetTypeInfo_RecordBatchBuilder::Data data; + + GetTypeInfoReader reader(original); + + while (reader.Next()) { + auto data_type_v3 = static_cast(reader.GetDataType()); + int16_t data_type_v2 = ConvertSqlDataTypeFromV3ToV2(data_type_v3); + + if (data_type != odbcabstraction::ALL_TYPES && data_type_v3 != data_type && data_type_v2 != data_type) { + continue; + } + + data.data_type = odbc_version == odbcabstraction::V_3 + ? data_type_v3 + : data_type_v2; + data.type_name = reader.GetTypeName(); + data.column_size = reader.GetColumnSize(); + data.literal_prefix = reader.GetLiteralPrefix(); + data.literal_suffix = reader.GetLiteralSuffix(); + + const auto &create_params = reader.GetCreateParams(); + if (create_params) { + data.create_params = boost::algorithm::join(*create_params, ","); + } else { + data.create_params = nullopt; + } + + data.nullable = reader.GetNullable() ? odbcabstraction::NULLABILITY_NULLABLE : odbcabstraction::NULLABILITY_NO_NULLS; + data.case_sensitive = reader.GetCaseSensitive(); + data.searchable = reader.GetSearchable() ? odbcabstraction::SEARCHABILITY_ALL : odbcabstraction::SEARCHABILITY_NONE; + data.unsigned_attribute = reader.GetUnsignedAttribute(); + data.fixed_prec_scale = reader.GetFixedPrecScale(); + data.auto_unique_value = reader.GetAutoIncrement(); + data.local_type_name = reader.GetLocalTypeName(); + data.minimum_scale = reader.GetMinimumScale(); + data.maximum_scale = reader.GetMaximumScale(); + data.sql_data_type = static_cast(reader.GetSqlDataType()); + data.sql_datetime_sub = GetSqlDateTimeSubCode(static_cast(data.data_type)); + data.num_prec_radix = reader.GetNumPrecRadix(); + data.interval_precision = reader.GetIntervalPrecision(); + + ARROW_RETURN_NOT_OK(builder.Append(data)); + } + + return builder.Build(); +} +} // namespace + +GetTypeInfo_RecordBatchBuilder::GetTypeInfo_RecordBatchBuilder( + odbcabstraction::OdbcVersion odbc_version) + : odbc_version_(odbc_version) {} + +Result> GetTypeInfo_RecordBatchBuilder::Build() { + + ARROW_ASSIGN_OR_RAISE(auto TYPE_NAME_Array, TYPE_NAME_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto DATA_TYPE_Array, DATA_TYPE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto COLUMN_SIZE_Array, COLUMN_SIZE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto LITERAL_PREFIX_Array, LITERAL_PREFIX_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto LITERAL_SUFFIX_Array, LITERAL_SUFFIX_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto CREATE_PARAMS_Array, CREATE_PARAMS_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto NULLABLE_Array, NULLABLE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto CASE_SENSITIVE_Array, CASE_SENSITIVE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto SEARCHABLE_Array, SEARCHABLE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto UNSIGNED_ATTRIBUTE_Array, UNSIGNED_ATTRIBUTE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto FIXED_PREC_SCALE_Array, FIXED_PREC_SCALE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto AUTO_UNIQUE_VALUE_Array, AUTO_UNIQUE_VALUE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto LOCAL_TYPE_NAME_Array, LOCAL_TYPE_NAME_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto MINIMUM_SCALE_Array, MINIMUM_SCALE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto MAXIMUM_SCALE_Array, MAXIMUM_SCALE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto SQL_DATA_TYPE_Array, SQL_DATA_TYPE_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto SQL_DATETIME_SUB_Array, SQL_DATETIME_SUB_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto NUM_PREC_RADIX_Array, NUM_PREC_RADIX_Builder_.Finish()) + ARROW_ASSIGN_OR_RAISE(auto INTERVAL_PRECISION_Array, INTERVAL_PRECISION_Builder_.Finish()) + + std::vector> arrays = { + TYPE_NAME_Array, + DATA_TYPE_Array, + COLUMN_SIZE_Array, + LITERAL_PREFIX_Array, + LITERAL_SUFFIX_Array, + CREATE_PARAMS_Array, + NULLABLE_Array, + CASE_SENSITIVE_Array, + SEARCHABLE_Array, + UNSIGNED_ATTRIBUTE_Array, + FIXED_PREC_SCALE_Array, + AUTO_UNIQUE_VALUE_Array, + LOCAL_TYPE_NAME_Array, + MINIMUM_SCALE_Array, + MAXIMUM_SCALE_Array, + SQL_DATA_TYPE_Array, + SQL_DATETIME_SUB_Array, + NUM_PREC_RADIX_Array, + INTERVAL_PRECISION_Array + }; + + const std::shared_ptr &schema = odbc_version_ == odbcabstraction::V_3 + ? GetTypeInfo_V3_Schema() + : GetTypeInfo_V2_Schema(); + return RecordBatch::Make(schema, num_rows_, arrays); +} + +Status GetTypeInfo_RecordBatchBuilder::Append( + const GetTypeInfo_RecordBatchBuilder::Data &data) { + ARROW_RETURN_NOT_OK(AppendToBuilder(TYPE_NAME_Builder_, data.type_name)); + ARROW_RETURN_NOT_OK(AppendToBuilder(DATA_TYPE_Builder_, data.data_type)); + ARROW_RETURN_NOT_OK(AppendToBuilder(COLUMN_SIZE_Builder_, data.column_size)); + ARROW_RETURN_NOT_OK(AppendToBuilder(LITERAL_PREFIX_Builder_, data.literal_prefix)); + ARROW_RETURN_NOT_OK(AppendToBuilder(LITERAL_SUFFIX_Builder_, data.literal_suffix)); + ARROW_RETURN_NOT_OK(AppendToBuilder(CREATE_PARAMS_Builder_, data.create_params)); + ARROW_RETURN_NOT_OK(AppendToBuilder(NULLABLE_Builder_, data.nullable)); + ARROW_RETURN_NOT_OK(AppendToBuilder(CASE_SENSITIVE_Builder_, data.case_sensitive)); + ARROW_RETURN_NOT_OK(AppendToBuilder(SEARCHABLE_Builder_, data.searchable)); + ARROW_RETURN_NOT_OK(AppendToBuilder(UNSIGNED_ATTRIBUTE_Builder_, data.unsigned_attribute)); + ARROW_RETURN_NOT_OK(AppendToBuilder(FIXED_PREC_SCALE_Builder_, data.fixed_prec_scale)); + ARROW_RETURN_NOT_OK(AppendToBuilder(AUTO_UNIQUE_VALUE_Builder_, data.auto_unique_value)); + ARROW_RETURN_NOT_OK(AppendToBuilder(LOCAL_TYPE_NAME_Builder_, data.local_type_name)); + ARROW_RETURN_NOT_OK(AppendToBuilder(MINIMUM_SCALE_Builder_, data.minimum_scale)); + ARROW_RETURN_NOT_OK(AppendToBuilder(MAXIMUM_SCALE_Builder_, data.maximum_scale)); + ARROW_RETURN_NOT_OK(AppendToBuilder(SQL_DATA_TYPE_Builder_, data.sql_data_type)); + ARROW_RETURN_NOT_OK(AppendToBuilder(SQL_DATETIME_SUB_Builder_, data.sql_datetime_sub)); + ARROW_RETURN_NOT_OK(AppendToBuilder(NUM_PREC_RADIX_Builder_, data.num_prec_radix)); + ARROW_RETURN_NOT_OK(AppendToBuilder(INTERVAL_PRECISION_Builder_, data.interval_precision)); + num_rows_++; + + return Status::OK(); +} + +GetTypeInfo_Transformer::GetTypeInfo_Transformer( + const odbcabstraction::OdbcVersion odbc_version, + int data_type) + : odbc_version_(odbc_version), + data_type_(data_type) { +} + +std::shared_ptr GetTypeInfo_Transformer::Transform( + const std::shared_ptr &original) { + const Result> &result = + Transform_inner(odbc_version_, original, data_type_); + ThrowIfNotOK(result.status()); + + return result.ValueOrDie(); +} + +std::shared_ptr GetTypeInfo_Transformer::GetTransformedSchema() { + return odbc_version_ == odbcabstraction::V_3 ? GetTypeInfo_V3_Schema() + : GetTypeInfo_V2_Schema(); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.h new file mode 100644 index 0000000000000..40137b58c0d97 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.h @@ -0,0 +1,102 @@ +// 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 "record_batch_transformer.h" +#include +#include +#include +#include +#include + +namespace driver { +namespace flight_sql { + +using arrow::util::optional; + +class GetTypeInfo_RecordBatchBuilder { +private: + odbcabstraction::OdbcVersion odbc_version_; + + StringBuilder TYPE_NAME_Builder_; + Int16Builder DATA_TYPE_Builder_; + Int32Builder COLUMN_SIZE_Builder_; + StringBuilder LITERAL_PREFIX_Builder_; + StringBuilder LITERAL_SUFFIX_Builder_; + StringBuilder CREATE_PARAMS_Builder_; + Int16Builder NULLABLE_Builder_; + Int16Builder CASE_SENSITIVE_Builder_; + Int16Builder SEARCHABLE_Builder_; + Int16Builder UNSIGNED_ATTRIBUTE_Builder_; + Int16Builder FIXED_PREC_SCALE_Builder_; + Int16Builder AUTO_UNIQUE_VALUE_Builder_; + StringBuilder LOCAL_TYPE_NAME_Builder_; + Int16Builder MINIMUM_SCALE_Builder_; + Int16Builder MAXIMUM_SCALE_Builder_; + Int16Builder SQL_DATA_TYPE_Builder_; + Int16Builder SQL_DATETIME_SUB_Builder_; + Int32Builder NUM_PREC_RADIX_Builder_; + Int16Builder INTERVAL_PRECISION_Builder_; + int64_t num_rows_{0}; + +public: + struct Data { + std::string type_name; + int16_t data_type; + optional column_size; + optional literal_prefix; + optional literal_suffix; + optional create_params; + int16_t nullable; + int16_t case_sensitive; + int16_t searchable; + optional unsigned_attribute; + int16_t fixed_prec_scale; + optional auto_unique_value; + optional local_type_name; + optional minimum_scale; + optional maximum_scale; + int16_t sql_data_type; + optional sql_datetime_sub; + optional num_prec_radix; + optional interval_precision; + }; + + explicit GetTypeInfo_RecordBatchBuilder( + odbcabstraction::OdbcVersion odbc_version); + + Result> Build(); + + Status Append(const Data &data); +}; + +class GetTypeInfo_Transformer : public RecordBatchTransformer { +private: + odbcabstraction::OdbcVersion odbc_version_; + int data_type_; + +public: + explicit GetTypeInfo_Transformer(odbcabstraction::OdbcVersion odbc_version_, + int data_type_); + + std::shared_ptr + Transform(const std::shared_ptr &original) override; + + std::shared_ptr GetTransformedSchema() override; +}; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index a0fc39f371c96..056f535f5ca16 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -92,18 +92,16 @@ GetDataTypeFromArrowField_V3(const std::shared_ptr &field) { return odbcabstraction::SqlDataType_VARCHAR; } -int16_t -GetDataTypeFromArrowField_V2(const std::shared_ptr &field) { - SqlDataType type = GetDataTypeFromArrowField_V3(field); - switch (type) { - case SqlDataType_TYPE_DATE: - return 9; // Same as SQL_DATE from sqlext.h - case SqlDataType_TYPE_TIME: - return 10; // Same as SQL_TIME from sqlext.h - case SqlDataType_TYPE_TIMESTAMP: - return 11; // Same as SQL_TIMESTAMP from sqlext.h - default: - return type; +int16_t ConvertSqlDataTypeFromV3ToV2(int16_t data_type_v3) { + switch (data_type_v3) { + case SqlDataType_TYPE_DATE: + return 9; // Same as SQL_DATE from sqlext.h + case SqlDataType_TYPE_TIME: + return 10; // Same as SQL_TIME from sqlext.h + case SqlDataType_TYPE_TIMESTAMP: + return 11; // Same as SQL_TIMESTAMP from sqlext.h + default: + return data_type_v3; } } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index 1d397b1ec87ab..ad9c41fd98985 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -67,8 +67,7 @@ arrow::Status AppendToBuilder(BUILDER &builder, T value) { odbcabstraction::SqlDataType GetDataTypeFromArrowField_V3(const std::shared_ptr &field); -int16_t -GetDataTypeFromArrowField_V2(const std::shared_ptr &field); +int16_t ConvertSqlDataTypeFromV3ToV2(int16_t data_type_v3); std::string GetTypeNameFromSqlDataType(int16_t data_type); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h index b5d10fea7f962..74fdc580b4387 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h @@ -163,11 +163,20 @@ class Statement { /// data types are intended for use in Data Definition Language (DDL) /// statements. /// - /// Accepts ODBC 2.x or 3.x data types as input. - /// Reports results according to which ODBC version is set on Driver. + /// NOTE: This is meant to be used by ODBC 2.x binding. + /// + /// \param data_type The SQL data type. + virtual std::shared_ptr GetTypeInfo_V2(int16_t data_type) = 0; + + /// \brief Returns information about data types supported by the data source. + /// The driver returns the information in the form of an SQL result set. The + /// data types are intended for use in Data Definition Language (DDL) + /// statements. + /// + /// NOTE: This is meant to be used by ODBC 3.x binding. /// - /// \param dataType The SQL data type. - virtual std::shared_ptr GetTypeInfo(int dataType) = 0; + /// \param data_type The SQL data type. + virtual std::shared_ptr GetTypeInfo_V3(int16_t data_type) = 0; /// \brief Gets the diagnostics for this statement. /// \return the diagnostics diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 02441612a36a7..e8670e4019848 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -121,6 +121,7 @@ enum Updatability { constexpr ssize_t NULL_DATA = -1; constexpr ssize_t NO_TOTAL = -4; +constexpr ssize_t ALL_TYPES = 0; } // namespace odbcabstraction } // namespace driver From 65df6008fe01d69448e388b724f5da21d9fdc77d Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 6 May 2022 20:36:36 +0000 Subject: [PATCH 088/183] Add Boost Beast dependency to vcpkg Add dependency on Boost Beast to vcpkg. Used for complex type support. Change-Id: I29e8083cbdf2511971969450fe8260560d2291d1 --- .../flightsql-odbc-clone/flightsql-odbc/vcpkg.json | 1 + 1 file changed, 1 insertion(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json index 3dc1ad7a558ca..959c675cceee2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json @@ -4,6 +4,7 @@ "dependencies": [ "abseil", "benchmark", + "boost-beast", "boost-filesystem", "boost-multiprecision", "boost-process", From 4ee80662c3e0beac37c816052410a80e6f10a5e1 Mon Sep 17 00:00:00 2001 From: James Duong Date: Tue, 5 Apr 2022 00:11:46 +0000 Subject: [PATCH 089/183] Fix Windows build errors Fix portability issues on Windows: - GetMessage symbol collides with windows definition. Replace with GetMessageText - include odbcabstraction/platform.h before using ssize_t Change-Id: I937a28577410411d59b9ee727983e0f57ccea6b2 Change-Id: I8d4c32c3a13d128305b6a1f47ce30013aa138c59 --- .../flightsql-odbc/flight_sql/flight_sql_result_set.cc | 2 +- .../flightsql-odbc/odbcabstraction/diagnostics.cc | 4 ++-- .../flightsql-odbc/odbcabstraction/exceptions.cc | 6 +++--- .../odbcabstraction/include/odbcabstraction/diagnostics.h | 2 +- .../odbcabstraction/include/odbcabstraction/exceptions.h | 4 ++-- .../odbcabstraction/include/odbcabstraction/types.h | 2 ++ 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index 8b7991e1c1cbe..ea16492a5d255 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -106,7 +106,7 @@ size_t FlightSqlResultSet::Move(size_t rows) { continue; } - for (auto it = columns_.begin(); it != columns_.end(); *it++) { + for (auto it = columns_.begin(); it != columns_.end(); ++it) { auto &column = *it; // There can be unbound columns. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/diagnostics.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/diagnostics.cc index b9c0d6c376b37..596f76f6441b4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/diagnostics.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/diagnostics.cc @@ -55,7 +55,7 @@ std::string Diagnostics::GetVendor() const { void driver::odbcabstraction::Diagnostics::AddError( const driver::odbcabstraction::DriverException &exception) { auto record = std::unique_ptr(new DiagnosticsRecord{ - exception.GetMessage(), exception.GetSqlState(), exception.GetNativeError()}); + exception.GetMessageText(), exception.GetSqlState(), exception.GetNativeError()}); if (version_ == OdbcVersion::V_2) { RewriteSQLStateForODBC2(record->sql_state_); } @@ -81,7 +81,7 @@ std::string driver::odbcabstraction::Diagnostics::GetMessageText( message += std::string("[") + vendor_ + "]"; } const DiagnosticsRecord* rec = GetRecordAtIndex(record_index); - return message + "[" + data_source_component_ + "] (" + std::to_string(rec->native_error_) + ") " + rec->message_; + return message + "[" + data_source_component_ + "] (" + std::to_string(rec->native_error_) + ") " + rec->msg_text_; } OdbcVersion Diagnostics::GetOdbcVersion() const { return version_; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc index 666dc8ee45c11..9f79706ca58f8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc @@ -24,12 +24,12 @@ namespace odbcabstraction { DriverException::DriverException(std::string message, std::string sql_state, int32_t native_error) - : message_(std::move(message)), + : msg_text_(std::move(message)), sql_state_(std::move(sql_state)), native_error_(native_error) {} -const char *DriverException::what() const throw() { return message_.c_str(); } -const std::string &DriverException::GetMessage() const { return message_; } +const char *DriverException::what() const throw() { return msg_text_.c_str(); } +const std::string &DriverException::GetMessageText() const { return msg_text_; } const std::string &DriverException::GetSqlState() const { return sql_state_; } int32_t DriverException::GetNativeError() const { return native_error_; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/diagnostics.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/diagnostics.h index 7ed31558a75ac..001e64be4e455 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/diagnostics.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/diagnostics.h @@ -29,7 +29,7 @@ namespace odbcabstraction { class Diagnostics { public: struct DiagnosticsRecord { - std::string message_; + std::string msg_text_; std::string sql_state_; int32_t native_error_; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h index 4eff3657b088d..d60a23c48e1bf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h @@ -33,12 +33,12 @@ class DriverException : public std::exception { const char *what() const throw() override; - const std::string &GetMessage() const; + const std::string &GetMessageText() const; const std::string &GetSqlState() const; int32_t GetNativeError() const; private: - const std::string message_; + const std::string msg_text_; const std::string sql_state_; const int32_t native_error_; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index e8670e4019848..7eaa119c20f74 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -17,6 +17,8 @@ #pragma once +#include + namespace driver { namespace odbcabstraction { From 2f1259b86ce0c38841c1678ac8ab130fa806319f Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Thu, 5 May 2022 16:28:17 -0300 Subject: [PATCH 090/183] Fix ODBC v2 C Data Types mapping Change-Id: I86672dae45686f5750c2d798e4cd4c2ea26fbefc --- .../flight_sql/flight_sql_result_set.cc | 10 ++++---- .../flight_sql/flight_sql_result_set.h | 4 ++-- .../flight_sql_result_set_accessors.cc | 2 +- .../flightsql-odbc/flight_sql/utils.cc | 23 +++++++++++++++++++ .../flightsql-odbc/flight_sql/utils.h | 2 ++ .../include/odbcabstraction/result_set.h | 4 ++-- .../include/odbcabstraction/types.h | 3 +++ 7 files changed, 38 insertions(+), 10 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index ea16492a5d255..1b054a81b89bb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -134,14 +134,14 @@ void FlightSqlResultSet::Close() { current_chunk_.data = nullptr; } -bool FlightSqlResultSet::GetData(int column_n, CDataType target_type, +bool FlightSqlResultSet::GetData(int column_n, int16_t target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) { - ColumnBinding binding(target_type, precision, scale, buffer, buffer_length, + ColumnBinding binding(ConvertCDataTypeFromV2ToV3(target_type), precision, scale, buffer, buffer_length, strlen_buffer); auto &column = columns_[column_n - 1]; - Accessor *accessor = column.GetAccessorForGetData(target_type); + Accessor *accessor = column.GetAccessorForGetData(binding.target_type); int64_t value_offset = get_data_offsets_[column_n - 1]; @@ -166,7 +166,7 @@ std::shared_ptr FlightSqlResultSet::GetMetadata() { return metadata_; } -void FlightSqlResultSet::BindColumn(int column_n, CDataType target_type, +void FlightSqlResultSet::BindColumn(int column_n, int16_t target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) { @@ -183,7 +183,7 @@ void FlightSqlResultSet::BindColumn(int column_n, CDataType target_type, num_binding_++; } - ColumnBinding binding(target_type, precision, scale, buffer, buffer_length, + ColumnBinding binding(ConvertCDataTypeFromV2ToV3(target_type), precision, scale, buffer, buffer_length, strlen_buffer); column.SetBinding(binding); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index 1ce9892dab424..deccf1bb84185 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -76,7 +76,7 @@ class FlightSqlResultSet : public ResultSet { void Close() override; - bool GetData(int column_n, CDataType target_type, int precision, int scale, + bool GetData(int column_n, int16_t target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) override; @@ -86,7 +86,7 @@ class FlightSqlResultSet : public ResultSet { std::shared_ptr GetMetadata() override; - void BindColumn(int column_n, CDataType target_type, int precision, int scale, + void BindColumn(int column_n, int16_t target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) override; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index 8e6350de66d4b..ccfdab5f160f0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -39,7 +39,7 @@ const std::unordered_map(array); + return new StringArrayFlightSqlAccessor(array); }}, {SourceAndTargetPair(arrow::Type::type::DOUBLE, CDataType_DOUBLE), [](arrow::Array *array) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 056f535f5ca16..6a7e719f17110 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -105,6 +105,29 @@ int16_t ConvertSqlDataTypeFromV3ToV2(int16_t data_type_v3) { } } +CDataType ConvertCDataTypeFromV2ToV3(int16_t data_type_v2) { + switch (data_type_v2) { + case -6: // Same as SQL_C_TINYINT from sqlext.h + return CDataType_STINYINT; + case 4: // Same as SQL_C_LONG from sqlext.h + return CDataType_SLONG; + case 5: // Same as SQL_C_SHORT from sqlext.h + return CDataType_SSHORT; + case 7: // Same as SQL_C_FLOAT from sqlext.h + return CDataType_FLOAT; + case 8: // Same as SQL_C_DOUBLE from sqlext.h + return CDataType_DOUBLE; + case 9: // Same as SQL_C_DATE from sqlext.h + return CDataType_DATE; + case 10: // Same as SQL_C_TIME from sqlext.h + return CDataType_TIME; + case 11: // Same as SQL_C_TIMESTAMP from sqlext.h + return CDataType_TIMESTAMP; + default: + return static_cast(data_type_v2); + } +} + std::string GetTypeNameFromSqlDataType(int16_t data_type) { switch (data_type) { case SqlDataType_CHAR: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index ad9c41fd98985..7c514670b090a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -69,6 +69,8 @@ GetDataTypeFromArrowField_V3(const std::shared_ptr &field); int16_t ConvertSqlDataTypeFromV3ToV2(int16_t data_type_v3); +odbcabstraction::CDataType ConvertCDataTypeFromV2ToV3(int16_t data_type_v2); + std::string GetTypeNameFromSqlDataType(int16_t data_type); optional diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h index 92b32d279686a..54c8954b07ef7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h @@ -53,7 +53,7 @@ class ResultSet { /// \param buffer_length Target buffer length. /// \param strlen_buffer Buffer that holds the length of each value contained /// on target buffer. - virtual void BindColumn(int column, CDataType target_type, int precision, + virtual void BindColumn(int column, int16_t target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) = 0; @@ -81,7 +81,7 @@ class ResultSet { /// \param strlen_buffer Buffer that holds the length of value being fetched. /// \returns true if there is more data to fetch from the current cell; /// false if the whole value was already fetched. - virtual bool GetData(int column, CDataType target_type, int precision, + virtual bool GetData(int column, int16_t target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) = 0; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 7eaa119c20f74..2d2a1f4bfe3e6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -95,6 +95,9 @@ enum CDataType { CDataType_FLOAT = 7, CDataType_DOUBLE = 8, CDataType_BIT = -7, + CDataType_DATE = 91, + CDataType_TIME = 92, + CDataType_TIMESTAMP = 93, CDataType_STINYINT = ((-6) + (-20)), CDataType_UTINYINT = ((-6) + (-22)), CDataType_SBIGINT = ((-5) + (-20)), From 1fd93fe430bdf44ed24ba91c4df14a5b35d4a0d7 Mon Sep 17 00:00:00 2001 From: James Duong Date: Tue, 10 May 2022 15:57:20 +0000 Subject: [PATCH 091/183] Correct issues in GetInfoCache - Fix string attributes to use the actual string scalar rather than the ToString() of the union. - Correct a crash iterating over the MapScalar when evaluating supported conversions. - Fix a bug where the first time GetSqlInfo gets cached, the info type that triggered the caching does not re-read from the cache. - SQL_KEYWORDS was incorrectly being handled as a string from GetSqlInfo, rather than a List Change-Id: I68ee1ab0b2680bcdc4ffed7759322de9839429e2 --- .../flight_sql/get_info_cache.cc | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc index 16c72b73b05ff..b724d140cdf4a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc @@ -303,7 +303,7 @@ bool GetInfoCache::LoadInfoFromServer() { switch (info_type) { // String properties case SqlInfoOptions::FLIGHT_SQL_SERVER_NAME: { - std::string server_name = scalar->ToString(); + std::string server_name(reinterpret_cast(scalar->value.get())->view()); // TODO: Consider creating different properties in GetSqlInfo. // TODO: Investigate if SQL_SERVER_NAME should just be the host @@ -317,7 +317,7 @@ bool GetInfoCache::LoadInfoFromServer() { break; } case SqlInfoOptions::FLIGHT_SQL_SERVER_VERSION: { - info_[SQL_DBMS_VER] = scalar->ToString(); + info_[SQL_DBMS_VER] = std::string(reinterpret_cast(scalar->value.get())->view()); break; } case SqlInfoOptions::FLIGHT_SQL_SERVER_ARROW_VERSION: { @@ -325,31 +325,27 @@ bool GetInfoCache::LoadInfoFromServer() { break; } case SqlInfoOptions::SQL_SEARCH_STRING_ESCAPE: { - info_[SQL_SEARCH_PATTERN_ESCAPE] = scalar->ToString(); + info_[SQL_SEARCH_PATTERN_ESCAPE] = std::string(reinterpret_cast(scalar->value.get())->view()); break; } case ARROW_SQL_IDENTIFIER_QUOTE_CHAR: { - info_[SQL_IDENTIFIER_QUOTE_CHAR] = scalar->ToString(); - break; - } - case ARROW_SQL_KEYWORDS: { - info_[SQL_KEYWORDS] = scalar->ToString(); + info_[SQL_IDENTIFIER_QUOTE_CHAR] = std::string(reinterpret_cast(scalar->value.get())->view()); break; } case SqlInfoOptions::SQL_EXTRA_NAME_CHARACTERS: { - info_[SQL_SPECIAL_CHARACTERS] = scalar->ToString(); + info_[SQL_SPECIAL_CHARACTERS] = std::string(reinterpret_cast(scalar->value.get())->view()); break; } case ARROW_SQL_SCHEMA_TERM: { - info_[SQL_SCHEMA_TERM] = scalar->ToString(); + info_[SQL_SCHEMA_TERM] = std::string(reinterpret_cast(scalar->value.get())->view()); break; } case ARROW_SQL_PROCEDURE_TERM: { - info_[SQL_PROCEDURE_TERM] = scalar->ToString(); + info_[SQL_PROCEDURE_TERM] = std::string(reinterpret_cast(scalar->value.get())->view()); break; } case ARROW_SQL_CATALOG_TERM: { - info_[SQL_CATALOG_TERM] = scalar->ToString(); + info_[SQL_CATALOG_TERM] = std::string(reinterpret_cast(scalar->value.get())->view()); // This property implies catalogs are supported. info_[SQL_CATALOG_NAME] = "Y"; @@ -991,10 +987,29 @@ bool GetInfoCache::LoadInfoFromServer() { break; } + case ARROW_SQL_KEYWORDS: { + std::shared_ptr list_value = + reinterpret_cast(scalar)->value; + std::string result; + for (int64_t list_index = 0; list_index < list_value->length(); + ++list_index) { + if (!list_value->IsNull(list_index)) { + if (list_index != 0) { + result += ", "; + } + + result += reinterpret_cast(list_value.get()) + ->GetString(list_index); + } + } + info_[SQL_KEYWORDS] = std::move(result); + break; + } + // Map properties case SqlInfoOptions::SQL_SUPPORTS_CONVERT: { arrow::MapScalar *map_scalar = - reinterpret_cast(scalar); + reinterpret_cast(scalar->value.get()); auto data_array = map_scalar->value; arrow::StructArray *map_contents = reinterpret_cast(data_array.get()); @@ -1071,6 +1086,7 @@ bool GetInfoCache::LoadInfoFromServer() { info_[SQL_CORRELATION_NAME] = static_cast(SQL_CN_NONE); } } + return true; } return false; From b28d52a888e68104b6b0ca9e7da731bb483c8208 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Wed, 13 Apr 2022 11:48:02 -0300 Subject: [PATCH 092/183] Implements accessor for date, time and timestamp - Add an accessor to handle date32 and date64 arrays - Add an accessor to handle timestamp arrays handling their time units - Add an accessor to handle time array handling their time units - Instantiate the accessor on the create method - Add tests for the created accessors Change-Id: Ib4dbb9a4c5ad7d4d8b261fd975992cf2cd4cd13c --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 7 + .../accessors/date_array_accessor.cc | 84 ++++++++ .../accessors/date_array_accessor.h | 44 +++++ .../accessors/date_array_accessor_test.cc | 92 +++++++++ .../flight_sql/accessors/main.h | 3 + .../accessors/time_array_accessor.cc | 81 ++++++++ .../accessors/time_array_accessor.h | 44 +++++ .../accessors/time_array_accessor_test.cc | 166 ++++++++++++++++ .../accessors/timestamp_array_accessor.cc | 90 +++++++++ .../accessors/timestamp_array_accessor.h | 46 +++++ .../timestamp_array_accessor_test.cc | 181 ++++++++++++++++++ .../flight_sql_result_set_accessors.cc | 24 ++- .../flight_sql_result_set_column.cc | 83 +++++--- .../odbcabstraction/calendar_utils.cc | 31 +++ .../include/odbcabstraction/calendar_utils.h | 27 +++ .../include/odbcabstraction/types.h | 29 +++ 16 files changed, 1000 insertions(+), 32 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 543f45026a5c3..bb1e66c3edc93 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -128,8 +128,12 @@ enable_testing() set(ARROW_ODBC_SPI_SOURCES accessors/binary_array_accessor.cc accessors/boolean_array_accessor.cc + accessors/calendar_utils.cc + accessors/date_array_accessor.cc accessors/primitive_array_accessor.cc accessors/string_array_accessor.cc + accessors/time_array_accessor.cc + accessors/timestamp_array_accessor.cc flight_sql_auth_method.cc flight_sql_connection.cc flight_sql_driver.cc @@ -207,8 +211,11 @@ target_link_libraries(arrow_odbc_spi_impl_cli arrow_odbc_spi_impl) set(ARROW_ODBC_SPI_TEST_SOURCES accessors/boolean_array_accessor_test.cc accessors/binary_array_accessor_test.cc + accessors/date_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 diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc new file mode 100644 index 0000000000000..0a431dad03c91 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc @@ -0,0 +1,84 @@ +// 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 "date_array_accessor.h" +#include "time.h" +#include "arrow/compute/api.h" +#include "odbcabstraction/calendar_utils.h" + +using namespace arrow; + + +namespace { + template long convertDate(typename T::value_type value) { + return value; + } + +/// Converts the value from the array, which is in milliseconds, to seconds. +/// \param value the value extracted from the array in milliseconds. +/// \return the converted value in seconds. + template <> long convertDate(int64_t value) { + return value / driver::flight_sql::MILLI_TO_SECONDS_DIVISOR; + } + +/// Converts the value from the array, which is in days, to seconds. +/// \param value the value extracted from the array in days. +/// \return the converted value in seconds. + template <> long convertDate(int32_t value) { + return value * driver::flight_sql::DAYS_TO_SECONDS_MULTIPLIER; + } +} // namespace + +namespace driver { +namespace flight_sql { + +using namespace odbcabstraction; + +template +DateArrayFlightSqlAccessor< + TARGET_TYPE, ARROW_ARRAY>::DateArrayFlightSqlAccessor(Array *array) + : FlightSqlAccessor>( + array) {} + +template +void DateArrayFlightSqlAccessor::MoveSingleCell_impl( + ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, + int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { + typedef unsigned char c_type; + auto *buffer = static_cast(binding->buffer); + long value = convertDate(array->Value(cell_counter)); + tm date{}; + + GetTimeForMillisSinceEpoch(date, value); + + buffer[cell_counter].year = 1900 + (date.tm_year); + buffer[cell_counter].month = date.tm_mon + 1; + buffer[cell_counter].day = date.tm_mday; + + if (binding->strlen_buffer) { + binding->strlen_buffer[cell_counter] = static_cast(sizeof(DATE_STRUCT)); + } +} + +template class DateArrayFlightSqlAccessor; +template class DateArrayFlightSqlAccessor; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h new file mode 100644 index 0000000000000..d6d1fff5a99b4 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h @@ -0,0 +1,44 @@ +// 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. + +#pragma once + +#include "arrow/type_fwd.h" +#include "types.h" +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +template +class DateArrayFlightSqlAccessor + : public FlightSqlAccessor< + ARROW_ARRAY, TARGET_TYPE, + DateArrayFlightSqlAccessor> { + +public: + explicit DateArrayFlightSqlAccessor(Array *array); + + void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, + int64_t value_offset, + odbcabstraction::Diagnostics &diagnostics); +}; +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc new file mode 100644 index 0000000000000..0f906b3da1b30 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc @@ -0,0 +1,92 @@ +// 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 "arrow/testing/builder.h" +#include "boolean_array_accessor.h" +#include "date_array_accessor.h" +#include "gtest/gtest.h" +#include "odbcabstraction/calendar_utils.h" + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +TEST(DateArrayAccessor, Test_Date32Array_CDataType_DATE) { + std::vector values = {7589, 12320, 18980, 19095}; + + std::shared_ptr array; + ArrayFromVector(values, &array); + + DateArrayFlightSqlAccessor accessor( + dynamic_cast *>(array.get())); + + std::vector buffer(values.size()); + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(CDataType_DATE, 0, 0, buffer.data(), 0, strlen_buffer); + + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); + ASSERT_EQ(values.size(), + accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + + for (size_t i = 0; i < values.size(); ++i) { + ASSERT_EQ(sizeof(DATE_STRUCT), strlen_buffer[i]); + tm date{}; + + long converted_time = values[i] * 86400; + GetTimeForMillisSinceEpoch(date, converted_time); + ASSERT_EQ((date.tm_year + 1900), buffer[i].year); + ASSERT_EQ(date.tm_mon + 1, buffer[i].month); + ASSERT_EQ(date.tm_mday, buffer[i].day); + } +} + +TEST(DateArrayAccessor, Test_Date64Array_CDataType_DATE) { + std::vector values = {86400000, 172800000, 259200000, 1649793238110, + 345600000, 432000000, 518400000}; + + std::shared_ptr array; + ArrayFromVector(values, &array); + + DateArrayFlightSqlAccessor accessor( + dynamic_cast *>(array.get())); + + std::vector buffer(values.size()); + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(CDataType_DATE, 0, 0, buffer.data(), 0, strlen_buffer); + + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); + ASSERT_EQ(values.size(), + accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + + for (size_t i = 0; i < values.size(); ++i) { + ASSERT_EQ(sizeof(DATE_STRUCT), strlen_buffer[i]); + tm date{}; + + long converted_time = values[i] / 1000; + GetTimeForMillisSinceEpoch(date, converted_time); + ASSERT_EQ((date.tm_year + 1900), buffer[i].year); + ASSERT_EQ(date.tm_mon + 1, buffer[i].month); + ASSERT_EQ(date.tm_mday, buffer[i].day); + } +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h index 8cd34cc133117..231c79e61b1c9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h @@ -19,5 +19,8 @@ #include "binary_array_accessor.h" #include "boolean_array_accessor.h" +#include "date_array_accessor.h" +#include "time_array_accessor.h" +#include "timestamp_array_accessor.h" #include "primitive_array_accessor.h" #include "string_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc new file mode 100644 index 0000000000000..8f99466df76fe --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc @@ -0,0 +1,81 @@ +// 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 "time_array_accessor.h" +#include "odbcabstraction/calendar_utils.h" + +namespace driver { +namespace flight_sql { +namespace { +template +long ConvertTimeValue(typename T::value_type value, TimeUnit::type unit) { + return value; +} + +template <> +long ConvertTimeValue(int32_t value, TimeUnit::type unit) { + return unit == TimeUnit::SECOND ? value : value / MILLI_TO_SECONDS_DIVISOR; +} + +template <> +long ConvertTimeValue(int64_t value, TimeUnit::type unit) { + return unit == TimeUnit::MICRO ? value / MICRO_TO_SECONDS_DIVISOR + : value / NANO_TO_SECONDS_DIVISOR; +} +} // namespace + +template +TimeArrayFlightSqlAccessor< + TARGET_TYPE, ARROW_ARRAY>::TimeArrayFlightSqlAccessor(Array *array) + : FlightSqlAccessor>( + array) {} + +template +void TimeArrayFlightSqlAccessor::MoveSingleCell_impl( + ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, + int64_t value_offset, odbcabstraction::Diagnostics &diagnostic) { + typedef unsigned char c_type; + auto *buffer = static_cast(binding->buffer); + + auto time_type = + arrow::internal::checked_pointer_cast(array->type()); + auto time_unit = time_type->unit(); + + tm time{}; + + auto converted_value = + ConvertTimeValue(array->Value(cell_counter), time_unit); + + GetTimeForMillisSinceEpoch(time, converted_value); + + buffer[cell_counter].hour = time.tm_hour; + buffer[cell_counter].minute = time.tm_min; + buffer[cell_counter].second = time.tm_sec; + + if (binding->strlen_buffer) { + binding->strlen_buffer[cell_counter] = static_cast(sizeof(TIME_STRUCT)); + } +} + +template class TimeArrayFlightSqlAccessor; +template class TimeArrayFlightSqlAccessor; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h new file mode 100644 index 0000000000000..3fe4f932a46f9 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h @@ -0,0 +1,44 @@ +// 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. + +#pragma once + +#include "arrow/type_fwd.h" +#include "types.h" +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +template +class TimeArrayFlightSqlAccessor + : public FlightSqlAccessor< + ARROW_ARRAY, TARGET_TYPE, + TimeArrayFlightSqlAccessor> { + +public: + explicit TimeArrayFlightSqlAccessor(Array *array); + + void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, + int64_t value_offset, + odbcabstraction::Diagnostics &diagnostic); +}; +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc new file mode 100644 index 0000000000000..792a1b639e28b --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc @@ -0,0 +1,166 @@ +// 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 "arrow/testing/builder.h" +#include "time_array_accessor.h" +#include "utils.h" +#include "gtest/gtest.h" +#include "odbcabstraction/calendar_utils.h" + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +TEST(TEST_TIME32, TIME_WITH_SECONDS) { + auto value_field = field("f0", time32(TimeUnit::SECOND)); + + std::vector t32_values = {14896, 14897, 14892, 85400, 14893, 14895}; + + std::shared_ptr time32_array; + ArrayFromVector(value_field->type(), + t32_values, &time32_array); + + TimeArrayFlightSqlAccessor accessor(time32_array.get()); + + std::vector buffer(t32_values.size()); + ssize_t strlen_buffer[t32_values.size()]; + + ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer); + + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); + ASSERT_EQ(t32_values.size(), + accessor.GetColumnarData(&binding, 0, t32_values.size(), 0, diagnostics)); + + for (size_t i = 0; i < t32_values.size(); ++i) { + ASSERT_EQ(sizeof(TIME_STRUCT), strlen_buffer[i]); + + tm time{}; + + GetTimeForMillisSinceEpoch(time, t32_values[i]); + ASSERT_EQ(buffer[i].hour, time.tm_hour); + ASSERT_EQ(buffer[i].minute, time.tm_min); + ASSERT_EQ(buffer[i].second, time.tm_sec); + } +} + +TEST(TEST_TIME32, TIME_WITH_MILLI) { + auto value_field = field("f0", time32(TimeUnit::MILLI)); + std::vector t32_values = {14896000, 14897000, 14892000, + 85400000, 14893000, 14895000}; + + std::shared_ptr time32_array; + ArrayFromVector(value_field->type(), + t32_values, &time32_array); + + TimeArrayFlightSqlAccessor accessor(time32_array.get()); + + std::vector buffer(t32_values.size()); + ssize_t strlen_buffer[t32_values.size()]; + + ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer); + + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); + ASSERT_EQ(t32_values.size(), + accessor.GetColumnarData(&binding, 0, t32_values.size(), 0, diagnostics)); + + for (size_t i = 0; i < t32_values.size(); ++i) { + ASSERT_EQ(sizeof(TIME_STRUCT), strlen_buffer[i]); + + tm time{}; + + long convertedValue = t32_values[i] / MILLI_TO_SECONDS_DIVISOR; + GetTimeForMillisSinceEpoch(time, convertedValue); + + ASSERT_EQ(buffer[i].hour, time.tm_hour); + ASSERT_EQ(buffer[i].minute, time.tm_min); + ASSERT_EQ(buffer[i].second, time.tm_sec); + } +} + +TEST(TEST_TIME64, TIME_WITH_MICRO) { + auto value_field = field("f0", time64(TimeUnit::MICRO)); + + std::vector t64_values = {14896000, 14897000, 14892000, + 85400000, 14893000, 14895000}; + + std::shared_ptr time64_array; + ArrayFromVector(value_field->type(), + t64_values, &time64_array); + + TimeArrayFlightSqlAccessor accessor(time64_array.get()); + + std::vector buffer(t64_values.size()); + ssize_t strlen_buffer[t64_values.size()]; + + ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer); + + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); + ASSERT_EQ(t64_values.size(), + accessor.GetColumnarData(&binding, 0, t64_values.size(), 0, diagnostics)); + + for (size_t i = 0; i < t64_values.size(); ++i) { + ASSERT_EQ(sizeof(TIME_STRUCT), strlen_buffer[i]); + + tm time{}; + + const auto convertedValue = t64_values[i] / MICRO_TO_SECONDS_DIVISOR; + GetTimeForMillisSinceEpoch(time, convertedValue); + + ASSERT_EQ(buffer[i].hour, time.tm_hour); + ASSERT_EQ(buffer[i].minute, time.tm_min); + ASSERT_EQ(buffer[i].second, time.tm_sec); + } +} + +TEST(TEST_TIME64, TIME_WITH_NANO) { + auto value_field = field("f0", time64(TimeUnit::NANO)); + std::vector t64_values = {14896000000, 14897000000, 14892000000, + 85400000000, 14893000000, 14895000000}; + + std::shared_ptr time64_array; + ArrayFromVector(value_field->type(), + t64_values, &time64_array); + + TimeArrayFlightSqlAccessor accessor( + time64_array.get()); + + std::vector buffer(t64_values.size()); + ssize_t strlen_buffer[t64_values.size()]; + + ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer); + + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); + ASSERT_EQ(t64_values.size(), + accessor.GetColumnarData(&binding, 0, t64_values.size(), 0, diagnostics)); + + for (size_t i = 0; i < t64_values.size(); ++i) { + ASSERT_EQ(sizeof(TIME_STRUCT), strlen_buffer[i]); + + tm time{}; + + const auto convertedValue = t64_values[i] / NANO_TO_SECONDS_DIVISOR; + GetTimeForMillisSinceEpoch(time, convertedValue); + + ASSERT_EQ(buffer[i].hour, time.tm_hour); + ASSERT_EQ(buffer[i].minute, time.tm_min); + ASSERT_EQ(buffer[i].second, time.tm_sec); + } +} +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc new file mode 100644 index 0000000000000..d362f4e947b6f --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc @@ -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 "timestamp_array_accessor.h" +#include "odbcabstraction/calendar_utils.h" + +using namespace arrow; + +namespace { +long convertTimeStampBasedOnUnit(TimeUnit::type unit) { + long converted_result; + switch (unit) { + case TimeUnit::SECOND: + converted_result = 1; + break; + case TimeUnit::MILLI: + converted_result = driver::flight_sql::MILLI_TO_SECONDS_DIVISOR; + break; + case TimeUnit::MICRO: + converted_result = driver::flight_sql::MICRO_TO_SECONDS_DIVISOR; + break; + case TimeUnit::NANO: + converted_result = driver::flight_sql::NANO_TO_SECONDS_DIVISOR; + break; + } + return converted_result; +} +} // namespace + +namespace driver { +namespace flight_sql { + +using namespace odbcabstraction; + +template +TimestampArrayFlightSqlAccessor::TimestampArrayFlightSqlAccessor(Array *array) + : FlightSqlAccessor>(array), + timestamp_type_( + arrow::internal::checked_pointer_cast( + array->type())) {} + +template +void +TimestampArrayFlightSqlAccessor::MoveSingleCell_impl(ColumnBinding *binding, + TimestampArray *array, + int64_t cell_counter, + int64_t value_offset, + odbcabstraction::Diagnostics &diagnostics) { + typedef unsigned char c_type; + auto *buffer = static_cast(binding->buffer); + + long value = array->Value(cell_counter); + const auto divisor = convertTimeStampBasedOnUnit(timestamp_type_->unit()); + const auto converted_result = value / divisor; + tm timestamp{}; + + GetTimeForMillisSinceEpoch(timestamp, converted_result); + + buffer[cell_counter].year = 1900 + (timestamp.tm_year); + buffer[cell_counter].month = timestamp.tm_mon + 1; + buffer[cell_counter].day = timestamp.tm_mday; + buffer[cell_counter].hour = timestamp.tm_hour; + buffer[cell_counter].minute = timestamp.tm_min; + buffer[cell_counter].second = timestamp.tm_sec; + buffer[cell_counter].fraction = value % divisor; + + if (binding->strlen_buffer) { + binding->strlen_buffer[cell_counter] = static_cast(sizeof(TIMESTAMP_STRUCT)); + } +} + +template class TimestampArrayFlightSqlAccessor; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h new file mode 100644 index 0000000000000..3bf47db6e1cb2 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h @@ -0,0 +1,46 @@ +// 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. + +#pragma once + +#include "arrow/type_fwd.h" +#include "types.h" +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +template +class TimestampArrayFlightSqlAccessor + : public FlightSqlAccessor> { + +public: + explicit TimestampArrayFlightSqlAccessor(Array *array); + + void MoveSingleCell_impl(ColumnBinding *binding, TimestampArray *array, int64_t cell_counter, + int64_t value_offset, + odbcabstraction::Diagnostics &diagnostics); + +private: + std::shared_ptr timestamp_type_; +}; +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc new file mode 100644 index 0000000000000..7bbd56ab560f1 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc @@ -0,0 +1,181 @@ +// 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 "arrow/testing/builder.h" +#include "timestamp_array_accessor.h" +#include "utils.h" +#include "gtest/gtest.h" +#include "odbcabstraction/calendar_utils.h" + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MILI) { + std::vector values = {86400370, 172800000, 259200000, 1649793238110, + 345600000, 432000000, 518400000}; + + std::shared_ptr timestamp_array; + + auto timestamp_field = field("timestamp_field", timestamp(TimeUnit::MILLI)); + ArrayFromVector(timestamp_field->type(), + values, ×tamp_array); + + TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); + + std::vector buffer(values.size()); + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer); + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); + ASSERT_EQ(values.size(), + accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + + for (size_t i = 0; i < values.size(); ++i) { + ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); + + tm date{}; + + long converted_time = values[i] / MILLI_TO_SECONDS_DIVISOR; + GetTimeForMillisSinceEpoch(date, converted_time); + + ASSERT_EQ(buffer[i].year, 1900 + (date.tm_year)); + ASSERT_EQ(buffer[i].month, date.tm_mon + 1); + ASSERT_EQ(buffer[i].day, date.tm_mday); + ASSERT_EQ(buffer[i].hour, date.tm_hour); + ASSERT_EQ(buffer[i].minute, date.tm_min); + ASSERT_EQ(buffer[i].second, date.tm_sec); + ASSERT_EQ(buffer[i].fraction, values[i] % MILLI_TO_SECONDS_DIVISOR); + } +} + +TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_SECONDS) { + std::vector values = {86400, 172800, 259200, 1649793238, + 345600, 432000, 518400}; + + std::shared_ptr timestamp_array; + + auto timestamp_field = field("timestamp_field", timestamp(TimeUnit::SECOND)); + ArrayFromVector(timestamp_field->type(), + values, ×tamp_array); + + TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); + + std::vector buffer(values.size()); + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer); + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); + + ASSERT_EQ(values.size(), + accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + + for (size_t i = 0; i < values.size(); ++i) { + ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); + tm date{}; + + long converted_time = values[i]; + GetTimeForMillisSinceEpoch(date, converted_time); + + ASSERT_EQ(buffer[i].year, 1900 + (date.tm_year)); + ASSERT_EQ(buffer[i].month, date.tm_mon + 1); + ASSERT_EQ(buffer[i].day, date.tm_mday); + ASSERT_EQ(buffer[i].hour, date.tm_hour); + ASSERT_EQ(buffer[i].minute, date.tm_min); + ASSERT_EQ(buffer[i].second, date.tm_sec); + ASSERT_EQ(buffer[i].fraction, values[i] % 1); + } +} + +TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MICRO) { + std::vector values = {86400000000, 1649793238000000}; + + std::shared_ptr timestamp_array; + + auto timestamp_field = field("timestamp_field", timestamp(TimeUnit::MICRO)); + ArrayFromVector(timestamp_field->type(), + values, ×tamp_array); + + TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); + + std::vector buffer(values.size()); + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer); + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); + + ASSERT_EQ(values.size(), + accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + + for (size_t i = 0; i < values.size(); ++i) { + ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); + + tm date{}; + + long converted_time = values[i] / MICRO_TO_SECONDS_DIVISOR; + GetTimeForMillisSinceEpoch(date, converted_time); + + ASSERT_EQ(buffer[i].year, 1900 + (date.tm_year)); + ASSERT_EQ(buffer[i].month, date.tm_mon + 1); + ASSERT_EQ(buffer[i].day, date.tm_mday); + ASSERT_EQ(buffer[i].hour, date.tm_hour); + ASSERT_EQ(buffer[i].minute, date.tm_min); + ASSERT_EQ(buffer[i].second, date.tm_sec); + ASSERT_EQ(buffer[i].fraction, values[i] % MICRO_TO_SECONDS_DIVISOR); + } +} + +TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_NANO) { + std::vector values = {86400000010000, 1649793238000000000}; + + std::shared_ptr timestamp_array; + + auto timestamp_field = field("timestamp_field", timestamp(TimeUnit::NANO)); + ArrayFromVector(timestamp_field->type(), + values, ×tamp_array); + + TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); + + std::vector buffer(values.size()); + ssize_t strlen_buffer[values.size()]; + + ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer); + + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); + ASSERT_EQ(values.size(), + accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + + for (size_t i = 0; i < values.size(); ++i) { + ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); + tm date{}; + + long converted_time = values[i] / NANO_TO_SECONDS_DIVISOR; + GetTimeForMillisSinceEpoch(date, converted_time); + + ASSERT_EQ(buffer[i].year, 1900 + (date.tm_year)); + ASSERT_EQ(buffer[i].month, date.tm_mon + 1); + ASSERT_EQ(buffer[i].day, date.tm_mday); + ASSERT_EQ(buffer[i].hour, date.tm_hour); + ASSERT_EQ(buffer[i].minute, date.tm_min); + ASSERT_EQ(buffer[i].second, date.tm_sec); + ASSERT_EQ(buffer[i].fraction, values[i] % NANO_TO_SECONDS_DIVISOR); + } +} +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index ccfdab5f160f0..027483643c0e1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -100,8 +100,28 @@ const std::unordered_map(array); - }}}; - + }}, + {SourceAndTargetPair(arrow::Type::type::DATE32, CDataType_DATE), + [](arrow::Array *array) { + return new DateArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::DATE64, CDataType_DATE), + [](arrow::Array *array) { + return new DateArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::TIMESTAMP, CDataType_TIMESTAMP), + [](arrow::Array *array) { + return new TimestampArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::TIME32, CDataType_TIME), + [](arrow::Array *array) { + return new TimeArrayFlightSqlAccessor(array); + }}, + {SourceAndTargetPair(arrow::Type::type::TIME64, CDataType_TIME), + [](arrow::Array *array) { + return new TimeArrayFlightSqlAccessor(array); + }}, + }; } std::unique_ptr CreateAccessor(arrow::Array *source_array, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index 76941580b7ee1..c6301f81e4022 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -29,35 +29,59 @@ namespace flight_sql { namespace { std::shared_ptr -ConvertCToArrowDataType(odbcabstraction::CDataType data_type) { +ConvertCToArrowDataType(odbcabstraction::CDataType data_type, + const std::shared_ptr& original_array) { switch (data_type) { - case odbcabstraction::CDataType_CHAR: - case odbcabstraction::CDataType_WCHAR: - return arrow::utf8(); - case odbcabstraction::CDataType_SSHORT: - return arrow::int16(); - case odbcabstraction::CDataType_USHORT: - return arrow::uint16(); - case odbcabstraction::CDataType_SLONG: - return arrow::int32(); - case odbcabstraction::CDataType_ULONG: - return arrow::uint32(); - case odbcabstraction::CDataType_FLOAT: - return arrow::float32(); - case odbcabstraction::CDataType_DOUBLE: - return arrow::float64(); - case odbcabstraction::CDataType_BIT: - return arrow::boolean(); - case odbcabstraction::CDataType_STINYINT: - return arrow::int8(); - case odbcabstraction::CDataType_UTINYINT: - return arrow::uint8(); - case odbcabstraction::CDataType_SBIGINT: - return arrow::int64(); - case odbcabstraction::CDataType_UBIGINT: - return arrow::uint64(); - case odbcabstraction::CDataType_BINARY: - return arrow::binary(); + case odbcabstraction::CDataType_CHAR: + case odbcabstraction::CDataType_WCHAR: + return arrow::utf8(); + case odbcabstraction::CDataType_SSHORT: + return arrow::int16(); + case odbcabstraction::CDataType_USHORT: + return arrow::uint16(); + case odbcabstraction::CDataType_SLONG: + return arrow::int32(); + case odbcabstraction::CDataType_ULONG: + return arrow::uint32(); + case odbcabstraction::CDataType_FLOAT: + return arrow::float32(); + case odbcabstraction::CDataType_DOUBLE: + return arrow::float64(); + case odbcabstraction::CDataType_BIT: + return arrow::boolean(); + case odbcabstraction::CDataType_STINYINT: + return arrow::int8(); + case odbcabstraction::CDataType_UTINYINT: + return arrow::uint8(); + case odbcabstraction::CDataType_SBIGINT: + return arrow::int64(); + case odbcabstraction::CDataType_UBIGINT: + return arrow::uint64(); + case odbcabstraction::CDataType_BINARY: + return arrow::binary(); + case odbcabstraction::CDataType_TIMESTAMP: { + auto type_id = original_array->type_id(); + if (type_id == arrow::Type::TIMESTAMP) { + return original_array->type(); + } + // TODO Analyze how the conversion will be made + return arrow::timestamp(TimeUnit::SECOND); + } + case odbcabstraction::CDataType_TIME: { + auto type_id = original_array->type_id(); + if (type_id == arrow::Type::TIME32 || type_id == arrow::Type::TIME64) { + return original_array->type(); + } + //TODO Analyze how the conversion will be made + return arrow::time64(TimeUnit::NANO); + } + case odbcabstraction::CDataType_DATE: + auto type = original_array->type(); + if (type->Equals(date64()) || type->Equals(date32())) { + return type; + } + //TODO Analyze how the conversion will be made + return date64(); } throw odbcabstraction::DriverException(std::string("Invalid target type: ") + std::to_string(data_type)); @@ -77,8 +101,7 @@ CastArray(const std::shared_ptr &original_array, return result.ValueOrDie(); } - const std::shared_ptr &target_arrow_type = - ConvertCToArrowDataType(target_type); + const std::shared_ptr &target_arrow_type = ConvertCToArrowDataType(target_type, original_array); if (original_array->type()->Equals(target_arrow_type)) { // Avoid casting if target type is the same as original return original_array; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc new file mode 100644 index 0000000000000..db419cd0b0ee7 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc @@ -0,0 +1,31 @@ +// 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 + +namespace driver { +namespace flight_sql { +void GetTimeForMillisSinceEpoch(tm& date, int64_t value) { + #if defined(_WIN32) + gmtime_s(&date, &value); + #else + gmtime_r(&value, &date); + #endif + } +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h new file mode 100644 index 0000000000000..1d3650f5b77a7 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h @@ -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. + +#include +#include + +#pragma once + +namespace driver { +namespace flight_sql { + void GetTimeForMillisSinceEpoch(tm& date, int64_t value); +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 2d2a1f4bfe3e6..57b20ad63b116 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -127,6 +127,35 @@ enum Updatability { constexpr ssize_t NULL_DATA = -1; constexpr ssize_t NO_TOTAL = -4; constexpr ssize_t ALL_TYPES = 0; +constexpr ssize_t DAYS_TO_SECONDS_MULTIPLIER = 86400; +constexpr ssize_t MILLI_TO_SECONDS_DIVISOR = 1000; +constexpr ssize_t MICRO_TO_SECONDS_DIVISOR = 1000000; +constexpr ssize_t NANO_TO_SECONDS_DIVISOR = 1000000000; + +typedef struct tagDATE_STRUCT +{ + int16_t year; + u_int16_t month; + u_int16_t day; +} DATE_STRUCT; + +typedef struct tagTIME_STRUCT +{ + u_int16_t hour; + u_int16_t minute; + u_int16_t second; +} TIME_STRUCT; + +typedef struct tagTIMESTAMP_STRUCT +{ + int16_t year; + u_int16_t month; + u_int16_t day; + u_int16_t hour; + u_int16_t minute; + u_int16_t second; + u_int32_t fraction; +} TIMESTAMP_STRUCT; } // namespace odbcabstraction } // namespace driver From 5939c7adb52b147c90ac6933d48dd7f72bf12531 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Thu, 12 May 2022 15:12:54 -0300 Subject: [PATCH 093/183] Change calendar_utils.cc from flightsql-odbc cmake file to the odbcabstraction one Change-Id: I138ea1bff85014aaa01d329accaf7b7909b55ae8 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 1 - .../flightsql-odbc/odbcabstraction/CMakeLists.txt | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index bb1e66c3edc93..4cfb5174678dc 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -128,7 +128,6 @@ enable_testing() set(ARROW_ODBC_SPI_SOURCES accessors/binary_array_accessor.cc accessors/boolean_array_accessor.cc - accessors/calendar_utils.cc accessors/date_array_accessor.cc accessors/primitive_array_accessor.cc accessors/string_array_accessor.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index 0db46d01b8c5d..b56affab78d88 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -24,6 +24,7 @@ include_directories(include) add_library(odbcabstraction include/odbcabstraction/diagnostics.h include/odbcabstraction/error_codes.h + calendar_utils.cc diagnostics.cc exceptions.cc) From b2a8f0edec188507b5cf66feb315432b234cb896 Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 12 May 2022 14:41:32 -0700 Subject: [PATCH 094/183] Fix Mac build error with calendar code. Fix build error due to the assumption that time_t is always the same as int64_t. Also fix GetTimeMillisSinceEpoch being in the wrong namespace. Change-Id: Ic299e5fa72c8449c9ca5e4de45e34d60a45b4d57 --- .../flightsql-odbc/odbcabstraction/calendar_utils.cc | 7 ++++--- .../include/odbcabstraction/calendar_utils.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc index db419cd0b0ee7..61cfadf1f5974 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc @@ -19,13 +19,14 @@ #include namespace driver { -namespace flight_sql { +namespace odbcabstraction { void GetTimeForMillisSinceEpoch(tm& date, int64_t value) { #if defined(_WIN32) gmtime_s(&date, &value); #else - gmtime_r(&value, &date); + time_t time_value = static_cast(value); + gmtime_r(&time_value, &date); #endif } -} // namespace flight_sql +} // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h index 1d3650f5b77a7..caadf964866ea 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h @@ -21,7 +21,7 @@ #pragma once namespace driver { -namespace flight_sql { +namespace odbcabstraction { void GetTimeForMillisSinceEpoch(tm& date, int64_t value); } // namespace flight_sql } // namespace driver From 5aeab716833779f751571de6f2ea78a04ab5f1e8 Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 12 May 2022 15:06:40 -0700 Subject: [PATCH 095/183] Fix use of variable-length arrays in tests Change variable length arrays to vectors to avoid Windows portability problems. Change-Id: I511dce07718c4dbfe9c7cafc24f6c895ef336113 --- .../accessors/date_array_accessor_test.cc | 8 ++++---- .../accessors/time_array_accessor_test.cc | 16 ++++++++-------- .../accessors/timestamp_array_accessor_test.cc | 16 ++++++++-------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc index 0f906b3da1b30..9f151f0aea703 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc @@ -37,9 +37,9 @@ TEST(DateArrayAccessor, Test_Date32Array_CDataType_DATE) { dynamic_cast *>(array.get())); std::vector buffer(values.size()); - ssize_t strlen_buffer[values.size()]; + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_DATE, 0, 0, buffer.data(), 0, strlen_buffer); + ColumnBinding binding(CDataType_DATE, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), @@ -68,9 +68,9 @@ TEST(DateArrayAccessor, Test_Date64Array_CDataType_DATE) { dynamic_cast *>(array.get())); std::vector buffer(values.size()); - ssize_t strlen_buffer[values.size()]; + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_DATE, 0, 0, buffer.data(), 0, strlen_buffer); + ColumnBinding binding(CDataType_DATE, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc index 792a1b639e28b..5f8705d1fc0d6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc @@ -39,9 +39,9 @@ TEST(TEST_TIME32, TIME_WITH_SECONDS) { TimeArrayFlightSqlAccessor accessor(time32_array.get()); std::vector buffer(t32_values.size()); - ssize_t strlen_buffer[t32_values.size()]; + std::vector strlen_buffer(t32_values.size()); - ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer); + ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(t32_values.size(), @@ -71,9 +71,9 @@ TEST(TEST_TIME32, TIME_WITH_MILLI) { TimeArrayFlightSqlAccessor accessor(time32_array.get()); std::vector buffer(t32_values.size()); - ssize_t strlen_buffer[t32_values.size()]; + std::vector strlen_buffer(t32_values.size()); - ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer); + ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(t32_values.size(), @@ -106,9 +106,9 @@ TEST(TEST_TIME64, TIME_WITH_MICRO) { TimeArrayFlightSqlAccessor accessor(time64_array.get()); std::vector buffer(t64_values.size()); - ssize_t strlen_buffer[t64_values.size()]; + std::vector strlen_buffer(t64_values.size()); - ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer); + ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(t64_values.size(), @@ -141,9 +141,9 @@ TEST(TEST_TIME64, TIME_WITH_NANO) { time64_array.get()); std::vector buffer(t64_values.size()); - ssize_t strlen_buffer[t64_values.size()]; + std::vector strlen_buffer(t64_values.size()); - ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer); + ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(t64_values.size(), diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc index 7bbd56ab560f1..b02c6c060cad9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc @@ -40,9 +40,9 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MILI) { TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); std::vector buffer(values.size()); - ssize_t strlen_buffer[values.size()]; + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer); + ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); @@ -78,9 +78,9 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_SECONDS) { TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); std::vector buffer(values.size()); - ssize_t strlen_buffer[values.size()]; + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer); + ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), @@ -115,9 +115,9 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MICRO) { TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); std::vector buffer(values.size()); - ssize_t strlen_buffer[values.size()]; + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer); + ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), @@ -153,9 +153,9 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_NANO) { TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); std::vector buffer(values.size()); - ssize_t strlen_buffer[values.size()]; + std::vector strlen_buffer(values.size()); - ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer); + ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), From dc07014b07b4ec9d2352e3bc90a7f53f57bc5ab5 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Mon, 9 May 2022 14:21:37 -0300 Subject: [PATCH 096/183] Decimal array accessor Change-Id: I1c7738b77a269b8d6c9a423c00bd0200272e7d8e --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 2 + .../accessors/decimal_array_accessor.cc | 88 +++++++++++++ .../accessors/decimal_array_accessor.h | 48 +++++++ .../accessors/decimal_array_accessor_test.cc | 106 ++++++++++++++++ .../flight_sql/accessors/main.h | 1 + .../flight_sql_result_set_accessors.cc | 5 +- .../flight_sql_result_set_column.cc | 120 ++++++++++-------- .../flight_sql/json_converter.cc | 10 +- .../flightsql-odbc/flight_sql/main.cc | 38 +++--- .../flightsql-odbc/flight_sql/utils.cc | 1 - .../include/odbcabstraction/types.h | 8 ++ 11 files changed, 350 insertions(+), 77 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 4cfb5174678dc..a053ebbbd99cb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -129,6 +129,7 @@ set(ARROW_ODBC_SPI_SOURCES accessors/binary_array_accessor.cc accessors/boolean_array_accessor.cc accessors/date_array_accessor.cc + accessors/decimal_array_accessor.cc accessors/primitive_array_accessor.cc accessors/string_array_accessor.cc accessors/time_array_accessor.cc @@ -211,6 +212,7 @@ set(ARROW_ODBC_SPI_TEST_SOURCES 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 diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc new file mode 100644 index 0000000000000..4148b995d643b --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc @@ -0,0 +1,88 @@ +// 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 "decimal_array_accessor.h" + +#include +#include + +namespace { +void Negate(uint8_t* values) { + uint8_t carry = 1; + for (size_t i = 0; i < 16; ++i) { + uint8_t& elem = values[i]; + elem = ~elem + carry; + carry &= (elem == 0); + } +} +} // namespace + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +template +DecimalArrayFlightSqlAccessor::DecimalArrayFlightSqlAccessor( + Array *array) + : FlightSqlAccessor>(array) { + data_type_ = std::static_pointer_cast(array->type()); +} + +template <> +void DecimalArrayFlightSqlAccessor::MoveSingleCell_impl( + ColumnBinding *binding, Decimal128Array *array, int64_t i, + int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { + auto result = &(static_cast(binding->buffer)[i]); + int32_t original_scale = data_type_->scale(); + + std::shared_ptr scalar; + ThrowIfNotOK(array->GetScalar(i).Value(&scalar)); + const auto &decimal_scalar = internal::checked_pointer_cast(scalar); + Decimal128 value = decimal_scalar->value; + if (original_scale != binding->scale) { + const Status &status = value.Rescale(original_scale, binding->scale).Value(&value); + ThrowIfNotOK(status); + } + if (!value.FitsInPrecision(binding->precision)) { + throw DriverException("Decimal value doesn't fit in precision " + std::to_string(binding->precision)); + } + + uint8_t bytes[16]; + value.ToBytes(bytes); + memcpy(&result->val, bytes, 16); + result->precision = static_cast(binding->precision); + result->scale = static_cast(binding->scale); + + // If the most significant bit is set this number is negative (sign = 0). + result->sign = (static_cast(result->val[15]) >> 7) == 0; + result->precision = data_type_->precision(); + if (result->sign == 0) { + Negate(result->val); + } + + if (binding->strlen_buffer) { + binding->strlen_buffer[i] = static_cast(sizeof(NUMERIC_STRUCT)); + } +} + +template class DecimalArrayFlightSqlAccessor; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h new file mode 100644 index 0000000000000..633160ceb0fbc --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h @@ -0,0 +1,48 @@ +// 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. + +#pragma once + +#include "arrow/type_fwd.h" +#include "types.h" +#include "utils.h" +#include +#include + +namespace driver { +namespace flight_sql { + +using namespace arrow; +using namespace odbcabstraction; + +template +class DecimalArrayFlightSqlAccessor + : public FlightSqlAccessor> { +public: + explicit DecimalArrayFlightSqlAccessor(Array *array); + + void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, + int64_t i, int64_t value_offset, + odbcabstraction::Diagnostics &diagnostics); + +private: + std::shared_ptr data_type_; +}; + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc new file mode 100644 index 0000000000000..46db7566b33ce --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc @@ -0,0 +1,106 @@ +// 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 "arrow/util/decimal.h" +#include "arrow/builder.h" +#include "arrow/testing/builder.h" +#include "decimal_array_accessor.h" +#include "gtest/gtest.h" + +namespace { + +using namespace arrow; +using namespace driver::odbcabstraction; +using driver::flight_sql::ThrowIfNotOK; + +std::vector MakeDecimalVector(const std::vector &values, + int32_t scale) { + std::vector ret; + for (const auto &str: values) { + Decimal128 str_value; + int32_t str_precision; + int32_t str_scale; + + ThrowIfNotOK(Decimal128::FromString(str, &str_value, &str_precision, &str_scale)); + + Decimal128 scaled_value; + if (str_scale == scale) { + scaled_value = str_value; + } else { + scaled_value = str_value.Rescale(str_scale, scale).ValueOrDie(); + } + ret.push_back(scaled_value); + } + return ret; +} + +std::string ConvertNumericToString(NUMERIC_STRUCT &numeric) { + auto v = reinterpret_cast(numeric.val); + auto decimal = Decimal128(v[1], v[0]); + const std::string &string = decimal.ToString(numeric.scale); + + return (numeric.sign ? "" : "-") + string; +} +} + +namespace driver { +namespace flight_sql { + +void AssertNumericOutput(int input_precision, int input_scale, const std::vector &values_str, + int output_precision, int output_scale, const std::vector &expected_values_str) { + auto decimal_type = std::make_shared(input_precision, input_scale); + const std::vector &values = MakeDecimalVector(values_str, decimal_type->scale()); + + std::shared_ptr array; + ArrayFromVector(decimal_type, values, &array); + + DecimalArrayFlightSqlAccessor accessor(array.get()); + + std::vector buffer(values.size()); + std::vector strlen_buffer(values.size()); + + ColumnBinding binding(CDataType_NUMERIC, output_precision, output_scale, buffer.data(), 0, strlen_buffer.data()); + + odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); + ASSERT_EQ(values.size(), + accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + + for (int i = 0; i < values.size(); ++i) { + ASSERT_EQ(sizeof(NUMERIC_STRUCT), strlen_buffer[i]); + + ASSERT_EQ(output_precision, buffer[i].precision); + ASSERT_EQ(output_scale, buffer[i].scale); + ASSERT_STREQ(expected_values_str[i].c_str(), ConvertNumericToString(buffer[i]).c_str()); + } +} + +TEST(DecimalArrayFlightSqlAccessor, Test_Decimal128Array_CDataType_NUMERIC_SameScale) { + const std::vector &input_values = {"25.212", "-25.212", "-123456789.123", "123456789.123"}; + const std::vector &output_values = input_values; // String values should be the same + + AssertNumericOutput(38, 3, input_values, 38, 3, output_values); +} + +TEST(DecimalArrayFlightSqlAccessor, Test_Decimal128Array_CDataType_NUMERIC_IncreasingScale) { + const std::vector &input_values = {"25.212", "-25.212", "-123456789.123", "123456789.123"}; + const std::vector &output_values = {"25.2120", "-25.2120", "-123456789.1230", "123456789.1230"}; + + AssertNumericOutput(38, 3, input_values, 38, 4, output_values); +} + +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h index 231c79e61b1c9..14a49033278b3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h @@ -22,5 +22,6 @@ #include "date_array_accessor.h" #include "time_array_accessor.h" #include "timestamp_array_accessor.h" +#include "decimal_array_accessor.h" #include "primitive_array_accessor.h" #include "string_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index 027483643c0e1..e7a9ed71c5f83 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -121,7 +121,10 @@ const std::unordered_map(array); }}, - }; + {SourceAndTargetPair(arrow::Type::type::DECIMAL128, CDataType_NUMERIC), + [](arrow::Array *array) { + return new DecimalArrayFlightSqlAccessor(array); + }}}; } std::unique_ptr CreateAccessor(arrow::Array *source_array, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index c6301f81e4022..453a135502cd2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -29,59 +29,71 @@ namespace flight_sql { namespace { std::shared_ptr -ConvertCToArrowDataType(odbcabstraction::CDataType data_type, - const std::shared_ptr& original_array) { +GetDefaultDataTypeForTypeId(arrow::Type::type type_id) { + switch (type_id) { + case arrow::Type::STRING: + return arrow::utf8(); + case arrow::Type::INT16: + return arrow::int16(); + case arrow::Type::UINT16: + return arrow::uint16(); + case arrow::Type::INT32: + return arrow::int32(); + case arrow::Type::UINT32: + return arrow::uint32(); + case arrow::Type::FLOAT: + return arrow::float32(); + case arrow::Type::DOUBLE: + return arrow::float64(); + case arrow::Type::BOOL: + return arrow::boolean(); + case arrow::Type::INT8: + return arrow::int8(); + case arrow::Type::UINT8: + return arrow::uint8(); + case arrow::Type::INT64: + return arrow::int64(); + case arrow::Type::UINT64: + return arrow::uint64(); + case arrow::Type::BINARY: + return arrow::binary(); + } + + throw odbcabstraction::DriverException(std::string("Invalid type id: ") + std::to_string(type_id)); +} + +arrow::Type::type +ConvertCToArrowType(odbcabstraction::CDataType data_type) { switch (data_type) { case odbcabstraction::CDataType_CHAR: case odbcabstraction::CDataType_WCHAR: - return arrow::utf8(); + return arrow::Type::STRING; case odbcabstraction::CDataType_SSHORT: - return arrow::int16(); + return arrow::Type::INT16; case odbcabstraction::CDataType_USHORT: - return arrow::uint16(); + return arrow::Type::UINT16; case odbcabstraction::CDataType_SLONG: - return arrow::int32(); + return arrow::Type::INT32; case odbcabstraction::CDataType_ULONG: - return arrow::uint32(); + return arrow::Type::UINT32; case odbcabstraction::CDataType_FLOAT: - return arrow::float32(); + return arrow::Type::FLOAT; case odbcabstraction::CDataType_DOUBLE: - return arrow::float64(); + return arrow::Type::DOUBLE; case odbcabstraction::CDataType_BIT: - return arrow::boolean(); + return arrow::Type::BOOL; case odbcabstraction::CDataType_STINYINT: - return arrow::int8(); + return arrow::Type::INT8; case odbcabstraction::CDataType_UTINYINT: - return arrow::uint8(); + return arrow::Type::UINT8; case odbcabstraction::CDataType_SBIGINT: - return arrow::int64(); + return arrow::Type::INT64; case odbcabstraction::CDataType_UBIGINT: - return arrow::uint64(); + return arrow::Type::UINT64; case odbcabstraction::CDataType_BINARY: - return arrow::binary(); - case odbcabstraction::CDataType_TIMESTAMP: { - auto type_id = original_array->type_id(); - if (type_id == arrow::Type::TIMESTAMP) { - return original_array->type(); - } - // TODO Analyze how the conversion will be made - return arrow::timestamp(TimeUnit::SECOND); - } - case odbcabstraction::CDataType_TIME: { - auto type_id = original_array->type_id(); - if (type_id == arrow::Type::TIME32 || type_id == arrow::Type::TIME64) { - return original_array->type(); - } - //TODO Analyze how the conversion will be made - return arrow::time64(TimeUnit::NANO); - } - case odbcabstraction::CDataType_DATE: - auto type = original_array->type(); - if (type->Equals(date64()) || type->Equals(date32())) { - return type; - } - //TODO Analyze how the conversion will be made - return date64(); + return arrow::Type::BINARY; + case odbcabstraction::CDataType_NUMERIC: + return arrow::Type::DECIMAL128; } throw odbcabstraction::DriverException(std::string("Invalid target type: ") + std::to_string(data_type)); @@ -90,31 +102,29 @@ ConvertCToArrowDataType(odbcabstraction::CDataType data_type, std::shared_ptr CastArray(const std::shared_ptr &original_array, CDataType target_type) { - Type::type type = original_array->type_id(); - auto is_complex = type == Type::LIST || type == Type::FIXED_SIZE_LIST || type == Type::LARGE_LIST - || type == Type::MAP || type == Type::STRUCT; - if (is_complex && - (target_type == odbcabstraction::CDataType_CHAR || target_type == odbcabstraction::CDataType_WCHAR)) { - const auto &result = ConvertToJson(original_array); - ThrowIfNotOK(result.status()); - - return result.ValueOrDie(); - } - - const std::shared_ptr &target_arrow_type = ConvertCToArrowDataType(target_type, original_array); - if (original_array->type()->Equals(target_arrow_type)) { + const arrow::Type::type &target_arrow_type_id = ConvertCToArrowType(target_type); + if (original_array->type()->id() == target_arrow_type_id) { // Avoid casting if target type is the same as original return original_array; } arrow::compute::CastOptions cast_options; - cast_options.to_type = target_arrow_type; + cast_options.to_type = GetDefaultDataTypeForTypeId(target_arrow_type_id); const arrow::Result &result = arrow::compute::CallFunction("cast", {original_array}, &cast_options); - ThrowIfNotOK(result.status()); - arrow::Datum datum = result.ValueOrDie(); - return std::move(datum).make_array(); + if (result.ok()) { + arrow::Datum datum = result.ValueOrDie(); + return std::move(datum).make_array(); + } else if (target_type == odbcabstraction::CDataType_CHAR || target_type == odbcabstraction::CDataType_WCHAR) { + // Fallback to JSON conversion if target type is CHAR/WCHAR + const auto &json_conversion_result = ConvertToJson(original_array); + ThrowIfNotOK(json_conversion_result.status()); + + return json_conversion_result.ValueOrDie(); + } else { + throw odbcabstraction::DriverException(result.status().message()); + } } } // namespace diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc index 71381ad9129ec..dd2b0bd81e4b0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc @@ -213,11 +213,17 @@ class ScalarToJson : public arrow::ScalarVisitor { } Status Visit(const Decimal128Scalar &scalar) override { - return Status::NotImplemented("Cannot convert Decimal128Scalar to JSON."); + const auto &view = scalar.ToString(); + writer_.RawValue(view.data(), view.length(), rapidjson::kNumberType); + + return Status::OK(); } Status Visit(const Decimal256Scalar &scalar) override { - return Status::NotImplemented("Cannot convert Decimal256Scalar to JSON."); + const auto &view = scalar.ToString(); + writer_.RawValue(view.data(), view.length(), rapidjson::kNumberType); + + return Status::OK(); } Status Visit(const ListScalar &scalar) override { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index f6ee52d405ee8..d2f387c877140 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -82,17 +82,22 @@ void TestBindColumn(const std::shared_ptr &connection) { void TestGetData(const std::shared_ptr &connection) { const std::shared_ptr &statement = connection->CreateStatement(); statement->Execute( - "SELECT IncidntNum, Category FROM \"@dremio\".Test LIMIT 10"); + "SELECT * FROM \"@dremio\".\"test_numeric\""); const std::shared_ptr &result_set = statement->GetResultSet(); + const std::shared_ptr &metadata = result_set->GetMetadata(); + + std::cout << metadata->GetDataType(1) << std::endl; while (result_set->Move(1) == 1) { - const int buffer_length = 1024; - char result[buffer_length]; + driver::odbcabstraction::NUMERIC_STRUCT result[0]; ssize_t result_length; - result_set->GetData(1, driver::odbcabstraction::CDataType_CHAR, 0, 0, - result, buffer_length, &result_length); - std::cout << result << std::endl; + result_set->GetData(1, driver::odbcabstraction::CDataType_NUMERIC, 0, 0, + result, 0, &result_length); + std::cout << "precision:" << result[0].precision << std::endl; + std::cout << "scale:" << result[0].scale << std::endl; + std::cout << "sign:" << result[0].sign << std::endl; + std::cout << "val:" << result[0].val << std::endl; } } @@ -172,9 +177,10 @@ void TestGetTablesV2(const std::shared_ptr &connection) { void TestGetColumnsV3(const std::shared_ptr &connection) { const std::shared_ptr &statement = connection->CreateStatement(); + std::string table_name = "test_numeric"; std::string column_name = "%"; const std::shared_ptr &result_set = - statement->GetColumns_V3(nullptr, nullptr, nullptr, &column_name); + statement->GetColumns_V3(nullptr, nullptr, &table_name, &column_name); const std::shared_ptr &metadata = result_set->GetMetadata(); @@ -210,17 +216,13 @@ int main() { {FlightSqlConnection::PASSWORD, std::string("dremio123")}, }; std::vector missing_attr; - try { - connection->Connect(properties, missing_attr); - - // TestBindColumnBigInt(connection); - // TestBindColumn(connection); - // TestGetData(connection); - // TestGetTablesV2(connection); - TestGetColumnsV3(connection); - } catch (...) { - std::cout << "error occured" << std::endl; - } + connection->Connect(properties, missing_attr); + + // TestBindColumnBigInt(connection); +// TestBindColumn(connection); + TestGetData(connection); + // TestGetTablesV2(connection); +// TestGetColumnsV3(connection); connection->Close(); return 0; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 6a7e719f17110..8d76c25320118 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -64,7 +64,6 @@ GetDataTypeFromArrowField_V3(const std::shared_ptr &field) { case arrow::Type::TIMESTAMP: return odbcabstraction::SqlDataType_TYPE_TIMESTAMP; case arrow::Type::DECIMAL128: - case arrow::Type::DECIMAL256: return odbcabstraction::SqlDataType_DECIMAL; case arrow::Type::TIME32: case arrow::Type::TIME64: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 57b20ad63b116..82a46d68cd679 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -103,6 +103,7 @@ enum CDataType { CDataType_SBIGINT = ((-5) + (-20)), CDataType_UBIGINT = ((-5) + (-22)), CDataType_BINARY = (-2), + CDataType_NUMERIC = 2, }; enum Nullability { @@ -157,5 +158,12 @@ typedef struct tagTIMESTAMP_STRUCT u_int32_t fraction; } TIMESTAMP_STRUCT; +typedef struct tagNUMERIC_STRUCT { + uint8_t precision; + int8_t scale; + uint8_t sign; // The sign field is 1 if positive, 0 if negative. + uint8_t val[16]; //[e], [f] +} NUMERIC_STRUCT; + } // namespace odbcabstraction } // namespace driver From 98294ba86da9fbe14ad02f2b35118499870ca007 Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 12 May 2022 15:40:58 -0700 Subject: [PATCH 097/183] Correctly report when catalogs are unsupported Change flightsql-odbc to set SQL_CATALOG_NAME = "N" in SQLGetInfo when the Arrow SQL_CATALOG_TERM is set to an empty string or is missing. Change-Id: I392ea9aed52179311a24d5fe27eb4c7574db15a4 --- .../flightsql-odbc/flight_sql/get_info_cache.cc | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc index b724d140cdf4a..b188723d27af9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc @@ -244,6 +244,12 @@ GetInfoCache::GetInfoCache(FlightCallOptions &call_options, info_[SQL_AGGREGATE_FUNCTIONS] = static_cast( SQL_AF_ALL | SQL_AF_AVG | SQL_AF_COUNT | SQL_AF_DISTINCT | SQL_AF_MAX | SQL_AF_MIN | SQL_AF_SUM); + + // Assume catalogs are not supported by default. ODBC checks if SQL_CATALOG_NAME is + // "Y" or "N" to determine if catalogs are supported. + info_[SQL_CATALOG_TERM] = ""; + info_[SQL_CATALOG_NAME] = "N"; + info_[SQL_CATALOG_NAME_SEPARATOR] = ""; } void GetInfoCache::SetProperty( @@ -345,11 +351,16 @@ bool GetInfoCache::LoadInfoFromServer() { break; } case ARROW_SQL_CATALOG_TERM: { + std::string catalog_term(std::string(reinterpret_cast(scalar->value.get())->view())); + if (catalog_term.empty()) { + info_[SQL_CATALOG_NAME] = "N"; + info_[SQL_CATALOG_NAME_SEPARATOR] = ""; + } else { + info_[SQL_CATALOG_NAME] = "Y"; + info_[SQL_CATALOG_NAME_SEPARATOR] = "."; + } info_[SQL_CATALOG_TERM] = std::string(reinterpret_cast(scalar->value.get())->view()); - // This property implies catalogs are supported. - info_[SQL_CATALOG_NAME] = "Y"; - info_[SQL_CATALOG_NAME_SEPARATOR] = "."; break; } From be8564055d341f8ca7f2f187fd438c7dd74ecf16 Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 13 May 2022 13:48:59 -0700 Subject: [PATCH 098/183] Fix Windows build errors in datetime structs Use portable uint_*t types instead non-portable u_int_*t types Change-Id: I476c3974e85283973ff5695dd6442e107fef94ee --- .../include/odbcabstraction/types.h | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 82a46d68cd679..397b7fc6a3012 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -136,26 +136,26 @@ constexpr ssize_t NANO_TO_SECONDS_DIVISOR = 1000000000; typedef struct tagDATE_STRUCT { int16_t year; - u_int16_t month; - u_int16_t day; + uint16_t month; + uint16_t day; } DATE_STRUCT; typedef struct tagTIME_STRUCT { - u_int16_t hour; - u_int16_t minute; - u_int16_t second; + uint16_t hour; + uint16_t minute; + uint16_t second; } TIME_STRUCT; typedef struct tagTIMESTAMP_STRUCT { int16_t year; - u_int16_t month; - u_int16_t day; - u_int16_t hour; - u_int16_t minute; - u_int16_t second; - u_int32_t fraction; + uint16_t month; + uint16_t day; + uint16_t hour; + uint16_t minute; + uint16_t second; + uint32_t fraction; } TIMESTAMP_STRUCT; typedef struct tagNUMERIC_STRUCT { From 1fd712e386ba8d26f356877c27fb554467db0692 Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 13 May 2022 14:18:23 -0700 Subject: [PATCH 099/183] Fix portability in numeric retrieval in CLI app Fix Windows compilation issue due to trying to allocate and use a zero-length array. Change-Id: I7d30fb240f0c6d0188414fc0ff901247fe34911e --- .../flightsql-odbc/flight_sql/main.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index d2f387c877140..5a0ff8e095a3f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -17,6 +17,7 @@ #include #include +#include #include "flight_sql_connection.h" #include "flight_sql_result_set.h" @@ -90,14 +91,14 @@ void TestGetData(const std::shared_ptr &connection) { std::cout << metadata->GetDataType(1) << std::endl; while (result_set->Move(1) == 1) { - driver::odbcabstraction::NUMERIC_STRUCT result[0]; + driver::odbcabstraction::NUMERIC_STRUCT result; ssize_t result_length; result_set->GetData(1, driver::odbcabstraction::CDataType_NUMERIC, 0, 0, - result, 0, &result_length); - std::cout << "precision:" << result[0].precision << std::endl; - std::cout << "scale:" << result[0].scale << std::endl; - std::cout << "sign:" << result[0].sign << std::endl; - std::cout << "val:" << result[0].val << std::endl; + &result, 0, &result_length); + std::cout << "precision:" << result.precision << std::endl; + std::cout << "scale:" << result.scale << std::endl; + std::cout << "sign:" << result.sign << std::endl; + std::cout << "val:" << result.val << std::endl; } } From 2865b9007e465b3ec877d9241226226e5d9f17aa Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 16 May 2022 10:49:00 -0700 Subject: [PATCH 100/183] Fix reported type for IS_NULLABLE in SQLColumns Report the IS_NULLABLE column as a VARCHAR instead of an INTEGER per the spec. The data coming back is also VARCHAR. This is needed for loading data into Power BI. Change-Id: I119a29752d4ee67d79566b65c2f105668c9b6cb3 --- .../flight_sql/flight_sql_statement_get_columns.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc index 21780366fd037..85bb9ee324443 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc @@ -49,7 +49,7 @@ std::shared_ptr GetColumns_V3_Schema() { field("SQL_DATETIME_SUB", int16()), field("CHAR_OCTET_LENGTH", int32()), field("ORDINAL_POSITION", int32()), - field("IS_NULLABLE", int32()), + field("IS_NULLABLE", utf8()), }); } @@ -72,7 +72,7 @@ std::shared_ptr GetColumns_V2_Schema() { field("SQL_DATETIME_SUB", int16()), field("CHAR_OCTET_LENGTH", int32()), field("ORDINAL_POSITION", int32()), - field("IS_NULLABLE", int32()), + field("IS_NULLABLE", utf8()), }); } From e68cb7fb41cb0db4357290947dfd77fa5f02c114 Mon Sep 17 00:00:00 2001 From: James Duong Date: Wed, 18 May 2022 16:21:04 -0700 Subject: [PATCH 101/183] Send unknown connection string properties as headers Send unrecognized connection string properties to the FlightProducer as headers with each request. Needed to make the Schema, Quoting, Routing_Queue, and Routing_Tag options work. Change-Id: I6bfd53a2026169e9099b6296a0926147986ea840 --- .../flight_sql/flight_sql_connection.cc | 27 +++++++++++++++++-- .../flight_sql/flight_sql_connection.h | 2 +- .../flight_sql/flight_sql_connection_test.cc | 4 +-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 91577964e2c73..b69eee4369182 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -57,7 +58,19 @@ const std::string FlightSqlConnection::PWD = "pwd"; const std::string FlightSqlConnection::TOKEN = "token"; const std::string FlightSqlConnection::USE_TLS = "useTls"; + namespace { +const std::set BUILT_IN_PROPERTIES = { + FlightSqlConnection::HOST, + FlightSqlConnection::PORT, + FlightSqlConnection::USER, + FlightSqlConnection::UID, + FlightSqlConnection::PASSWORD, + FlightSqlConnection::PWD, + FlightSqlConnection::TOKEN, + FlightSqlConnection::USE_TLS +}; + // TODO: Add properties for getting the certificates // TODO: Check if gRPC can use the system truststore, if not copy from Drill @@ -102,7 +115,7 @@ void FlightSqlConnection::Connect(const ConnPropertyMap &properties, info_.SetProperty(SQL_USER_NAME, auth_method->GetUser()); attribute_[CONNECTION_DEAD] = static_cast(SQL_FALSE); - PopulateCallOptionsFromAttributes(); + PopulateCallOptions(properties); } catch (...) { attribute_[CONNECTION_DEAD] = static_cast(SQL_TRUE); sql_client_.reset(); @@ -112,7 +125,7 @@ void FlightSqlConnection::Connect(const ConnPropertyMap &properties, } const FlightCallOptions & -FlightSqlConnection::PopulateCallOptionsFromAttributes() { +FlightSqlConnection::PopulateCallOptions(const ConnPropertyMap &props) { // Set CONNECTION_TIMEOUT attribute or LOGIN_TIMEOUT depending on if this // is the first request. const boost::optional &connection_timeout = closed_ ? @@ -122,6 +135,16 @@ FlightSqlConnection::PopulateCallOptionsFromAttributes() { TimeoutDuration{static_cast(boost::get(*connection_timeout))}; } + for (auto prop : props) { + if (BUILT_IN_PROPERTIES.count(prop.first) != 0) { + continue; + } + + // Note: header names must be lower case for gRPC. + std::string key_lc = boost::algorithm::to_lower_copy(prop.first); + call_options_.headers.emplace_back(std::make_pair(key_lc, prop.second)); + } + return call_options_; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index e0d806ff00a9c..dbb907e7e4d9d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -78,7 +78,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { /// \brief Builds a FlightCallOptions used on gRPC calls. /// \note Visible for testing - const arrow::flight::FlightCallOptions &PopulateCallOptionsFromAttributes(); + const arrow::flight::FlightCallOptions &PopulateCallOptions(const ConnPropertyMap &properties); odbcabstraction::Diagnostics &GetDiagnostics() override; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 95ef89810134b..23be9428c0b40 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -113,11 +113,11 @@ TEST(PopulateCallOptionsTest, ConnectionTimeout) { // Expect default timeout to be -1 ASSERT_EQ(TimeoutDuration{-1.0}, - connection.PopulateCallOptionsFromAttributes().timeout); + connection.PopulateCallOptions(Connection::ConnPropertyMap()).timeout); connection.SetAttribute(Connection::CONNECTION_TIMEOUT, static_cast(10)); ASSERT_EQ(TimeoutDuration{10.0}, - connection.PopulateCallOptionsFromAttributes().timeout); + connection.PopulateCallOptions(Connection::ConnPropertyMap()).timeout); } } // namespace flight_sql From 5293ae59a454ae4f92a5b12c31e4223f951ba65b Mon Sep 17 00:00:00 2001 From: jayho Date: Thu, 19 May 2022 18:14:05 -0700 Subject: [PATCH 102/183] DX-50501: Run unit tests as part of post build step for flightsql-odbc - Added post build step to run unit tests - Skipped 4 unit tests for failures Change-Id: Icc621179d80f13c685f835ffa232b3775e9ec71a --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 7 +++++++ .../flight_sql/accessors/string_array_accessor_test.cc | 1 + .../flight_sql/flight_sql_connection_test.cc | 3 +++ 3 files changed, 11 insertions(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index a053ebbbd99cb..7f2568ddc2605 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -237,3 +237,10 @@ target_link_libraries(arrow_odbc_spi_impl_test 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/$/bin/arrow_odbc_spi_impl_test +) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc index a25f3c7bcc215..e79b110dc3bf0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc @@ -111,6 +111,7 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Basic) { } TEST(StringArrayAccessor, Test_CDataType_WCHAR_Truncation) { + GTEST_SKIP(); std::vector values = { "ABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEF"}; std::shared_ptr array; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 23be9428c0b40..ab20ef924f1c7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -30,6 +30,7 @@ using arrow::flight::TimeoutDuration; using odbcabstraction::Connection; TEST(AttributeTests, SetAndGetAttribute) { + GTEST_SKIP(); FlightSqlConnection connection(odbcabstraction::V_3); connection.SetAttribute(Connection::CONNECTION_TIMEOUT, static_cast(200)); @@ -52,6 +53,7 @@ TEST(AttributeTests, SetAndGetAttribute) { } TEST(AttributeTests, GetAttributeWithoutSetting) { + GTEST_SKIP(); FlightSqlConnection connection(odbcabstraction::V_3); const boost::optional anOptional = @@ -109,6 +111,7 @@ TEST(BuildLocationTests, ForTls) { } TEST(PopulateCallOptionsTest, ConnectionTimeout) { + GTEST_SKIP(); FlightSqlConnection connection(odbcabstraction::V_3); // Expect default timeout to be -1 From 1ffc56f96178a7df1dd00fb1eb37f26ef39250d7 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Tue, 24 May 2022 19:27:02 -0300 Subject: [PATCH 103/183] Fix failing tests in the flightsql-odbc layer Change-Id: Idd6e7b0441b15cf8c4dd027ef5f459ccfab746c8 --- .../flight_sql/accessors/date_array_accessor.cc | 8 ++++---- .../flight_sql/accessors/date_array_accessor_test.cc | 4 ++-- .../flight_sql/accessors/string_array_accessor_test.cc | 3 +-- .../flight_sql/accessors/time_array_accessor.cc | 6 +++--- .../flight_sql/accessors/time_array_accessor_test.cc | 2 +- .../flight_sql/accessors/timestamp_array_accessor.cc | 6 +++--- .../accessors/timestamp_array_accessor_test.cc | 10 +++++----- .../flightsql-odbc/flight_sql/flight_sql_connection.cc | 4 ++++ .../flightsql-odbc/flight_sql/flight_sql_connection.h | 4 ++++ .../flight_sql/flight_sql_connection_test.cc | 10 +++++----- 10 files changed, 32 insertions(+), 25 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc index 0a431dad03c91..05ff92ae51aab 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc @@ -24,21 +24,21 @@ using namespace arrow; namespace { - template long convertDate(typename T::value_type value) { + template int64_t convertDate(typename T::value_type value) { return value; } /// Converts the value from the array, which is in milliseconds, to seconds. /// \param value the value extracted from the array in milliseconds. /// \return the converted value in seconds. - template <> long convertDate(int64_t value) { + template <> int64_t convertDate(int64_t value) { return value / driver::flight_sql::MILLI_TO_SECONDS_DIVISOR; } /// Converts the value from the array, which is in days, to seconds. /// \param value the value extracted from the array in days. /// \return the converted value in seconds. - template <> long convertDate(int32_t value) { + template <> int64_t convertDate(int32_t value) { return value * driver::flight_sql::DAYS_TO_SECONDS_MULTIPLIER; } } // namespace @@ -61,7 +61,7 @@ void DateArrayFlightSqlAccessor::MoveSingleCell_impl( int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { typedef unsigned char c_type; auto *buffer = static_cast(binding->buffer); - long value = convertDate(array->Value(cell_counter)); + auto value = convertDate(array->Value(cell_counter)); tm date{}; GetTimeForMillisSinceEpoch(date, value); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc index 9f151f0aea703..eb4137036d678 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc @@ -49,7 +49,7 @@ TEST(DateArrayAccessor, Test_Date32Array_CDataType_DATE) { ASSERT_EQ(sizeof(DATE_STRUCT), strlen_buffer[i]); tm date{}; - long converted_time = values[i] * 86400; + int64_t converted_time = values[i] * 86400; GetTimeForMillisSinceEpoch(date, converted_time); ASSERT_EQ((date.tm_year + 1900), buffer[i].year); ASSERT_EQ(date.tm_mon + 1, buffer[i].month); @@ -80,7 +80,7 @@ TEST(DateArrayAccessor, Test_Date64Array_CDataType_DATE) { ASSERT_EQ(sizeof(DATE_STRUCT), strlen_buffer[i]); tm date{}; - long converted_time = values[i] / 1000; + int64_t converted_time = values[i] / 1000; GetTimeForMillisSinceEpoch(date, converted_time); ASSERT_EQ((date.tm_year + 1900), buffer[i].year); ASSERT_EQ(date.tm_mon + 1, buffer[i].month); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc index e79b110dc3bf0..7fd0654645e6a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc @@ -111,7 +111,6 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Basic) { } TEST(StringArrayAccessor, Test_CDataType_WCHAR_Truncation) { - GTEST_SKIP(); std::vector values = { "ABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEF"}; std::shared_ptr array; @@ -140,7 +139,7 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Truncation) { int64_t chunk_length = std::min(static_cast(max_strlen * sizeof(SqlWChar)), strlen_buffer[0] - value_offset); - finalStr += std::basic_string(buffer.data(), chunk_length); + finalStr += std::basic_string(buffer.data()); value_offset += chunk_length - sizeof(SqlWChar); } while (value_offset < strlen_buffer[0] - sizeof(SqlWChar)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc index 8f99466df76fe..0bce3a31f402b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc @@ -22,17 +22,17 @@ namespace driver { namespace flight_sql { namespace { template -long ConvertTimeValue(typename T::value_type value, TimeUnit::type unit) { +int64_t ConvertTimeValue(typename T::value_type value, TimeUnit::type unit) { return value; } template <> -long ConvertTimeValue(int32_t value, TimeUnit::type unit) { +int64_t ConvertTimeValue(int32_t value, TimeUnit::type unit) { return unit == TimeUnit::SECOND ? value : value / MILLI_TO_SECONDS_DIVISOR; } template <> -long ConvertTimeValue(int64_t value, TimeUnit::type unit) { +int64_t ConvertTimeValue(int64_t value, TimeUnit::type unit) { return unit == TimeUnit::MICRO ? value / MICRO_TO_SECONDS_DIVISOR : value / NANO_TO_SECONDS_DIVISOR; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc index 5f8705d1fc0d6..c4ff63c13571d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc @@ -84,7 +84,7 @@ TEST(TEST_TIME32, TIME_WITH_MILLI) { tm time{}; - long convertedValue = t32_values[i] / MILLI_TO_SECONDS_DIVISOR; + auto convertedValue = t32_values[i] / MILLI_TO_SECONDS_DIVISOR; GetTimeForMillisSinceEpoch(time, convertedValue); ASSERT_EQ(buffer[i].hour, time.tm_hour); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc index d362f4e947b6f..4627b13c8fd93 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc @@ -21,8 +21,8 @@ using namespace arrow; namespace { -long convertTimeStampBasedOnUnit(TimeUnit::type unit) { - long converted_result; +int64_t convertTimeStampBasedOnUnit(TimeUnit::type unit) { + int64_t converted_result; switch (unit) { case TimeUnit::SECOND: converted_result = 1; @@ -64,7 +64,7 @@ TimestampArrayFlightSqlAccessor::MoveSingleCell_impl(ColumnBinding typedef unsigned char c_type; auto *buffer = static_cast(binding->buffer); - long value = array->Value(cell_counter); + int64_t value = array->Value(cell_counter); const auto divisor = convertTimeStampBasedOnUnit(timestamp_type_->unit()); const auto converted_result = value / divisor; tm timestamp{}; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc index b02c6c060cad9..cea226282c1ef 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc @@ -28,7 +28,7 @@ using namespace arrow; using namespace odbcabstraction; TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MILI) { - std::vector values = {86400370, 172800000, 259200000, 1649793238110, + std::vector values = {86400370, 172800000, 259200000, 1649793238110LL, 345600000, 432000000, 518400000}; std::shared_ptr timestamp_array; @@ -52,7 +52,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MILI) { tm date{}; - long converted_time = values[i] / MILLI_TO_SECONDS_DIVISOR; + auto converted_time = values[i] / MILLI_TO_SECONDS_DIVISOR; GetTimeForMillisSinceEpoch(date, converted_time); ASSERT_EQ(buffer[i].year, 1900 + (date.tm_year)); @@ -90,7 +90,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_SECONDS) { ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); tm date{}; - long converted_time = values[i]; + auto converted_time = values[i]; GetTimeForMillisSinceEpoch(date, converted_time); ASSERT_EQ(buffer[i].year, 1900 + (date.tm_year)); @@ -128,7 +128,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MICRO) { tm date{}; - long converted_time = values[i] / MICRO_TO_SECONDS_DIVISOR; + auto converted_time = values[i] / MICRO_TO_SECONDS_DIVISOR; GetTimeForMillisSinceEpoch(date, converted_time); ASSERT_EQ(buffer[i].year, 1900 + (date.tm_year)); @@ -165,7 +165,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_NANO) { ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); tm date{}; - long converted_time = values[i] / NANO_TO_SECONDS_DIVISOR; + auto converted_time = values[i] / NANO_TO_SECONDS_DIVISOR; GetTimeForMillisSinceEpoch(date, converted_time); ASSERT_EQ(buffer[i].year, 1900 + (date.tm_year)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index b69eee4369182..fbc52ba5ab19a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -253,5 +253,9 @@ FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version) odbcabstraction::Diagnostics &FlightSqlConnection::GetDiagnostics() { return diagnostics_; } + +void FlightSqlConnection::SetClosed(bool is_closed) { + closed_ = is_closed; +} } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index dbb907e7e4d9d..30e309b922ce1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -81,6 +81,10 @@ class FlightSqlConnection : public odbcabstraction::Connection { const arrow::flight::FlightCallOptions &PopulateCallOptions(const ConnPropertyMap &properties); odbcabstraction::Diagnostics &GetDiagnostics() override; + + /// \brief A setter to the field closed_. + /// \note Visible for testing + void SetClosed(bool is_closed); }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index ab20ef924f1c7..00679e106c335 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -30,8 +30,8 @@ using arrow::flight::TimeoutDuration; using odbcabstraction::Connection; TEST(AttributeTests, SetAndGetAttribute) { - GTEST_SKIP(); FlightSqlConnection connection(odbcabstraction::V_3); + connection.SetClosed(false); connection.SetAttribute(Connection::CONNECTION_TIMEOUT, static_cast(200)); const boost::optional firstValue = @@ -53,13 +53,13 @@ TEST(AttributeTests, SetAndGetAttribute) { } TEST(AttributeTests, GetAttributeWithoutSetting) { - GTEST_SKIP(); FlightSqlConnection connection(odbcabstraction::V_3); - const boost::optional anOptional = + const boost::optional optional = connection.GetAttribute(Connection::CONNECTION_TIMEOUT); + connection.SetClosed(false); - EXPECT_FALSE(anOptional); + EXPECT_EQ(0, boost::get(*optional)); connection.Close(); } @@ -111,8 +111,8 @@ TEST(BuildLocationTests, ForTls) { } TEST(PopulateCallOptionsTest, ConnectionTimeout) { - GTEST_SKIP(); FlightSqlConnection connection(odbcabstraction::V_3); + connection.SetClosed(false); // Expect default timeout to be -1 ASSERT_EQ(TimeoutDuration{-1.0}, From 26f4def4801d9931a6671e76f740d060dea4c382 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Mon, 2 May 2022 16:25:21 -0300 Subject: [PATCH 104/183] Add ssl connection options to the odbc flight sql layer - It implements a new default behavior of driver that uses ssl enabled as default; - It implements the option to disable Certificate verification; - It implements the ability to connect passing a trusted cert; - It implements the ability to connect using the windows system trust store Change-Id: I5097021f0a8348716e37b5f11a84fa935ed424eb --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 5 +- .../flight_sql/flight_sql_connection.cc | 118 +++++++++++++++--- .../flight_sql/flight_sql_connection.h | 22 +++- .../flight_sql/flight_sql_connection_test.cc | 64 ++++++---- .../flight_sql/flight_sql_ssl_config.cc | 66 ++++++++++ .../flight_sql/flight_sql_ssl_config.h | 64 ++++++++++ .../flight_sql/system_trust_store.cc | 64 ++++++++++ .../flight_sql/system_trust_store.h | 69 ++++++++++ .../odbcabstraction/CMakeLists.txt | 4 +- .../include/odbcabstraction/utils.h | 43 +++++++ .../flightsql-odbc/odbcabstraction/utils.cc | 49 ++++++++ 11 files changed, 516 insertions(+), 52 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 7f2568ddc2605..d94faae0e96fe 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -145,6 +145,7 @@ set(ARROW_ODBC_SPI_SOURCES flight_sql_statement_get_tables.cc flight_sql_statement_get_type_info.cc flight_sql_statement_get_columns.cc + flight_sql_ssl_config.cc flight_sql_get_tables_reader.cc flight_sql_get_type_info_reader.cc flight_sql_stream_chunk_iterator.cc @@ -152,8 +153,8 @@ set(ARROW_ODBC_SPI_SOURCES json_converter.cc record_batch_transformer.cc scalar_function_reporter.cc - utils.cc -) + system_trust_store.cc + utils.cc) if (MSVC) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index fbc52ba5ab19a..3f3290f2e46b6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -18,8 +18,15 @@ #include "flight_sql_connection.h" #include +#include +#include #include +#include "flight_sql_auth_method.h" +#include "flight_sql_statement.h" +#include "flight_sql_ssl_config.h" +#include "utils.h" + #include #include #include @@ -29,9 +36,7 @@ #include #include -#include "flight_sql_auth_method.h" -#include "flight_sql_statement.h" -#include "utils.h" +#include "system_trust_store.h" namespace driver { namespace flight_sql { @@ -44,6 +49,7 @@ using arrow::flight::FlightClientOptions; using arrow::flight::Location; using arrow::flight::TimeoutDuration; using arrow::flight::sql::FlightSqlClient; +using driver::odbcabstraction::AsBool; using driver::odbcabstraction::Connection; using driver::odbcabstraction::DriverException; using driver::odbcabstraction::OdbcVersion; @@ -56,10 +62,49 @@ const std::string FlightSqlConnection::UID = "uid"; const std::string FlightSqlConnection::PASSWORD = "password"; const std::string FlightSqlConnection::PWD = "pwd"; const std::string FlightSqlConnection::TOKEN = "token"; -const std::string FlightSqlConnection::USE_TLS = "useTls"; - +const std::string FlightSqlConnection::USE_ENCRYPTION = "useEncryption"; +const std::string FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION = "disableCertificateVerification"; +const std::string FlightSqlConnection::TRUSTED_CERTS = "trustedCerts"; +const std::string FlightSqlConnection::USE_SYSTEM_TRUST_STORE = "useSystemTrustStore"; namespace { + +#if _WIN32 || _WIN64 +constexpr auto SYSTEM_TRUST_STORE_DEFAULT = true; +constexpr auto STORES = { + "CA", + "MY", + "ROOT", + "SPC" +}; + +inline std::string GetCerts() { + std::string certs; + + for (auto store : STORES) { + std::shared_ptr cert_iterator = std::make_shared(store); + + if (!cert_iterator->SystemHasStore()) { + // If the system does not have the specific store, we skip it using the continue. + continue; + } + while (cert_iterator->HasNext()) { + certs += cert_iterator->GetNext(); + } + } + + return certs; +} + +#else + +constexpr auto SYSTEM_TRUST_STORE_DEFAULT = false; +inline std::string GetCerts() { + return ""; +} + +#endif + const std::set BUILT_IN_PROPERTIES = { FlightSqlConnection::HOST, FlightSqlConnection::PORT, @@ -68,12 +113,12 @@ const std::set BUILT_IN_PROP FlightSqlConnection::PASSWORD, FlightSqlConnection::PWD, FlightSqlConnection::TOKEN, - FlightSqlConnection::USE_TLS + FlightSqlConnection::USE_ENCRYPTION, + FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, + FlightSqlConnection::TRUSTED_CERTS, + FlightSqlConnection::USE_SYSTEM_TRUST_STORE }; -// TODO: Add properties for getting the certificates -// TODO: Check if gRPC can use the system truststore, if not copy from Drill - Connection::ConnPropertyMap::const_iterator TrackMissingRequiredProperty(const std::string &property, const Connection::ConnPropertyMap &properties, @@ -87,12 +132,29 @@ TrackMissingRequiredProperty(const std::string &property, } } // namespace +std::shared_ptr LoadFlightSslConfigs(const Connection::ConnPropertyMap &connPropertyMap) { + bool use_encryption = AsBool(true, connPropertyMap, FlightSqlConnection::USE_ENCRYPTION); + bool disable_cert = AsBool(false, connPropertyMap, FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION); + bool use_system_trusted = AsBool(SYSTEM_TRUST_STORE_DEFAULT, connPropertyMap, FlightSqlConnection::USE_SYSTEM_TRUST_STORE); + + auto trusted_certs_iterator = connPropertyMap.find( + FlightSqlConnection::TRUSTED_CERTS); + auto trusted_certs = + trusted_certs_iterator != connPropertyMap.end() ? trusted_certs_iterator->second : ""; + + return std::make_shared(disable_cert, trusted_certs, + use_system_trusted, use_encryption); +} + void FlightSqlConnection::Connect(const ConnPropertyMap &properties, std::vector &missing_attr) { try { - Location location = BuildLocation(properties, missing_attr); + auto flight_ssl_configs = LoadFlightSslConfigs(properties); + + Location location = BuildLocation(properties, missing_attr, flight_ssl_configs); FlightClientOptions client_options = - BuildFlightClientOptions(properties, missing_attr); + BuildFlightClientOptions(properties, missing_attr, + flight_ssl_configs); const std::shared_ptr &cookie_factory = arrow::flight::GetCookieFactory(); @@ -100,10 +162,10 @@ void FlightSqlConnection::Connect(const ConnPropertyMap &properties, std::unique_ptr flight_client; ThrowIfNotOK( - FlightClient::Connect(location, client_options, &flight_client)); + FlightClient::Connect(location, client_options, &flight_client)); std::unique_ptr auth_method = - FlightSqlAuthMethod::FromProperties(flight_client, properties); + FlightSqlAuthMethod::FromProperties(flight_client, properties); auth_method->Authenticate(*this, call_options_); sql_client_.reset(new FlightSqlClient(std::move(flight_client))); @@ -148,19 +210,37 @@ FlightSqlConnection::PopulateCallOptions(const ConnPropertyMap &props) { return call_options_; } -FlightClientOptions FlightSqlConnection::BuildFlightClientOptions( - const ConnPropertyMap &properties, std::vector &missing_attr) { +FlightClientOptions +FlightSqlConnection::BuildFlightClientOptions(const ConnPropertyMap &properties, + std::vector &missing_attr, + const std::shared_ptr& ssl_config) { FlightClientOptions options; // Persist state information using cookies if the FlightProducer supports it. options.middleware.push_back(arrow::flight::GetCookieFactory()); - // TODO: Set up TLS properties + if (ssl_config->useEncryption()) { + if (ssl_config->shouldDisableCertificateVerification()) { + options.disable_server_verification = ssl_config->shouldDisableCertificateVerification(); + } else { + if (ssl_config->useSystemTrustStore()) { + const std::string certs = GetCerts(); + + options.tls_root_certs = certs; + } else if (!ssl_config->getTrustedCerts().empty()) { + flight::CertKeyPair cert_key_pair; + ssl_config->populateOptionsWithCerts(&cert_key_pair); + options.tls_root_certs = cert_key_pair.pem_cert; + } + } + } + return std::move(options); } Location FlightSqlConnection::BuildLocation(const ConnPropertyMap &properties, - std::vector &missing_attr) { + std::vector &missing_attr, + const std::shared_ptr& ssl_config) { const auto &host_iter = TrackMissingRequiredProperty(HOST, properties, missing_attr); @@ -178,9 +258,7 @@ FlightSqlConnection::BuildLocation(const ConnPropertyMap &properties, const int &port = boost::lexical_cast(port_iter->second); Location location; - const auto &it_use_tls = properties.find(USE_TLS); - if (it_use_tls != properties.end() && - boost::lexical_cast(it_use_tls->second)) { + if (ssl_config->useEncryption()) { ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); } else { ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 30e309b922ce1..7910f74b8ec35 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -27,6 +27,16 @@ namespace driver { namespace flight_sql { +class FlightSqlSslConfig; + +/// \brief Create an instance of the FlightSqlSslConfig class, from the properties passed +/// into the map. +/// \param connPropertyMap the map with the Connection properties. +/// \return An instance of the FlightSqlSslConfig. +std::shared_ptr LoadFlightSslConfigs( + const odbcabstraction::Connection::ConnPropertyMap &connPropertyMap); + + class FlightSqlConnection : public odbcabstraction::Connection { private: @@ -46,7 +56,10 @@ class FlightSqlConnection : public odbcabstraction::Connection { static const std::string PASSWORD; static const std::string PWD; static const std::string TOKEN; - static const std::string USE_TLS; + static const std::string USE_ENCRYPTION; + static const std::string DISABLE_CERTIFICATE_VERIFICATION; + static const std::string TRUSTED_CERTS; + static const std::string USE_SYSTEM_TRUST_STORE; explicit FlightSqlConnection(odbcabstraction::OdbcVersion odbc_version); @@ -67,14 +80,15 @@ class FlightSqlConnection : public odbcabstraction::Connection { /// \brief Builds a Location used for FlightClient connection. /// \note Visible for testing static arrow::flight::Location - BuildLocation(const ConnPropertyMap &properties, - std::vector &missing_attr); + BuildLocation(const ConnPropertyMap &properties, std::vector &missing_attr, + const std::shared_ptr& ssl_config); /// \brief Builds a FlightClientOptions used for FlightClient connection. /// \note Visible for testing static arrow::flight::FlightClientOptions BuildFlightClientOptions(const ConnPropertyMap &properties, - std::vector &missing_attr); + std::vector &missing_attr, + const std::shared_ptr& ssl_config); /// \brief Builds a FlightCallOptions used on gRPC calls. /// \note Visible for testing diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 00679e106c335..e16b97150c67d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -66,42 +66,56 @@ TEST(AttributeTests, GetAttributeWithoutSetting) { TEST(BuildLocationTests, ForTcp) { std::vector missing_attr; - const Location &actual_location1 = FlightSqlConnection::BuildLocation( - { - {FlightSqlConnection::HOST, std::string("localhost")}, - {FlightSqlConnection::PORT, std::string("32010")}, - }, - missing_attr); + Connection::ConnPropertyMap properties = { + {FlightSqlConnection::HOST, std::string("localhost")}, + {FlightSqlConnection::PORT, std::string("32010")}, + {FlightSqlConnection::USE_ENCRYPTION, std::string("false")}, + }; + + const std::shared_ptr &ssl_config = + LoadFlightSslConfigs(properties); + + const Location &actual_location1 = + FlightSqlConnection::BuildLocation(properties, missing_attr, ssl_config); const Location &actual_location2 = FlightSqlConnection::BuildLocation( - { - {FlightSqlConnection::HOST, std::string("localhost")}, - {FlightSqlConnection::PORT, std::string("32011")}, - }, - missing_attr); + { + {FlightSqlConnection::HOST, std::string("localhost")}, + {FlightSqlConnection::PORT, std::string("32011")}, + }, + missing_attr, ssl_config); Location expected_location; ASSERT_TRUE( - Location::ForGrpcTcp("localhost", 32010, &expected_location).ok()); + Location::ForGrpcTcp("localhost", 32010, &expected_location).ok()); ASSERT_EQ(expected_location, actual_location1); ASSERT_NE(expected_location, actual_location2); } TEST(BuildLocationTests, ForTls) { std::vector missing_attr; - const Location &actual_location1 = FlightSqlConnection::BuildLocation( - { - {FlightSqlConnection::HOST, std::string("localhost")}, - {FlightSqlConnection::PORT, std::string("32010")}, - {FlightSqlConnection::USE_TLS, std::string("1")}, - }, - missing_attr); + Connection::ConnPropertyMap properties = { + {FlightSqlConnection::HOST, std::string("localhost")}, + {FlightSqlConnection::PORT, std::string("32010")}, + {FlightSqlConnection::USE_ENCRYPTION, std::string("1")}, + }; + + const std::shared_ptr &ssl_config = + LoadFlightSslConfigs(properties); + + const Location &actual_location1 = + FlightSqlConnection::BuildLocation(properties, missing_attr, ssl_config); + + Connection::ConnPropertyMap second_properties = { + {FlightSqlConnection::HOST, std::string("localhost")}, + {FlightSqlConnection::PORT, std::string("32011")}, + {FlightSqlConnection::USE_ENCRYPTION, std::string("1")}, + }; + + const std::shared_ptr &second_ssl_config = + LoadFlightSslConfigs(properties); + const Location &actual_location2 = FlightSqlConnection::BuildLocation( - { - {FlightSqlConnection::HOST, std::string("localhost")}, - {FlightSqlConnection::PORT, std::string("32011")}, - {FlightSqlConnection::USE_TLS, std::string("1")}, - }, - missing_attr); + second_properties, missing_attr, ssl_config); Location expected_location; ASSERT_TRUE( diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.cc new file mode 100644 index 0000000000000..3c95b7790b9a8 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.cc @@ -0,0 +1,66 @@ +// 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 "flight_sql_ssl_config.h" + +#include +#include +#include + +namespace driver { +namespace flight_sql { + + +FlightSqlSslConfig::FlightSqlSslConfig( + bool disableCertificateVerification, const std::string& trustedCerts, + bool systemTrustStore, bool useEncryption) + : trustedCerts_(trustedCerts), useEncryption_(useEncryption), + disableCertificateVerification_(disableCertificateVerification), + systemTrustStore_(systemTrustStore) {} + +bool FlightSqlSslConfig::useEncryption() const { + return useEncryption_; +} + +bool FlightSqlSslConfig::shouldDisableCertificateVerification() const { + return disableCertificateVerification_; +} + +const std::string& FlightSqlSslConfig::getTrustedCerts() const { + return trustedCerts_; +} + +bool FlightSqlSslConfig::useSystemTrustStore() const { + return systemTrustStore_; +} + +void FlightSqlSslConfig::populateOptionsWithCerts(arrow::flight::CertKeyPair* out) { + try { + std::ifstream cert_file(trustedCerts_); + if (!cert_file) { + throw odbcabstraction::DriverException("Could not open certificate: " + trustedCerts_); + } + std::stringstream cert; + cert << cert_file.rdbuf(); + out->pem_cert = cert.str(); + } + catch (const std::ifstream::failure& e) { + throw odbcabstraction::DriverException(e.what()); + } +} +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.h new file mode 100644 index 0000000000000..d818d513af2eb --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.h @@ -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. + +#pragma once + +#include "arrow/flight/types.h" +#include +#include + +namespace driver { +namespace flight_sql { + +/// \brief An Auxiliary class that holds all the information to perform +/// a SSL connection. +class FlightSqlSslConfig { +public: + FlightSqlSslConfig(bool disableCertificateVerification, + const std::string &trustedCerts, bool systemTrustStore, + bool useEncryption); + + /// \brief Tells if ssl is enabled. By default it will be true. + /// \return Whether ssl is enabled. + bool useEncryption() const; + + /// \brief Tells if disable certificate verification is enabled. + /// \return Whether disable certificate verification is enabled. + bool shouldDisableCertificateVerification() const; + + /// \brief The path to the trusted certificate. + /// \return Certificate path. + const std::string &getTrustedCerts() const; + + /// \brief Tells if we need to check if the certificate is in the system trust store. + /// \return Whether to use the system trust store. + bool useSystemTrustStore() const; + + /// \brief Loads the certificate file and extract the certificate file from it + /// and create the object CertKeyPair with it on. + /// \param out A CertKeyPair with the cert on it. + /// \return The cert key pair object + void populateOptionsWithCerts(arrow::flight::CertKeyPair *out); + +private: + const std::string trustedCerts_; + const bool useEncryption_; + const bool disableCertificateVerification_; + const bool systemTrustStore_; +}; +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.cc new file mode 100644 index 0000000000000..8387a5897336c --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.cc @@ -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. + +#include "system_trust_store.h" + + +#if defined _WIN32 || defined _WIN64 + +namespace driver { +namespace flight_sql { + bool SystemTrustStore::HasNext() { + p_context_ = CertEnumCertificatesInStore(h_store_, p_context_); + + return p_context_ != nullptr; + } + + std::string SystemTrustStore::GetNext() const { + DWORD size = 0; + CryptBinaryToString(p_context_->pbCertEncoded, p_context_->cbCertEncoded, + CRYPT_STRING_BASE64HEADER, nullptr, &size); + + std::string cert; + cert.resize(size); + CryptBinaryToString(p_context_->pbCertEncoded, + p_context_->cbCertEncoded, CRYPT_STRING_BASE64HEADER, + &cert[0], &size); + cert.resize(size); + + return cert; + } + + bool SystemTrustStore::SystemHasStore() { + return h_store_ != nullptr; + } + + SystemTrustStore::SystemTrustStore(const char* store) : stores_(store), + h_store_(CertOpenSystemStore(NULL, store)), p_context_(nullptr) {} + + SystemTrustStore::~SystemTrustStore() { + if (p_context_) { + CertFreeCertificateContext(p_context_); + } + if (h_store_) { + CertCloseStore(h_store_, 0); + } + } +} // namespace flight_sql +} // namespace driver + +#endif diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.h new file mode 100644 index 0000000000000..8504806ee361e --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.h @@ -0,0 +1,69 @@ +// 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. + +#pragma once + +#if defined _WIN32 || defined _WIN64 + +#include +#include +#include +#include +#include +#include +#include + +namespace driver { +namespace flight_sql { + +/// Load the certificates from the windows system trust store. Part of the logic +/// was based in the drill connector +/// https://github.com/apache/drill/blob/master/contrib/native/client/src/clientlib/wincert.ipp. +class SystemTrustStore { +private: + const char* stores_; + HCERTSTORE h_store_; + PCCERT_CONTEXT p_context_; + +public: + explicit SystemTrustStore(const char* store); + + ~SystemTrustStore(); + + /// Check if there is a certificate inside the system trust store to be extracted + /// \return If there is a valid cert in the store. + bool HasNext(); + + /// Get the next certificate from the store. + /// \return the certificate. + std::string GetNext() const; + + /// Check if the system has the specify store. + /// \return If the specific store exist in the system. + bool SystemHasStore(); +}; +} // namespace flight_sql +} // namespace driver + +#else // Not Windows +namespace driver { +namespace flight_sql { +class SystemTrustStore; +} // namespace flight_sql +} // namespace driver + +#endif diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index b56affab78d88..1770aca6cbbc3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -24,9 +24,11 @@ include_directories(include) add_library(odbcabstraction include/odbcabstraction/diagnostics.h include/odbcabstraction/error_codes.h + include/odbcabstraction/utils.h calendar_utils.cc diagnostics.cc - exceptions.cc) + exceptions.cc + utils.cc) set_target_properties(odbcabstraction PROPERTIES diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h new file mode 100644 index 0000000000000..1a9bd800a3cdb --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h @@ -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. + +#pragma once + +#include +#include + +namespace driver { +namespace odbcabstraction { + +using driver::odbcabstraction::Connection; + +/// Parse a string value to a boolean. +/// \param value the value to be parsed. +/// \param default_value the default value in case the parse fails. +/// \return the parsed valued. +bool AsBool(const std::string& value, const bool default_value); + +/// Looks up for a value inside the ConnPropertyMap and then try to parse it. +/// In case it does not find or it cannot parse, the default value will be returned. +/// \param default_value the default value to be parsed. +/// \param connPropertyMap the map with the connection properties. +/// \param property_name the name of the property that will be looked up. +/// \return the parsed valued. +bool AsBool(const bool default_value, const Connection::ConnPropertyMap& connPropertyMap, + const std::string& property_name); +} // namespace odbcabstraction +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc new file mode 100644 index 0000000000000..0e9d864c54e5f --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc @@ -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. + +#include + +#include + +namespace driver { +namespace odbcabstraction { + +bool AsBool(const std::string& value, const bool default_value) { + if (boost::iequals(value, "true") || boost::iequals(value, "1")) { + return true; + } else if (boost::iequals(value, "false") || boost::iequals(value, "0")) { + return false; + } else { + return default_value; + } +} + +bool AsBool( const bool default_value, const Connection::ConnPropertyMap& connPropertyMap, + const std::string& property_name) { + + auto extracted_property = connPropertyMap.find( + property_name); + + if (extracted_property != connPropertyMap.end()) { + return AsBool(extracted_property->second, default_value); + } + else { + return default_value; + } +} +} // namespace odbcabstraction +} // namespace driver From 02ccf30a6884c32bb3f32fac31b5263de03bd198 Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 26 May 2022 12:32:30 +0000 Subject: [PATCH 105/183] Memory leak when using complex types that have binary data Fix a memory leak due to using new char[] in json_converter and not deleting it. Change-Id: Iac93467dfe398c00d91a2a12da6de4a0e489ecef --- .../flight_sql/json_converter.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc index dd2b0bd81e4b0..4fb5d8d128a82 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc @@ -132,9 +132,9 @@ class ScalarToJson : public arrow::ScalarVisitor { Status Visit(const BinaryScalar &scalar) override { const auto &view = scalar.view(); size_t encoded_size = base64::encoded_size(view.length()); - char* encoded = new char[encoded_size]; - base64::encode(encoded, view.data(), view.length()); - writer_.String(encoded, encoded_size); + std::vector encoded(std::max(encoded_size, static_cast(1))); + base64::encode(&encoded[0], view.data(), view.length()); + writer_.String(&encoded[0], encoded_size, true); return Status::OK(); } @@ -149,9 +149,9 @@ class ScalarToJson : public arrow::ScalarVisitor { Status Visit(const LargeBinaryScalar &scalar) override { const auto &view = scalar.view(); size_t encoded_size = base64::encoded_size(view.length()); - char* encoded = new char[encoded_size]; - base64::encode(encoded, view.data(), view.length()); - writer_.String(encoded, encoded_size); + std::vector encoded(std::max(encoded_size, static_cast(1))); + base64::encode(&encoded[0], view.data(), view.length()); + writer_.String(&encoded[0], encoded_size, true); return Status::OK(); } @@ -159,9 +159,9 @@ class ScalarToJson : public arrow::ScalarVisitor { Status Visit(const FixedSizeBinaryScalar &scalar) override { const auto &view = scalar.view(); size_t encoded_size = base64::encoded_size(view.length()); - char* encoded = new char[encoded_size]; - base64::encode(encoded, view.data(), view.length()); - writer_.String(encoded, encoded_size); + std::vector encoded(std::max(encoded_size, static_cast(1))); + base64::encode(&encoded[0], view.data(), view.length()); + writer_.String(&encoded[0], encoded_size, true); return Status::OK(); } From a203e0a1031d1a0e0f1523006fe3b9b457db3077 Mon Sep 17 00:00:00 2001 From: James Duong Date: Wed, 18 May 2022 15:01:14 -0700 Subject: [PATCH 106/183] Change MacOS build to allow vcpkg configuration - Run the CMAKE_TOOLCHAIN_FILE when it is defined - Propagate VCPKG-related options to external projects - Always set VCPKG_MANIFEST_MODE to OFF for external projects to use the ones the building project retrieved. Change-Id: I85beb7916bdb80def88186591beaf1a38ac3dea0 --- .../flightsql-odbc/CMakeLists.txt | 9 +++++ .../flightsql-odbc/flight_sql/CMakeLists.txt | 37 +++++++++++++++---- .../odbcabstraction/CMakeLists.txt | 4 +- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index d4967e22f2634..19d60fdd2e3d2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -24,6 +24,15 @@ project(flightsql_odbc) find_package(Boost REQUIRED) include_directories(${Boost_INCLUDE_DIRS}) +# Add ODBC dependencies. +if (APPLE) + set(ODBC_INCLUDE_DIRS /usr/local/Cellar/libiodbc/3.52.15/include) + add_compile_definitions(HAVE_LONG_LONG SQLCOLATTRIBUTE_SQLLEN WITH_IODBC) +else() + find_package(ODBC REQUIRED) +endif() +include_directories(${ODBC_INCLUDE_DIRS}) + # Fetch and include GTest # Adapted from Google's documentation: https://google.github.io/googletest/quickstart-cmake.html#set-up-a-project include(FetchContent) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index d94faae0e96fe..be858333d361e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -24,7 +24,11 @@ include_directories( include ${CMAKE_SOURCE_DIR}/odbcabstraction/include) -# Add Zlib dependencies needed by Arrow Flight. Should be pre-installed. +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. @@ -35,7 +39,7 @@ find_package(Protobuf REQUIRED) # 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) +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 @@ -79,6 +83,29 @@ if (MSVC) -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} ${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow/cpp ) +elseif(APPLE) + set(ARROW_CMAKE_ARGS + -DARROW_FLIGHT=ON + -DARROW_FLIGHT_SQL=ON + -DARROW_IPC=ON + -DARROW_BUILD_SHARED=OFF + -DARROW_BUILD_STATIC=ON + -DARROW_COMPUTE=ON + -DARROW_WITH_UTF8PROC=OFF + -DARROW_BUILD_TESTS=OFF + -DARROW_DEPENDENCY_USE_SHARED=OFF + -DARROW_DEPENDENCY_USE_STATIC=ON + -DCMAKE_DEPENDS_USE_COMPILER=FALSE + -DVCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET} + -DVCPKG_MANIFEST_MODE=OFF + -DCMAKE_DEPENDS_USE_COMPILER=FALSE + -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install + -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} + ${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow/cpp + ) + if (DEFINED CMAKE_TOOLCHAIN_FILE) + list(APPEND ARROW_CMAKE_ARGS -DARROW_DEPENDENCY_SOURCE=VCPKG) + endif() else() set(ARROW_CMAKE_ARGS -DARROW_FLIGHT=ON @@ -106,7 +133,7 @@ ExternalProject_Add(ApacheArrow GIT_TAG ${ARROW_GIT_TAG} CMAKE_ARGS ${ARROW_CMAKE_ARGS}) -include_directories(${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install/include) +include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install/include) IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(ARROW_LIB_DIR lib64) else() @@ -114,10 +141,6 @@ else() endif() link_directories(${CMAKE_CURRENT_BINARY_DIR}/ApacheArrow-prefix/src/ApacheArrow-install/${ARROW_LIB_DIR}) -if (APPLE) - add_compile_definitions(WITH_IODBC) -endif() - 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) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index 1770aca6cbbc3..8bd11104c24b7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -15,8 +15,6 @@ # specific language governing permissions and limitations # under the License. -include(FindODBC) - set(CMAKE_POSITION_INDEPENDENT_CODE ON) include_directories(include) @@ -36,4 +34,4 @@ set_target_properties(odbcabstraction LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib ) -target_link_libraries(odbcabstraction ${ODBC_LIBRARIES}) +target_link_libraries(odbcabstraction) From cb854c2684743e9ee3e096b00306b01c758348dc Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 26 May 2022 21:59:04 +0000 Subject: [PATCH 107/183] Avoid inclusion of extra windows headers Define WIN32_LEAN_AND_MEAN before including windows.h to reduce the number of headers included implicitly. Change-Id: Iad1fc5e043e7ebbf6057e2e2832722f6ca9913fb --- .../odbcabstraction/include/odbcabstraction/platform.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h index 04f0480a4af1b..d479dd7f3371e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h @@ -19,7 +19,15 @@ #if defined(_WIN32) // NOMINMAX avoids std::min/max being defined as a c macro + #ifndef NOMINMAX #define NOMINMAX + #endif + + // Avoid including extraneous Windows headers. + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #include #include From 7ff73d720331cc5f613fe01f58eed72c0e950cc2 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Fri, 27 May 2022 11:19:22 -0300 Subject: [PATCH 108/183] Add calendar types to default types and also refactor the converter logic. - Add some missing calendar types when creating accessor - Handle conversion from string to date - Handle conversion from string to time Change-Id: I6b127f37eca8ce9149f77d766337c4cb15d13144 --- .../flight_sql_result_set_column.cc | 103 +------- .../flightsql-odbc/flight_sql/utils.cc | 231 ++++++++++++++++++ .../flightsql-odbc/flight_sql/utils.h | 18 ++ .../flightsql-odbc/flight_sql/utils_test.cc | 30 +++ .../include/odbcabstraction/types.h | 1 + 5 files changed, 290 insertions(+), 93 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index 453a135502cd2..617722e5ef5fe 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -19,8 +19,8 @@ #include #include "flight_sql_result_set.h" #include "json_converter.h" +#include "utils.h" #include -#include #include #include @@ -28,105 +28,18 @@ namespace driver { namespace flight_sql { namespace { -std::shared_ptr -GetDefaultDataTypeForTypeId(arrow::Type::type type_id) { - switch (type_id) { - case arrow::Type::STRING: - return arrow::utf8(); - case arrow::Type::INT16: - return arrow::int16(); - case arrow::Type::UINT16: - return arrow::uint16(); - case arrow::Type::INT32: - return arrow::int32(); - case arrow::Type::UINT32: - return arrow::uint32(); - case arrow::Type::FLOAT: - return arrow::float32(); - case arrow::Type::DOUBLE: - return arrow::float64(); - case arrow::Type::BOOL: - return arrow::boolean(); - case arrow::Type::INT8: - return arrow::int8(); - case arrow::Type::UINT8: - return arrow::uint8(); - case arrow::Type::INT64: - return arrow::int64(); - case arrow::Type::UINT64: - return arrow::uint64(); - case arrow::Type::BINARY: - return arrow::binary(); - } - - throw odbcabstraction::DriverException(std::string("Invalid type id: ") + std::to_string(type_id)); -} - -arrow::Type::type -ConvertCToArrowType(odbcabstraction::CDataType data_type) { - switch (data_type) { - case odbcabstraction::CDataType_CHAR: - case odbcabstraction::CDataType_WCHAR: - return arrow::Type::STRING; - case odbcabstraction::CDataType_SSHORT: - return arrow::Type::INT16; - case odbcabstraction::CDataType_USHORT: - return arrow::Type::UINT16; - case odbcabstraction::CDataType_SLONG: - return arrow::Type::INT32; - case odbcabstraction::CDataType_ULONG: - return arrow::Type::UINT32; - case odbcabstraction::CDataType_FLOAT: - return arrow::Type::FLOAT; - case odbcabstraction::CDataType_DOUBLE: - return arrow::Type::DOUBLE; - case odbcabstraction::CDataType_BIT: - return arrow::Type::BOOL; - case odbcabstraction::CDataType_STINYINT: - return arrow::Type::INT8; - case odbcabstraction::CDataType_UTINYINT: - return arrow::Type::UINT8; - case odbcabstraction::CDataType_SBIGINT: - return arrow::Type::INT64; - case odbcabstraction::CDataType_UBIGINT: - return arrow::Type::UINT64; - case odbcabstraction::CDataType_BINARY: - return arrow::Type::BINARY; - case odbcabstraction::CDataType_NUMERIC: - return arrow::Type::DECIMAL128; - } - - throw odbcabstraction::DriverException(std::string("Invalid target type: ") + std::to_string(data_type)); -} - std::shared_ptr CastArray(const std::shared_ptr &original_array, CDataType target_type) { - const arrow::Type::type &target_arrow_type_id = ConvertCToArrowType(target_type); - if (original_array->type()->id() == target_arrow_type_id) { - // Avoid casting if target type is the same as original - return original_array; - } - - arrow::compute::CastOptions cast_options; - cast_options.to_type = GetDefaultDataTypeForTypeId(target_arrow_type_id); - - const arrow::Result &result = - arrow::compute::CallFunction("cast", {original_array}, &cast_options); - if (result.ok()) { - arrow::Datum datum = result.ValueOrDie(); - return std::move(datum).make_array(); - } else if (target_type == odbcabstraction::CDataType_CHAR || target_type == odbcabstraction::CDataType_WCHAR) { - // Fallback to JSON conversion if target type is CHAR/WCHAR - const auto &json_conversion_result = ConvertToJson(original_array); - ThrowIfNotOK(json_conversion_result.status()); + bool conversion = NeedArrayConversion(original_array->type()->id(), target_type); - return json_conversion_result.ValueOrDie(); + if (conversion) { + auto converter = GetConverter(original_array->type_id(), target_type); + return converter(original_array); } else { - throw odbcabstraction::DriverException(result.status().message()); + return original_array; } } - } // namespace std::unique_ptr @@ -144,6 +57,10 @@ FlightSqlResultSetColumn::GetAccessorForTargetType(CDataType target_type) { const std::shared_ptr &original_array = result_set_->GetArrayForColumn(column_n_); + if (target_type == odbcabstraction::CDataType_DEFAULT) { + target_type = ConvertArrowTypeToC(original_array->type_id()); + } + // TODO: Figure out if that's the best way of caching if (cached_accessor_ && original_array.get() == cached_original_array_ && cached_accessor_->target_type_ == target_type) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 8d76c25320118..80a920a1cbb32 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -16,8 +16,10 @@ // under the License. #include "utils.h" +#include "arrow/type_fwd.h" #include #include +#include #include namespace driver { @@ -472,5 +474,234 @@ boost::xpressive::sregex ConvertSqlPatternToRegex(const std::string &pattern) { return boost::xpressive::sregex(boost::xpressive::sregex::compile(regex_str)); } +bool NeedArrayConversion(arrow::Type::type original_type_id, odbcabstraction::CDataType data_type) { + switch (original_type_id) { + case arrow::Type::DATE32: + case arrow::Type::DATE64: + return data_type != odbcabstraction::CDataType_DATE; + case arrow::Type::TIME32: + case arrow::Type::TIME64: + return data_type != odbcabstraction::CDataType_TIME; + case arrow::Type::TIMESTAMP: + return data_type != odbcabstraction::CDataType_TIMESTAMP; + case arrow::Type::STRING: + return data_type != odbcabstraction::CDataType_CHAR && + data_type != odbcabstraction::CDataType_WCHAR; + case arrow::Type::INT16: + return data_type != odbcabstraction::CDataType_SSHORT; + case arrow::Type::UINT16: + return data_type != odbcabstraction::CDataType_USHORT; + case arrow::Type::INT32: + return data_type != odbcabstraction::CDataType_SLONG; + case arrow::Type::UINT32: + return data_type != odbcabstraction::CDataType_ULONG; + case arrow::Type::FLOAT: + return data_type != odbcabstraction::CDataType_FLOAT; + case arrow::Type::DOUBLE: + return data_type != odbcabstraction::CDataType_DOUBLE; + case arrow::Type::BOOL: + return data_type != odbcabstraction::CDataType_BIT; + case arrow::Type::INT8: + return data_type != odbcabstraction::CDataType_STINYINT; + case arrow::Type::UINT8: + return data_type != odbcabstraction::CDataType_UTINYINT; + case arrow::Type::INT64: + return data_type != odbcabstraction::CDataType_SBIGINT; + case arrow::Type::UINT64: + return data_type != odbcabstraction::CDataType_UBIGINT; + case arrow::Type::BINARY: + return data_type != odbcabstraction::CDataType_BINARY; + case arrow::Type::DECIMAL128: + return data_type != odbcabstraction::CDataType_NUMERIC; + default: + throw odbcabstraction::DriverException(std::string("Invalid conversion")); + } +} + +std::shared_ptr +GetDefaultDataTypeForTypeId(arrow::Type::type type_id) { + switch (type_id) { + case arrow::Type::STRING: + return arrow::utf8(); + case arrow::Type::INT16: + return arrow::int16(); + case arrow::Type::UINT16: + return arrow::uint16(); + case arrow::Type::INT32: + return arrow::int32(); + case arrow::Type::UINT32: + return arrow::uint32(); + case arrow::Type::FLOAT: + return arrow::float32(); + case arrow::Type::DOUBLE: + return arrow::float64(); + case arrow::Type::BOOL: + return arrow::boolean(); + case arrow::Type::INT8: + return arrow::int8(); + case arrow::Type::UINT8: + return arrow::uint8(); + case arrow::Type::INT64: + return arrow::int64(); + case arrow::Type::UINT64: + return arrow::uint64(); + case arrow::Type::BINARY: + return arrow::binary(); + case arrow::Type::DATE64: + return arrow::date64(); + case arrow::Type::TIME64: + return arrow::time64(arrow::TimeUnit::MICRO); + case arrow::Type::TIMESTAMP: + return arrow::timestamp(arrow::TimeUnit::SECOND); + } + + throw odbcabstraction::DriverException(std::string("Invalid type id: ") + std::to_string(type_id)); +} + +arrow::Type::type +ConvertCToArrowType(odbcabstraction::CDataType data_type) { + switch (data_type) { + case odbcabstraction::CDataType_CHAR: + case odbcabstraction::CDataType_WCHAR: + return arrow::Type::STRING; + case odbcabstraction::CDataType_SSHORT: + return arrow::Type::INT16; + case odbcabstraction::CDataType_USHORT: + return arrow::Type::UINT16; + case odbcabstraction::CDataType_SLONG: + return arrow::Type::INT32; + case odbcabstraction::CDataType_ULONG: + return arrow::Type::UINT32; + case odbcabstraction::CDataType_FLOAT: + return arrow::Type::FLOAT; + case odbcabstraction::CDataType_DOUBLE: + return arrow::Type::DOUBLE; + case odbcabstraction::CDataType_BIT: + return arrow::Type::BOOL; + case odbcabstraction::CDataType_STINYINT: + return arrow::Type::INT8; + case odbcabstraction::CDataType_UTINYINT: + return arrow::Type::UINT8; + case odbcabstraction::CDataType_SBIGINT: + return arrow::Type::INT64; + case odbcabstraction::CDataType_UBIGINT: + return arrow::Type::UINT64; + case odbcabstraction::CDataType_BINARY: + return arrow::Type::BINARY; + case odbcabstraction::CDataType_NUMERIC: + return arrow::Type::DECIMAL128; + case odbcabstraction::CDataType_TIMESTAMP: + return arrow::Type::TIMESTAMP; + case odbcabstraction::CDataType_TIME: + return arrow::Type::TIME64; + case odbcabstraction::CDataType_DATE: + return arrow::Type::DATE64; + default: + throw odbcabstraction::DriverException(std::string("Invalid target type: ") + std::to_string(data_type)); + } +} + +odbcabstraction::CDataType ConvertArrowTypeToC(arrow::Type::type type_id) { + switch (type_id) { + case arrow::Type::STRING: + return odbcabstraction::CDataType_CHAR; + case arrow::Type::INT16: + return odbcabstraction::CDataType_SSHORT; + case arrow::Type::UINT16: + return odbcabstraction::CDataType_USHORT; + case arrow::Type::INT32: + return odbcabstraction::CDataType_SLONG; + case arrow::Type::UINT32: + return odbcabstraction::CDataType_ULONG; + case arrow::Type::FLOAT: + return odbcabstraction::CDataType_FLOAT; + case arrow::Type::DOUBLE: + return odbcabstraction::CDataType_DOUBLE; + case arrow::Type::BOOL: + return odbcabstraction::CDataType_BIT; + case arrow::Type::INT8: + return odbcabstraction::CDataType_STINYINT; + case arrow::Type::UINT8: + return odbcabstraction::CDataType_UTINYINT; + case arrow::Type::INT64: + return odbcabstraction::CDataType_SBIGINT; + case arrow::Type::UINT64: + return odbcabstraction::CDataType_UBIGINT; + case arrow::Type::BINARY: + return odbcabstraction::CDataType_BINARY; + case arrow::Type::DATE64: + case arrow::Type::DATE32: + return odbcabstraction::CDataType_DATE; + case arrow::Type::TIME64: + case arrow::Type::TIME32: + return odbcabstraction::CDataType_TIME; + case arrow::Type::TIMESTAMP: + return odbcabstraction::CDataType_TIMESTAMP; + default: + throw odbcabstraction::DriverException(std::string("Invalid type id: ") + std::to_string(type_id)); + } +} + +std::shared_ptr +CheckConversion(const arrow::Result &result) { + if (result.ok()) { + const arrow::Datum &datum = result.ValueOrDie(); + return datum.make_array(); + } else { + throw odbcabstraction::DriverException(result.status().message()); + } +} + +ArrayConvertTask GetConverter(arrow::Type::type original_type_id, + odbcabstraction::CDataType target_type) { + // The else statement has a convert the works for the most case of array + // conversion. In case, we find conversion that the default one can't handle + // we can include some additional if-else statement with the logic to handle + // it + if (original_type_id == arrow::Type::STRING && + target_type == odbcabstraction::CDataType_TIME) { + return [=](const std::shared_ptr &original_array) { + arrow::compute::StrptimeOptions options("%H:%M", arrow::TimeUnit::MICRO, false); + + auto converted_result = + arrow::compute::Strptime({original_array}, options); + auto first_converted_array = CheckConversion(converted_result); + + arrow::compute::CastOptions cast_options; + cast_options.to_type = time64(arrow::TimeUnit::MICRO); + return CheckConversion(arrow::compute::CallFunction( + "cast", {first_converted_array}, &cast_options)); + }; + } else if (original_type_id == arrow::Type::STRING && + target_type == odbcabstraction::CDataType_DATE) { + return [=](const std::shared_ptr &original_array) { + // The Strptime requires a date format. Using the ISO 8601 format + arrow::compute::StrptimeOptions options("%Y-%m-%d", arrow::TimeUnit::SECOND, + false); + + auto converted_result = + arrow::compute::Strptime({original_array}, options); + + auto first_converted_array = CheckConversion(converted_result); + arrow::compute::CastOptions cast_options; + cast_options.to_type = arrow::date64(); + return CheckConversion(arrow::compute::CallFunction( + "cast", {first_converted_array}, &cast_options)); + }; + } else { + // Default converter + return [=](const std::shared_ptr &original_array) { + const arrow::Type::type &target_arrow_type_id = + ConvertCToArrowType(target_type); + arrow::compute::CastOptions cast_options; + cast_options.to_type = GetDefaultDataTypeForTypeId(target_arrow_type_id); + + return CheckConversion(arrow::compute::CallFunction( + "cast", {original_array}, &cast_options)); + }; + } +} + + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index 7c514670b090a..844d5fc5c5305 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -27,6 +27,10 @@ namespace driver { namespace flight_sql { +typedef std::function< + std::shared_ptr(std::shared_ptr)> + ArrayConvertTask; + using arrow::util::optional; #ifdef WITH_IODBC @@ -93,5 +97,19 @@ std::string ConvertSqlPatternToRegexString(const std::string &pattern); boost::xpressive::sregex ConvertSqlPatternToRegex(const std::string &pattern); +bool NeedArrayConversion(arrow::Type::type original_type_id, + odbcabstraction::CDataType data_type); + +std::shared_ptr GetDefaultDataTypeForTypeId(arrow::Type::type type_id); + +arrow::Type::type ConvertCToArrowType(odbcabstraction::CDataType data_type); + +odbcabstraction::CDataType ConvertArrowTypeToC(arrow::Type::type type_id); + +std::shared_ptr CheckConversion(const arrow::Result &result); + +ArrayConvertTask GetConverter(arrow::Type::type original_type_id, + odbcabstraction::CDataType target_type); + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc index 28f6ad5c8f315..f759827f0c764 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc @@ -16,12 +16,42 @@ // under the License. #include "utils.h" +#include "arrow/testing/builder.h" #include #include "gtest/gtest.h" namespace driver { namespace flight_sql { +void TestArrayConversion(const std::vector& input, + odbcabstraction::CDataType c_type, + arrow::Type::type arrow_type) { + std::shared_ptr array; + arrow::ArrayFromVector(input, &array); + + auto converter = GetConverter(array->type_id(), + c_type); + auto converted_array = converter(array); + + ASSERT_EQ(converted_array->type_id(), arrow_type); + ASSERT_EQ(converted_array->length(), input.size()); +} + +TEST(Utils, StringToDateArray) { + TestArrayConversion({"2020-01-20", "2022-03-10"}, + odbcabstraction::CDataType_DATE, arrow::Type::DATE64); +} + +TEST(Utils, StringToTimeArray) { + TestArrayConversion({"10:00", "12:00"}, + odbcabstraction::CDataType_TIME, arrow::Type::TIME64); +} + +TEST(Utils, StringToTimeStampArray) { + TestArrayConversion({"2013-05-27 19:15:00", "2013-05-31 16:40:00"}, + odbcabstraction::CDataType_TIMESTAMP, arrow::Type::TIMESTAMP); +} + TEST(Utils, ConvertSqlPatternToRegexString) { ASSERT_EQ(std::string("XY"), ConvertSqlPatternToRegexString("XY")); ASSERT_EQ(std::string("X.Y"), ConvertSqlPatternToRegexString("X_Y")); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 397b7fc6a3012..21db5de23e7a1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -104,6 +104,7 @@ enum CDataType { CDataType_UBIGINT = ((-5) + (-22)), CDataType_BINARY = (-2), CDataType_NUMERIC = 2, + CDataType_DEFAULT = 99, }; enum Nullability { From deb0b932f98d8745ca56106015ebfcfcaabadd2a Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Mon, 30 May 2022 13:53:17 -0300 Subject: [PATCH 109/183] Add converter for the complex types Change-Id: I62d4e179bd2cd7f86f641231e7b86c48ac253a64 --- .../flight_sql_result_set_column.cc | 1 - .../flightsql-odbc/flight_sql/utils.cc | 34 +++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index 617722e5ef5fe..1f89799479d7f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -18,7 +18,6 @@ #include "flight_sql_result_set_column.h" #include #include "flight_sql_result_set.h" -#include "json_converter.h" #include "utils.h" #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 80a920a1cbb32..ffa4e480028b8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -21,10 +21,26 @@ #include #include #include +#include namespace driver { namespace flight_sql { +namespace { +bool IsComplexType(arrow::Type::type type_id) { + switch (type_id) { + case arrow::Type::LIST: + case arrow::Type::LARGE_LIST: + case arrow::Type::FIXED_SIZE_LIST: + case arrow::Type::MAP: + case arrow::Type::STRUCT: + return true; + default: + return false; + } +} +} + using namespace odbcabstraction; using arrow::util::make_optional; using arrow::util::nullopt; @@ -513,6 +529,12 @@ bool NeedArrayConversion(arrow::Type::type original_type_id, odbcabstraction::CD return data_type != odbcabstraction::CDataType_BINARY; case arrow::Type::DECIMAL128: return data_type != odbcabstraction::CDataType_NUMERIC; + case arrow::Type::LIST: + case arrow::Type::LARGE_LIST: + case arrow::Type::FIXED_SIZE_LIST: + case arrow::Type::MAP: + case arrow::Type::STRUCT: + return data_type == odbcabstraction::CDataType_CHAR || data_type == odbcabstraction::CDataType_WCHAR; default: throw odbcabstraction::DriverException(std::string("Invalid conversion")); } @@ -688,16 +710,24 @@ ArrayConvertTask GetConverter(arrow::Type::type original_type_id, return CheckConversion(arrow::compute::CallFunction( "cast", {first_converted_array}, &cast_options)); }; + } else if (IsComplexType(original_type_id) && + (target_type == odbcabstraction::CDataType_CHAR || + target_type == odbcabstraction::CDataType_WCHAR)) { + return [=](const std::shared_ptr &original_array) { + const auto &json_conversion_result = ConvertToJson(original_array); + ThrowIfNotOK(json_conversion_result.status()); + return json_conversion_result.ValueOrDie(); + }; } else { // Default converter return [=](const std::shared_ptr &original_array) { const arrow::Type::type &target_arrow_type_id = - ConvertCToArrowType(target_type); + ConvertCToArrowType(target_type); arrow::compute::CastOptions cast_options; cast_options.to_type = GetDefaultDataTypeForTypeId(target_arrow_type_id); return CheckConversion(arrow::compute::CallFunction( - "cast", {original_array}, &cast_options)); + "cast", {original_array}, &cast_options)); }; } } From fa12c37b5a014ac5499fd319fc6b2fcc678b6b17 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Wed, 18 May 2022 14:37:44 -0300 Subject: [PATCH 110/183] Partial support for query cancellation This adds partial support for query cancellation, it doesn't actually cancel the operation on server and will wait for Statement.Execute to finish (loading the first record batch) Change-Id: I6dc57eef249fb859c0d73b004bd4a9dee028a8c9 --- .../flightsql-odbc/flight_sql/flight_sql_result_set.cc | 10 ++++++++++ .../flightsql-odbc/flight_sql/flight_sql_result_set.h | 2 ++ .../flightsql-odbc/flight_sql/flight_sql_statement.cc | 5 +++++ .../flightsql-odbc/flight_sql/flight_sql_statement.h | 2 ++ .../flight_sql/flight_sql_stream_chunk_iterator.cc | 10 ++++++---- .../include/odbcabstraction/result_set.h | 3 +++ .../include/odbcabstraction/statement.h | 3 +++ 7 files changed, 31 insertions(+), 4 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index 1b054a81b89bb..f8f5c41d5869c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -134,6 +134,11 @@ void FlightSqlResultSet::Close() { current_chunk_.data = nullptr; } +void FlightSqlResultSet::Cancel() { + chunk_iterator_.Close(); + current_chunk_.data = nullptr; +} + bool FlightSqlResultSet::GetData(int column_n, int16_t target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) { @@ -156,6 +161,11 @@ bool FlightSqlResultSet::GetData(int column_n, int16_t target_type, std::shared_ptr FlightSqlResultSet::GetArrayForColumn(int column) { + if (!current_chunk_.data) { + // This may happen if query is cancelled right after SQLFetch and before SQLGetData. + throw DriverException("No RecordBatch loaded.", "24000"); + } + std::shared_ptr original_array = current_chunk_.data->column(column - 1); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index deccf1bb84185..64fe361915dc2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -76,6 +76,8 @@ class FlightSqlResultSet : public ResultSet { void Close() override; + void Cancel() override; + bool GetData(int column_n, int16_t target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index b9548921b6d2f..e07a867dbadfd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -293,5 +293,10 @@ odbcabstraction::Diagnostics &FlightSqlStatement::GetDiagnostics() { return diagnostics_; } +void FlightSqlStatement::Cancel() { + if (!current_result_set_) return; + current_result_set_->Cancel(); +} + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h index 453402d0ad824..7786380643762 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h @@ -86,6 +86,8 @@ class FlightSqlStatement : public odbcabstraction::Statement { std::shared_ptr GetTypeInfo_V3(int16_t data_type) override; odbcabstraction::Diagnostics &GetDiagnostics() override; + + void Cancel() override; }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc index 24dcf509a7716..3bfe21a7fc049 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc @@ -29,11 +29,11 @@ FlightStreamChunkIterator::FlightStreamChunkIterator( const arrow::flight::FlightCallOptions &call_options, const std::shared_ptr &flight_info) : closed_(false) { - const std::vector &vector = flight_info->endpoints(); + const std::vector &endpoints = flight_info->endpoints(); - stream_readers_.reserve(vector.size()); - for (int i = 0; i < vector.size(); ++i) { - auto result = flight_sql_client.DoGet(call_options, vector[0].ticket); + stream_readers_.reserve(endpoints.size()); + for (int i = 0; i < endpoints.size(); ++i) { + auto result = flight_sql_client.DoGet(call_options, endpoints[i].ticket); ThrowIfNotOK(result.status()); stream_readers_.push_back(std::move(result.ValueOrDie())); } @@ -44,6 +44,8 @@ FlightStreamChunkIterator::FlightStreamChunkIterator( FlightStreamChunkIterator::~FlightStreamChunkIterator() { Close(); } bool FlightStreamChunkIterator::GetNext(FlightStreamChunk *chunk) { + if (closed_) return false; + chunk->data = nullptr; while (stream_readers_it_ != stream_readers_.end()) { const auto &chunk_result = (*stream_readers_it_)->Next(); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h index 54c8954b07ef7..239bf88ee72b9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h @@ -42,6 +42,9 @@ class ResultSet { /// \brief Closes ResultSet, releasing any resources allocated by it. virtual void Close() = 0; + /// \brief Cancels ResultSet. + virtual void Cancel() = 0; + /// \brief Binds a column with a result buffer. The buffer will be filled with /// up to `GetMaxBatchSize()` values. /// diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h index 74fdc580b4387..7b557ec065d6e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h @@ -181,6 +181,9 @@ class Statement { /// \brief Gets the diagnostics for this statement. /// \return the diagnostics virtual Diagnostics& GetDiagnostics() = 0; + + /// \brief Cancels the processing of this statement. + virtual void Cancel() = 0; }; } // namespace odbcabstraction From bde860e7919fbd30d2e8f696706eae3a469759f6 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Fri, 27 May 2022 14:21:04 -0300 Subject: [PATCH 111/183] Fix FlightSqlStatement.GetTables behavior when passing "%" When passing "%" to CatalogName or SchemaName on SQLTables, catalogs and schemas list should be returned regardless of what is on TableType argument. Change-Id: I0f70aa93ab5d66383019c0e71c0b43215a2de955 --- .../flightsql-odbc/flight_sql/flight_sql_statement.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index e07a867dbadfd..1b1d4fe6435a2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -164,14 +164,12 @@ std::shared_ptr FlightSqlStatement::GetTables( if ((catalog_name && *catalog_name == "%") && (schema_name && schema_name->empty()) && - (table_name && table_name->empty()) && - (table_type && table_type->empty())) { + (table_name && table_name->empty())) { current_result_set_ = GetTablesForSQLAllCatalogs(column_names, call_options_, sql_client_, diagnostics_); } else if ((catalog_name && catalog_name->empty()) && (schema_name && *schema_name == "%") && - (table_name && table_name->empty()) && - (table_type && table_type->empty())) { + (table_name && table_name->empty())) { current_result_set_ = GetTablesForSQLAllDbSchemas( column_names, call_options_, sql_client_, schema_name, diagnostics_); } else if ((catalog_name && catalog_name->empty()) && From d5342f117528b7735400d624c45c11de09ec7471 Mon Sep 17 00:00:00 2001 From: "joy.cundy" Date: Thu, 19 May 2022 04:19:49 +0000 Subject: [PATCH 112/183] DX-50418: Implement Configuration Dialog Change-Id: If7d496734275c19d94fdf1d6070dfab640061401 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 13 + .../flight_sql/config/configuration.cc | 176 ++++++ .../config/connection_string_parser.cc | 114 ++++ .../flight_sql/flight_sql_connection.cc | 7 + .../flight_sql/flight_sql_connection.h | 4 + .../include/flight_sql/config/configuration.h | 77 +++ .../config/connection_string_parser.h | 79 +++ .../flight_sql/ui/add_property_window.h | 125 ++++ .../include/flight_sql/ui/custom_window.h | 115 ++++ .../flight_sql/ui/dsn_configuration_window.h | 226 +++++++ .../flight_sql/include/flight_sql/ui/window.h | 314 ++++++++++ .../flightsql-odbc/flight_sql/system_dsn.cc | 192 ++++++ .../flight_sql/ui/add_property_window.cc | 188 ++++++ .../flight_sql/ui/custom_window.cc | 119 ++++ .../flight_sql/ui/dsn_configuration_window.cc | 577 ++++++++++++++++++ .../flightsql-odbc/flight_sql/ui/window.cc | 384 ++++++++++++ 16 files changed, 2710 insertions(+) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/configuration.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/connection_string_parser.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/configuration.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/connection_string_parser.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/add_property_window.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/custom_window.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/dsn_configuration_window.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/window.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_dsn.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/add_property_window.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/custom_window.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index be858333d361e..efb85d6521ade 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -22,6 +22,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) include_directories( include + include/flight_sql ${CMAKE_SOURCE_DIR}/odbcabstraction/include) if (DEFINED CMAKE_TOOLCHAIN_FILE) @@ -179,6 +180,18 @@ set(ARROW_ODBC_SPI_SOURCES system_trust_store.cc utils.cc) +if (WIN32) + include_directories(flight_sql/include) + + list(APPEND ARROW_ODBC_SPI_SOURCES + 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() if (MSVC) set(CMAKE_CXX_FLAGS_RELEASE "/MD") diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/configuration.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/configuration.cc new file mode 100644 index 0000000000000..4c876f125c1c2 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/configuration.cc @@ -0,0 +1,176 @@ +/* + * 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 "config/configuration.h" + +#include "flight_sql_connection.h" +#include +#include +#include +#include +#include + +namespace driver { +namespace flight_sql { +namespace config { + +static const std::string DEFAULT_DSN = "Apache Arrow Flight SQL"; +static const std::string DEFAULT_ENABLE_ENCRYPTION = TRUE_STR; +static const std::string DEFAULT_USE_CERT_STORE = TRUE_STR; +static const std::string DEFAULT_DISABLE_CERT_VERIFICATION = FALSE_STR; + +namespace { +std::string ReadDsnString(const std::string& dsn, const std::string& key, const std::string& dflt = "") +{ + #define BUFFER_SIZE (1024) + std::vector buf(BUFFER_SIZE); + + int ret = SQLGetPrivateProfileString(dsn.c_str(), key.c_str(), dflt.c_str(), buf.data(), static_cast(buf.size()), "ODBC.INI"); + + if (ret > BUFFER_SIZE) + { + // If there wasn't enough space, try again with the right size buffer. + buf.resize(ret + 1); + ret = SQLGetPrivateProfileString(dsn.c_str(), key.c_str(), dflt.c_str(), buf.data(), static_cast(buf.size()), "ODBC.INI"); + } + + return std::string(buf.data(), ret); +} + +void RemoveAllKnownKeys(std::vector& keys) { + // Remove all known DSN keys from the passed in set of keys, case insensitively. + keys.erase(std::remove_if(keys.begin(), keys.end(), [&](auto& x) { + return std::find_if(FlightSqlConnection::ALL_KEYS.begin(), FlightSqlConnection::ALL_KEYS.end(), [&](auto& s) { + return boost::iequals(x, s);}) != FlightSqlConnection::ALL_KEYS.end(); + }), keys.end()); +} + +std::vector ReadAllKeys(const std::string& dsn) +{ + std::vector buf(BUFFER_SIZE); + + int ret = SQLGetPrivateProfileString(dsn.c_str(), NULL, "", buf.data(), static_cast(buf.size()), "ODBC.INI"); + + if (ret > BUFFER_SIZE) + { + // If there wasn't enough space, try again with the right size buffer. + buf.resize(ret + 1); + ret = SQLGetPrivateProfileString(dsn.c_str(), NULL, "", buf.data(), static_cast(buf.size()), "ODBC.INI"); + } + + // When you pass NULL to SQLGetPrivateProfileString it gives back a \0 delimited list of all the keys. + // The below loop simply tokenizes all the keys and places them into a vector. + std::vector keys; + char* begin = buf.data(); + while (begin && *begin != '\0') { + char* cur; + for (cur = begin; *cur != '\0'; ++cur); + keys.emplace_back(begin, cur); + begin = ++cur; + } + return keys; +} +} + +Configuration::Configuration() +{ + // No-op. +} + +Configuration::~Configuration() +{ + // No-op. +} + +void Configuration::LoadDefaults() +{ + Set(FlightSqlConnection::DSN, DEFAULT_DSN); + Set(FlightSqlConnection::USE_ENCRYPTION, DEFAULT_ENABLE_ENCRYPTION); + Set(FlightSqlConnection::USE_SYSTEM_TRUST_STORE, DEFAULT_USE_CERT_STORE); + Set(FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, DEFAULT_DISABLE_CERT_VERIFICATION); +} + +void Configuration::LoadDsn(const std::string& dsn) +{ + Set(FlightSqlConnection::DSN, dsn); + Set(FlightSqlConnection::HOST, ReadDsnString(dsn, FlightSqlConnection::HOST)); + Set(FlightSqlConnection::PORT, ReadDsnString(dsn, FlightSqlConnection::PORT)); + Set(FlightSqlConnection::TOKEN, ReadDsnString(dsn, FlightSqlConnection::TOKEN)); + Set(FlightSqlConnection::UID, ReadDsnString(dsn, FlightSqlConnection::UID)); + Set(FlightSqlConnection::PWD, ReadDsnString(dsn, FlightSqlConnection::PWD)); + Set(FlightSqlConnection::USE_ENCRYPTION, + ReadDsnString(dsn, FlightSqlConnection::USE_ENCRYPTION, DEFAULT_ENABLE_ENCRYPTION)); + Set(FlightSqlConnection::TRUSTED_CERTS, ReadDsnString(dsn, FlightSqlConnection::TRUSTED_CERTS)); + Set(FlightSqlConnection::USE_SYSTEM_TRUST_STORE, + ReadDsnString(dsn, FlightSqlConnection::USE_SYSTEM_TRUST_STORE, DEFAULT_USE_CERT_STORE)); + Set(FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, + ReadDsnString(dsn, FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, DEFAULT_DISABLE_CERT_VERIFICATION)); + + auto customKeys = ReadAllKeys(dsn); + RemoveAllKnownKeys(customKeys); + for (auto key : customKeys) { + Set(key, ReadDsnString(dsn, key)); + } +} + +void Configuration::Clear() +{ + this->properties.clear(); +} + +bool Configuration::IsSet(const std::string& key) const +{ + return 0 != this->properties.count(key); +} + +const std::string& Configuration::Get(const std::string& key) const +{ + const auto itr = this->properties.find(key); + if (itr == this->properties.cend()) { + static const std::string empty(""); + return empty; + } + return itr->second; +} + +void Configuration::Set(const std::string& key, const std::string& value) +{ + const std::string copy = boost::trim_copy(value); + if (!copy.empty()) { + this->properties[key] = value; + } +} + +const driver::odbcabstraction::Connection::ConnPropertyMap& Configuration::GetProperties() const +{ + return this->properties; +} + +std::vector Configuration::GetCustomKeys() const +{ + driver::odbcabstraction::Connection::ConnPropertyMap copyProps(properties); + for (auto& key : FlightSqlConnection::ALL_KEYS) { + copyProps.erase(key); + } + std::vector keys; + boost::copy(copyProps | boost::adaptors::map_keys, std::back_inserter(keys)); + return keys; +} + +} // namespace config +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/connection_string_parser.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/connection_string_parser.cc new file mode 100644 index 0000000000000..a69e556991a88 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/connection_string_parser.cc @@ -0,0 +1,114 @@ +/* + * 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 "config/connection_string_parser.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace driver { +namespace flight_sql { +namespace config { + +ConnectionStringParser::ConnectionStringParser(Configuration& cfg): + cfg(cfg) +{ + // No-op. +} + +ConnectionStringParser::~ConnectionStringParser() +{ + // No-op. +} + +void ConnectionStringParser::ParseConnectionString(const char* str, size_t len, char delimiter) +{ + std::string connect_str(str, len); + + while (connect_str.rbegin() != connect_str.rend() && *connect_str.rbegin() == 0) + connect_str.erase(connect_str.size() - 1); + + while (!connect_str.empty()) + { + size_t attr_begin = connect_str.rfind(delimiter); + + if (attr_begin == std::string::npos) + attr_begin = 0; + else + ++attr_begin; + + size_t attr_eq_pos = connect_str.rfind('='); + + if (attr_eq_pos == std::string::npos) + attr_eq_pos = 0; + + if (attr_begin < attr_eq_pos) + { + const char* key_begin = connect_str.data() + attr_begin; + const char* key_end = connect_str.data() + attr_eq_pos; + std::string key(key_begin, key_end); + boost::algorithm::trim(key); + + const char* value_begin = connect_str.data() + attr_eq_pos + 1; + const char* value_end = connect_str.data() + connect_str.size(); + std::string value(value_begin, value_end); + boost::algorithm::trim(value); + + if (value[0] == '{' && value[value.size() - 1] == '}') { + value = value.substr(1, value.size() - 2); + } + + cfg.Set(key, value); + } + + if (!attr_begin) + break; + + connect_str.erase(attr_begin - 1); + } +} + +void ConnectionStringParser::ParseConnectionString(const std::string& str) +{ + ParseConnectionString(str.data(), str.size(), ';'); +} + +void ConnectionStringParser::ParseConfigAttributes(const char* str) +{ + size_t len = 0; + + // Getting list length. List is terminated by two '\0'. + while (str[len] || str[len + 1]) + ++len; + + ++len; + + ParseConnectionString(str, len, '\0'); +} + +} // namespace config +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 3f3290f2e46b6..809fffc3ed300 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -55,6 +55,8 @@ using driver::odbcabstraction::DriverException; using driver::odbcabstraction::OdbcVersion; using driver::odbcabstraction::Statement; +const std::string FlightSqlConnection::DSN = "dsn"; +const std::string FlightSqlConnection::DRIVER = "driver"; const std::string FlightSqlConnection::HOST = "host"; const std::string FlightSqlConnection::PORT = "port"; const std::string FlightSqlConnection::USER = "user"; @@ -67,6 +69,11 @@ const std::string FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION = "disab const std::string FlightSqlConnection::TRUSTED_CERTS = "trustedCerts"; const std::string FlightSqlConnection::USE_SYSTEM_TRUST_STORE = "useSystemTrustStore"; +const std::vector FlightSqlConnection::ALL_KEYS = { + FlightSqlConnection::DSN, FlightSqlConnection::DRIVER, FlightSqlConnection::HOST, FlightSqlConnection::PORT, + FlightSqlConnection::TOKEN, FlightSqlConnection::UID, FlightSqlConnection::PWD, FlightSqlConnection::USE_ENCRYPTION, + FlightSqlConnection::TRUSTED_CERTS, FlightSqlConnection::USE_SYSTEM_TRUST_STORE, FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION }; + namespace { #if _WIN32 || _WIN64 diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 7910f74b8ec35..95a5da1adc994 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -21,6 +21,7 @@ #include #include +#include #include "get_info_cache.h" @@ -49,6 +50,9 @@ class FlightSqlConnection : public odbcabstraction::Connection { bool closed_; public: + static const std::vector ALL_KEYS; + static const std::string DSN; + static const std::string DRIVER; static const std::string HOST; static const std::string PORT; static const std::string USER; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/configuration.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/configuration.h new file mode 100644 index 0000000000000..6e6c52bdb5fe4 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/configuration.h @@ -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. + */ + +#pragma once + +#include +#include "winuser.h" +#include +#include +#include + +namespace driver { +namespace flight_sql { +namespace config { + +#define TRUE_STR "true" +#define FALSE_STR "false" + +/** + * ODBC configuration abstraction. + */ +class Configuration +{ +public: + /** + * Default constructor. + */ + Configuration(); + + /** + * Destructor. + */ + ~Configuration(); + + /** + * Convert configure to connect string. + * + * @return Connect string. + */ + std::string ToConnectString() const; + + void LoadDefaults(); + void LoadDsn(const std::string& dsn); + + void Clear(); + bool IsSet(const std::string& key) const; + const std::string& Get(const std::string& key) const; + void Set(const std::string& key, const std::string& value); + + /** + * Get properties map. + */ + const driver::odbcabstraction::Connection::ConnPropertyMap& GetProperties() const; + + std::vector GetCustomKeys() const; + +private: + driver::odbcabstraction::Connection::ConnPropertyMap properties; +}; + +} // namespace config +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/connection_string_parser.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/connection_string_parser.h new file mode 100644 index 0000000000000..fa65cfb1743dd --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/connection_string_parser.h @@ -0,0 +1,79 @@ +/* + * 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. + */ + +#pragma once + +#include + +#include "config/configuration.h" + +namespace driver { +namespace flight_sql { +namespace config { + +/** + * ODBC configuration parser abstraction. + */ +class ConnectionStringParser +{ +public: + /** + * Constructor. + * + * @param cfg Configuration. + */ + explicit ConnectionStringParser(Configuration& cfg); + + /** + * Destructor. + */ + ~ConnectionStringParser(); + + /** + * Parse connect string. + * + * @param str String to parse. + * @param len String length. + * @param delimiter delimiter. + */ + void ParseConnectionString(const char* str, size_t len, char delimiter); + + /** + * Parse connect string. + * + * @param str String to parse. + */ + void ParseConnectionString(const std::string& str); + + /** + * Parse config attributes. + * + * @param str String to parse. + */ + void ParseConfigAttributes(const char* str); + +private: + ConnectionStringParser(const ConnectionStringParser& parser) = delete; + ConnectionStringParser& operator=(const ConnectionStringParser&) = delete; + + /** Configuration. */ + Configuration& cfg; +}; + +} // namespace config +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/add_property_window.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/add_property_window.h new file mode 100644 index 0000000000000..1f77cee42e80b --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/add_property_window.h @@ -0,0 +1,125 @@ +/* + * 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. + */ + +#pragma once + +#include +#include "ui/custom_window.h" + +namespace driver { +namespace flight_sql { +namespace config { +/** + * Add property window class. + */ +class AddPropertyWindow : public CustomWindow +{ + /** + * Children windows ids. + */ + struct ChildId + { + enum Type + { + KEY_EDIT = 100, + KEY_LABEL, + VALUE_EDIT, + VALUE_LABEL, + OK_BUTTON, + CANCEL_BUTTON + }; + }; + +public: + /** + * Constructor. + * + * @param parent Parent window handle. + */ + explicit AddPropertyWindow(Window* parent); + + /** + * Destructor. + */ + virtual ~AddPropertyWindow(); + + /** + * Create window in the center of the parent window. + */ + void Create(); + + /** + * @copedoc ignite::odbc::system::ui::CustomWindow::OnCreate + */ + virtual void OnCreate() override; + + /** + * @copedoc ignite::odbc::system::ui::CustomWindow::OnMessage + */ + virtual bool OnMessage(UINT msg, WPARAM wParam, LPARAM lParam) override; + + /** + * Get the property from the dialog. + * + * @return true if the dialog was OK'd, false otherwise. + */ + bool GetProperty(std::string& key, std::string& value); + +private: + /** + * Create property edit boxes. + * + * @param posX X position. + * @param posY Y position. + * @param sizeX Width. + * @return Size by Y. + */ + int CreateEdits(int posX, int posY, int sizeX); + + void CheckEnableOk(); + + std::vector > labels; + + /** Ok button. */ + std::unique_ptr okButton; + + /** Cancel button. */ + std::unique_ptr cancelButton; + + std::unique_ptr keyEdit; + + std::unique_ptr valueEdit; + + std::string key; + + std::string value; + + /** Window width. */ + int width; + + /** Window height. */ + int height; + + /** Flag indicating whether OK option was selected. */ + bool accepted; + + bool isInitialized; +}; + +} // namespace config +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/custom_window.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/custom_window.h new file mode 100644 index 0000000000000..d0b5f46a7f797 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/custom_window.h @@ -0,0 +1,115 @@ +/* + * 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. + */ + +#pragma once + +#include "ui/window.h" + +namespace driver { +namespace flight_sql { +namespace config { +/** + * Application execution result. + */ +struct Result +{ + enum Type + { + OK, + CANCEL + }; +}; + +/** + * Process UI messages in current thread. + * Blocks until quit message has been received. + * + * @param window Main window. + * @return Application execution result. + */ +Result::Type ProcessMessages(Window& window); + +/** + * Window class. + */ +class CustomWindow : public Window +{ +public: + // Window margin size. + enum { MARGIN = 10 }; + + // Standard interval between UI elements. + enum { INTERVAL = 10 }; + + // Standard row height. + enum { ROW_HEIGHT = 20 }; + + // Standard button width. + enum { BUTTON_WIDTH = 80 }; + + // Standard button height. + enum { BUTTON_HEIGHT = 25 }; + + /** + * Constructor. + * + * @param parent Parent window. + * @param className Window class name. + * @param title Window title. + */ + CustomWindow(Window* parent, const char* className, const char* title); + + /** + * Destructor. + */ + virtual ~CustomWindow(); + + /** + * Callback which is called upon receiving new message. + * Pure virtual. Should be defined by user. + * + * @param msg Message. + * @param wParam Word-sized parameter. + * @param lParam Long parameter. + * @return Should return true if the message has been + * processed by the handler and false otherwise. + */ + virtual bool OnMessage(UINT msg, WPARAM wParam, LPARAM lParam) = 0; + + /** + * Callback that is called upon window creation. + */ + virtual void OnCreate() = 0; + +private: +// IGNITE_NO_COPY_ASSIGNMENT(CustomWindow) + + /** + * Static callback. + * + * @param hwnd Window handle. + * @param msg Message. + * @param wParam Word-sized parameter. + * @param lParam Long parameter. + * @return Operation result. + */ + static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +}; + +} // namespace config +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/dsn_configuration_window.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/dsn_configuration_window.h new file mode 100644 index 0000000000000..3191b3aac83d0 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/dsn_configuration_window.h @@ -0,0 +1,226 @@ +/* + * 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. + */ + +#pragma once + +#include "config/configuration.h" +#include "ui/custom_window.h" + +namespace driver { +namespace flight_sql { +namespace config { +/** + * DSN configuration window class. + */ +class DsnConfigurationWindow : public CustomWindow +{ + /** + * Children windows ids. + */ + struct ChildId + { + enum Type + { + CONNECTION_SETTINGS_GROUP_BOX = 100, + AUTH_SETTINGS_GROUP_BOX, + ENCRYPTION_SETTINGS_GROUP_BOX, + NAME_EDIT, + NAME_LABEL, + SERVER_EDIT, + SERVER_LABEL, + PORT_EDIT, + PORT_LABEL, + AUTH_TYPE_LABEL, + AUTH_TYPE_COMBOBOX, + USER_LABEL, + USER_EDIT, + PASSWORD_LABEL, + PASSWORD_EDIT, + AUTH_TOKEN_LABEL, + AUTH_TOKEN_EDIT, + ENABLE_ENCRYPTION_LABEL, + ENABLE_ENCRYPTION_CHECKBOX, + CERTIFICATE_LABEL, + CERTIFICATE_EDIT, + CERTIFICATE_BROWSE_BUTTON, + USE_SYSTEM_CERT_STORE_LABEL, + USE_SYSTEM_CERT_STORE_CHECKBOX, + DISABLE_CERT_VERIFICATION_LABEL, + DISABLE_CERT_VERIFICATION_CHECKBOX, + PROPERTY_GROUP_BOX, + PROPERTY_LIST, + ADD_BUTTON, + DELETE_BUTTON, + TAB_CONTROL, + OK_BUTTON, + CANCEL_BUTTON + }; + }; + +public: + /** + * Constructor. + * + * @param parent Parent window handle. + */ + DsnConfigurationWindow(Window* parent, config::Configuration& config); + + /** + * Destructor. + */ + virtual ~DsnConfigurationWindow(); + + /** + * Create window in the center of the parent window. + */ + void Create(); + + /** + * @copedoc ignite::odbc::system::ui::CustomWindow::OnCreate + */ + virtual void OnCreate() override; + + /** + * @copedoc ignite::odbc::system::ui::CustomWindow::OnMessage + */ + virtual bool OnMessage(UINT msg, WPARAM wParam, LPARAM lParam) override; + +private: + /** + * Create connection settings group box. + * + * @param posX X position. + * @param posY Y position. + * @param sizeX Width. + * @return Size by Y. + */ + int CreateConnectionSettingsGroup(int posX, int posY, int sizeX); + + /** + * Create aythentication settings group box. + * + * @param posX X position. + * @param posY Y position. + * @param sizeX Width. + * @return Size by Y. + */ + int CreateAuthSettingsGroup(int posX, int posY, int sizeX); + + /** + * Create Encryption settings group box. + * + * @param posX X position. + * @param posY Y position. + * @param sizeX Width. + * @return Size by Y. + */ + int CreateEncryptionSettingsGroup(int posX, int posY, int sizeX); + + /** + * Create advanced properties group box. + * + * @param posX X position. + * @param posY Y position. + * @param sizeX Width. + * @return Size by Y. + */ + int CreatePropertiesGroup(int posX, int posY, int sizeX); + + void SelectTab(int tabIndex); + + void CheckEnableOk(); + + void CheckAuthType(); + + void SaveParameters(); + + /** Window width. */ + int width; + + /** Window height. */ + int height; + + std::unique_ptr tabControl; + + std::unique_ptr commonContent; + + std::unique_ptr advancedContent; + + /** Connection settings group box. */ + std::unique_ptr connectionSettingsGroupBox; + + /** Authentication settings group box. */ + std::unique_ptr authSettingsGroupBox; + + /** Encryption settings group box. */ + std::unique_ptr encryptionSettingsGroupBox; + + std::vector > labels; + + /** Ok button. */ + std::unique_ptr okButton; + + /** Cancel button. */ + std::unique_ptr cancelButton; + + /** DSN name edit field. */ + std::unique_ptr nameEdit; + + std::unique_ptr serverEdit; + + std::unique_ptr portEdit; + + std::unique_ptr authTypeComboBox; + + /** User edit. */ + std::unique_ptr userEdit; + + /** Password edit. */ + std::unique_ptr passwordEdit; + + std::unique_ptr authTokenEdit; + + std::unique_ptr enableEncryptionCheckBox; + + std::unique_ptr certificateEdit; + + std::unique_ptr certificateBrowseButton; + + std::unique_ptr useSystemCertStoreCheckBox; + + std::unique_ptr disableCertVerificationCheckBox; + + std::unique_ptr propertyGroupBox; + + std::unique_ptr propertyList; + + std::unique_ptr addButton; + + std::unique_ptr deleteButton; + + /** Configuration. */ + Configuration& config; + + /** Flag indicating whether OK option was selected. */ + bool accepted; + + bool isInitialized; +}; + +} // namespace config +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/window.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/window.h new file mode 100644 index 0000000000000..addb800d9e751 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/window.h @@ -0,0 +1,314 @@ +/* + * 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. + */ + +#pragma once + +#include +#include +#include + +namespace driver { +namespace flight_sql { +namespace config { + +/** + * Get handle for the current module. + * + * @return Handle for the current module. + */ +HINSTANCE GetHInstance(); + +/** + * Window class. + */ +class Window +{ +public: + /** + * Constructor for a new window that is going to be created. + * + * @param parent Parent window handle. + * @param className Window class name. + * @param title Window title. + * @param callback Event processing function. + */ + Window(Window* parent, const char* className, const char* title); + + /** + * Constructor for the existing window. + * + * @param handle Window handle. + */ + explicit Window(HWND handle); + + /** + * Destructor. + */ + virtual ~Window(); + + /** + * Create window. + * + * @param style Window style. + * @param posX Window x position. + * @param posY Window y position. + * @param width Window width. + * @param height Window height. + * @param id ID for child window. + */ + void Create(DWORD style, int posX, int posY, int width, int height, int id); + + /** + * Create child tab controlwindow. + * + * @param id ID to be assigned to the created window. + * @return Auto pointer containing new window. + */ + std::unique_ptr CreateTabControl(int id); + + /** + * Create child list view window. + * + * @param posX Position by X coordinate. + * @param posY Position by Y coordinate. + * @param sizeX Size by X coordinate. + * @param sizeY Size by Y coordinate. + * @param id ID to be assigned to the created window. + * @return Auto pointer containing new window. + */ + std::unique_ptr CreateList(int posX, int posY, + int sizeX, int sizeY, int id); + + /** + * Create child group box window. + * + * @param posX Position by X coordinate. + * @param posY Position by Y coordinate. + * @param sizeX Size by X coordinate. + * @param sizeY Size by Y coordinate. + * @param title Title. + * @param id ID to be assigned to the created window. + * @return Auto pointer containing new window. + */ + std::unique_ptr CreateGroupBox(int posX, int posY, + int sizeX, int sizeY, const char* title, int id); + + /** + * Create child label window. + * + * @param posX Position by X coordinate. + * @param posY Position by Y coordinate. + * @param sizeX Size by X coordinate. + * @param sizeY Size by Y coordinate. + * @param title Title. + * @param id ID to be assigned to the created window. + * @return Auto pointer containing new window. + */ + std::unique_ptr CreateLabel(int posX, int posY, + int sizeX, int sizeY, const char* title, int id); + + /** + * Create child Edit window. + * + * @param posX Position by X coordinate. + * @param posY Position by Y coordinate. + * @param sizeX Size by X coordinate. + * @param sizeY Size by Y coordinate. + * @param title Title. + * @param id ID to be assigned to the created window. + * @return Auto pointer containing new window. + */ + std::unique_ptr CreateEdit(int posX, int posY, + int sizeX, int sizeY, const char* title, int id, int style = 0); + + /** + * Create child button window. + * + * @param posX Position by X coordinate. + * @param posY Position by Y coordinate. + * @param sizeX Size by X coordinate. + * @param sizeY Size by Y coordinate. + * @param title Title. + * @param id ID to be assigned to the created window. + * @return Auto pointer containing new window. + */ + std::unique_ptr CreateButton(int posX, int posY, + int sizeX, int sizeY, const char* title, int id, int style = 0); + + /** + * Create child CheckBox window. + * + * @param posX Position by X coordinate. + * @param posY Position by Y coordinate. + * @param sizeX Size by X coordinate. + * @param sizeY Size by Y coordinate. + * @param title Title. + * @param id ID to be assigned to the created window. + * @return Auto pointer containing new window. + */ + std::unique_ptr CreateCheckBox(int posX, int posY, + int sizeX, int sizeY, const char* title, int id, bool state); + + /** + * Create child ComboBox window. + * + * @param posX Position by X coordinate. + * @param posY Position by Y coordinate. + * @param sizeX Size by X coordinate. + * @param sizeY Size by Y coordinate. + * @param title Title. + * @param id ID to be assigned to the created window. + * @return Auto pointer containing new window. + */ + std::unique_ptr CreateComboBox(int posX, int posY, + int sizeX, int sizeY, const char* title, int id); + + /** + * Show window. + */ + void Show(); + + /** + * Update window. + */ + void Update(); + + /** + * Destroy window. + */ + void Destroy(); + + /** + * Get window handle. + * + * @return Window handle. + */ + HWND GetHandle() const + { + return handle; + } + + void SetVisible(bool isVisible); + + void ListAddColumn(const std::string& name, int index, int width); + + void ListAddItem(const std::vector& items); + + void ListDeleteSelectedItem(); + + std::vector > ListGetAll(); + + void AddTab(const std::string& name, int index); + + bool IsTextEmpty() const; + + /** + * Get window text. + * + * @param text Text. + */ + void GetText(std::string& text) const; + + /** + * Set window text. + * + * @param text Text. + */ + void SetText(const std::string& text) const; + + /** + * Get CheckBox state. + * + * @param True if checked. + */ + bool IsChecked() const; + + /** + * Set CheckBox state. + * + * @param state True if checked. + */ + void SetChecked(bool state); + + /** + * Add string. + * + * @param str String. + */ + void AddString(const std::string& str); + + /** + * Set current ComboBox selection. + * + * @param idx List index. + */ + void SetSelection(int idx); + + /** + * Get current ComboBox selection. + * + * @return idx List index. + */ + int GetSelection() const; + + /** + * Set enabled. + * + * @param enabled Enable flag. + */ + void SetEnabled(bool enabled); + + /** + * Check if the window is enabled. + * + * @return True if enabled. + */ + bool IsEnabled() const; + +protected: + /** + * Set window handle. + * + * @param value Window handle. + */ + void SetHandle(HWND value) + { + handle = value; + } + + /** Window class name. */ + std::string className; + + /** Window title. */ + std::string title; + + /** Window handle. */ + HWND handle; + + /** Window parent. */ + Window* parent; + + /** Specifies whether window has been created by the thread and needs destruction. */ + bool created; + +private: + Window(const Window& window) = delete; +}; + +} // namespace config +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_dsn.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_dsn.cc new file mode 100644 index 0000000000000..86b3ee419486f --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_dsn.cc @@ -0,0 +1,192 @@ +/* + * 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 "flight_sql_connection.h" +#include "config/configuration.h" +#include "config/connection_string_parser.h" +#include "ui/window.h" +#include "ui/dsn_configuration_window.h" +#include +#include +#include + +#include +#include +#include +#include + +using namespace std; +using namespace driver::flight_sql; +using namespace driver::flight_sql::config; + +BOOL CALLBACK ConfigDriver( + HWND hwndParent, + WORD fRequest, + LPCSTR lpszDriver, + LPCSTR lpszArgs, + LPSTR lpszMsg, + WORD cbMsgMax, + WORD* pcbMsgOut) { + return false; +} + +bool DisplayConnectionWindow(void* windowParent, Configuration& config) +{ + HWND hwndParent = (HWND)windowParent; + + if (!hwndParent) + return true; + + try + { + Window parent(hwndParent); + DsnConfigurationWindow window(&parent, config); + + window.Create(); + + window.Show(); + window.Update(); + + return ProcessMessages(window) == Result::OK; + } + catch (driver::odbcabstraction::DriverException& err) + { + std::stringstream buf; + buf << "Message: " << err.GetMessageText() << ", Code: " << err.GetNativeError(); + std::string message = buf.str(); + MessageBox(NULL, message.c_str(), "Error!", MB_ICONEXCLAMATION | MB_OK); + + SQLPostInstallerError(err.GetNativeError(), err.GetMessageText().c_str()); + } + + return false; +} + +void PostLastInstallerError() { + + #define BUFFER_SIZE (1024) + DWORD code; + char msg[BUFFER_SIZE]; + SQLInstallerError(1, &code, msg, BUFFER_SIZE, NULL); + + std::stringstream buf; + buf << "Message: \"" << msg << "\", Code: " << code; + std::string errorMsg = buf.str(); + + MessageBox(NULL, errorMsg.c_str(), "Error!", MB_ICONEXCLAMATION | MB_OK); + SQLPostInstallerError(code, errorMsg.c_str()); +} + +/** + * Unregister specified DSN. + * + * @param dsn DSN name. + * @return True on success and false on fail. + */ +bool UnregisterDsn(const std::string& dsn) +{ + if (SQLRemoveDSNFromIni(dsn.c_str())) { + return true; + } + + PostLastInstallerError(); + return false; +} + +/** + * Register DSN with specified configuration. + * + * @param config Configuration. + * @param driver Driver. + * @return True on success and false on fail. + */ +bool RegisterDsn(const Configuration& config, LPCSTR driver) +{ + const std::string& dsn = config.Get(FlightSqlConnection::DSN); + + if (!SQLWriteDSNToIni(dsn.c_str(), driver)) + { + PostLastInstallerError(); + return false; + } + + const auto& map = config.GetProperties(); + for (auto it = map.begin(); it != map.end(); ++it) + { + const std::string& key = it->first; + if (boost::iequals(FlightSqlConnection::DSN, key) || boost::iequals(FlightSqlConnection::DRIVER, key)) { + continue; + } + + if (!SQLWritePrivateProfileString(dsn.c_str(), key.c_str(), it->second.c_str(), "ODBC.INI")) { + PostLastInstallerError(); + return false; + } + } + + return true; +} + +BOOL INSTAPI ConfigDSN(HWND hwndParent, WORD req, LPCSTR driver, LPCSTR attributes) +{ + Configuration config; + ConnectionStringParser parser(config); + parser.ParseConfigAttributes(attributes); + + switch (req) + { + case ODBC_ADD_DSN: + { + config.LoadDefaults(); + if (!DisplayConnectionWindow(hwndParent, config) || !RegisterDsn(config, driver)) + return FALSE; + + break; + } + + case ODBC_CONFIG_DSN: + { + const std::string& dsn = config.Get(FlightSqlConnection::DSN); + if (!SQLValidDSN(dsn.c_str())) + return FALSE; + + Configuration loaded(config); + loaded.LoadDsn(dsn); + + if (!DisplayConnectionWindow(hwndParent, loaded) || !UnregisterDsn(dsn.c_str()) || !RegisterDsn(loaded, driver)) + return FALSE; + + break; + } + + case ODBC_REMOVE_DSN: + { + const std::string& dsn = config.Get(FlightSqlConnection::DSN); + if (!SQLValidDSN(dsn.c_str()) || !UnregisterDsn(dsn)) + return FALSE; + + break; + } + + default: + return FALSE; + } + + return TRUE; +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/add_property_window.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/add_property_window.cc new file mode 100644 index 0000000000000..0fe9b789b47a2 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/add_property_window.cc @@ -0,0 +1,188 @@ +/* + * 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 "ui/add_property_window.h" + +#include +#include +#include +#include + +#include "ui/custom_window.h" +#include "ui/window.h" +#include + +namespace driver { +namespace flight_sql { +namespace config { + +AddPropertyWindow::AddPropertyWindow(Window* parent) : + CustomWindow(parent, "AddProperty", "Add Property"), + width(300), + height(120), + accepted(false), + isInitialized(false) +{ + // No-op. +} + +AddPropertyWindow::~AddPropertyWindow() +{ + // No-op. +} + +void AddPropertyWindow::Create() +{ + // Finding out parent position. + RECT parentRect; + GetWindowRect(parent->GetHandle(), &parentRect); + + // Positioning window to the center of parent window. + const int posX = parentRect.left + (parentRect.right - parentRect.left - width) / 2; + const int posY = parentRect.top + (parentRect.bottom - parentRect.top - height) / 2; + + RECT desiredRect = { posX, posY, posX + width, posY + height }; + AdjustWindowRect(&desiredRect, WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, FALSE); + + Window::Create(WS_OVERLAPPED | WS_SYSMENU, desiredRect.left, desiredRect.top, + desiredRect.right - desiredRect.left, desiredRect.bottom - desiredRect.top, 0); + + if (!handle) + { + std::stringstream buf; + buf << "Can not create window, error code: " << GetLastError(); + throw odbcabstraction::DriverException(buf.str()); + } +} + +bool AddPropertyWindow::GetProperty(std::string& key, std::string& value) +{ + if (accepted) + { + key = this->key; + value = this->value; + return true; + } + return false; +} + +void AddPropertyWindow::OnCreate() +{ + int groupPosY = MARGIN; + int groupSizeY = width - 2 * MARGIN; + + groupPosY += INTERVAL + CreateEdits(MARGIN, groupPosY, groupSizeY); + + int cancelPosX = width - MARGIN - BUTTON_WIDTH; + int okPosX = cancelPosX - INTERVAL - BUTTON_WIDTH; + + okButton = CreateButton(okPosX, groupPosY, BUTTON_WIDTH, BUTTON_HEIGHT, "Ok", ChildId::OK_BUTTON, BS_DEFPUSHBUTTON); + cancelButton = CreateButton(cancelPosX, groupPosY, BUTTON_WIDTH, BUTTON_HEIGHT, + "Cancel", ChildId::CANCEL_BUTTON); + isInitialized = true; + CheckEnableOk(); +} + +int AddPropertyWindow::CreateEdits(int posX, int posY, int sizeX) +{ + enum { LABEL_WIDTH = 30 }; + + const int editSizeX = sizeX - LABEL_WIDTH - INTERVAL; + const int editPosX = posX + LABEL_WIDTH + INTERVAL; + + int rowPos = posY; + + labels.push_back(CreateLabel(posX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Key:", ChildId::KEY_LABEL)); + keyEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, "", ChildId::KEY_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + labels.push_back(CreateLabel(posX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Value:", ChildId::VALUE_LABEL)); + valueEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, "", ChildId::VALUE_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + return rowPos - posY; +} + +void AddPropertyWindow::CheckEnableOk() { + if (!isInitialized) { + return; + } + + okButton->SetEnabled(!keyEdit->IsTextEmpty() && !valueEdit->IsTextEmpty()); +} + +bool AddPropertyWindow::OnMessage(UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case ChildId::OK_BUTTON: + { + keyEdit->GetText(key); + valueEdit->GetText(value); + accepted = true; + PostMessage(GetHandle(), WM_CLOSE, 0, 0); + + break; + } + + case IDCANCEL: + case ChildId::CANCEL_BUTTON: + { + PostMessage(GetHandle(), WM_CLOSE, 0, 0); + break; + } + + case ChildId::KEY_EDIT: + case ChildId::VALUE_EDIT: + { + if (HIWORD(wParam) == EN_CHANGE) + { + CheckEnableOk(); + } + break; + } + + default: + return false; + } + + break; + } + + case WM_DESTROY: + { + PostQuitMessage(accepted ? Result::OK : Result::CANCEL); + + break; + } + + default: + return false; + } + + return true; +} + +} // namespace config +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/custom_window.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/custom_window.cc new file mode 100644 index 0000000000000..40f02b25f88c0 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/custom_window.cc @@ -0,0 +1,119 @@ +/* + * 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 "ui/custom_window.h" +#include + +namespace driver { +namespace flight_sql { +namespace config { + +Result::Type ProcessMessages(Window& window) +{ + MSG msg; + + while (GetMessage(&msg, NULL, 0, 0) > 0) + { + if (!IsDialogMessage(window.GetHandle(), &msg)) + { + TranslateMessage(&msg); + + DispatchMessage(&msg); + } + } + + return static_cast(msg.wParam); +} + +LRESULT CALLBACK CustomWindow::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + CustomWindow* window = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + + switch (msg) + { + case WM_NCCREATE: + { + _ASSERT(lParam != NULL); + + CREATESTRUCT* createStruct = reinterpret_cast(lParam); + + LONG_PTR longSelfPtr = reinterpret_cast(createStruct->lpCreateParams); + + SetWindowLongPtr(hwnd, GWLP_USERDATA, longSelfPtr); + + return DefWindowProc(hwnd, msg, wParam, lParam); + } + + case WM_CREATE: + { + _ASSERT(window != NULL); + + window->SetHandle(hwnd); + + window->OnCreate(); + + return 0; + } + + default: + break; + } + + if (window && window->OnMessage(msg, wParam, lParam)) + return 0; + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +CustomWindow::CustomWindow(Window* parent, const char* className, const char* title) : + Window(parent, className, title) +{ + WNDCLASS wcx; + + wcx.style = CS_HREDRAW | CS_VREDRAW; + wcx.lpfnWndProc = WndProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = GetHInstance(); + wcx.hIcon = NULL; + wcx.hCursor = LoadCursor(NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)COLOR_WINDOW; + wcx.lpszMenuName = NULL; + wcx.lpszClassName = className; + + if (!RegisterClass(&wcx)) + { + std::stringstream buf; + buf << "Can not register window class, error code: " << GetLastError(); + throw odbcabstraction::DriverException(buf.str()); + } +} + +CustomWindow::~CustomWindow() +{ + UnregisterClass(className.c_str(), GetHInstance()); +} + +} // namespace config +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc new file mode 100644 index 0000000000000..379cbe9486ccc --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc @@ -0,0 +1,577 @@ +/* + * 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 "ui/dsn_configuration_window.h" + +#include "flight_sql_connection.h" +#include +#include +#include +#include +#include + +#include "ui/add_property_window.h" + +#define COMMON_TAB 0 +#define ADVANCED_TAB 1 + +namespace driver { +namespace flight_sql { +namespace config { + +DsnConfigurationWindow::DsnConfigurationWindow(Window* parent, config::Configuration& config) : + CustomWindow(parent, "FlightConfigureDSN", "Configure Apache Arrow Flight SQL"), + width(480), + height(375), + config(config), + accepted(false), + isInitialized(false) +{ + // No-op. +} + +DsnConfigurationWindow::~DsnConfigurationWindow() +{ + // No-op. +} + +void DsnConfigurationWindow::Create() +{ + // Finding out parent position. + RECT parentRect; + GetWindowRect(parent->GetHandle(), &parentRect); + + // Positioning window to the center of parent window. + const int posX = parentRect.left + (parentRect.right - parentRect.left - width) / 2; + const int posY = parentRect.top + (parentRect.bottom - parentRect.top - height) / 2; + + RECT desiredRect = { posX, posY, posX + width, posY + height }; + AdjustWindowRect(&desiredRect, WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, FALSE); + + Window::Create(WS_OVERLAPPED | WS_SYSMENU, desiredRect.left, desiredRect.top, + desiredRect.right - desiredRect.left, desiredRect.bottom - desiredRect.top, 0); + + if (!handle) + { + std::stringstream buf; + buf << "Can not create window, error code: " << GetLastError(); + throw odbcabstraction::DriverException(buf.str()); + } +} + +void DsnConfigurationWindow::OnCreate() +{ + tabControl = CreateTabControl(ChildId::TAB_CONTROL); + tabControl->AddTab("Common", COMMON_TAB); + tabControl->AddTab("Advanced", ADVANCED_TAB); + + int groupPosY = 3 * MARGIN; + int groupSizeY = width - 2 * MARGIN; + + int commonGroupPosY = groupPosY; + commonGroupPosY += INTERVAL + CreateConnectionSettingsGroup(MARGIN, commonGroupPosY, groupSizeY); + commonGroupPosY += INTERVAL + CreateAuthSettingsGroup(MARGIN, commonGroupPosY, groupSizeY); + + int advancedGroupPosY = groupPosY; + advancedGroupPosY += INTERVAL + CreateEncryptionSettingsGroup(MARGIN, advancedGroupPosY, groupSizeY); + advancedGroupPosY += INTERVAL + CreatePropertiesGroup(MARGIN, advancedGroupPosY, groupSizeY); + + int cancelPosX = width - MARGIN - BUTTON_WIDTH; + int okPosX = cancelPosX - INTERVAL - BUTTON_WIDTH; + + int buttonPosY = std::max(commonGroupPosY, advancedGroupPosY); + okButton = CreateButton(okPosX, buttonPosY, BUTTON_WIDTH, BUTTON_HEIGHT, "Ok", ChildId::OK_BUTTON); + cancelButton = CreateButton(cancelPosX, buttonPosY, BUTTON_WIDTH, BUTTON_HEIGHT, + "Cancel", ChildId::CANCEL_BUTTON); + isInitialized = true; + CheckEnableOk(); + SelectTab(COMMON_TAB); +} + +int DsnConfigurationWindow::CreateConnectionSettingsGroup(int posX, int posY, int sizeX) +{ + enum { LABEL_WIDTH = 100 }; + + const int labelPosX = posX + INTERVAL; + + const int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; + const int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; + + int rowPos = posY + 2 * INTERVAL; + + const char* val = config.Get(FlightSqlConnection::DSN).c_str(); + labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Data Source Name:", ChildId::NAME_LABEL)); + nameEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::NAME_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.Get(FlightSqlConnection::HOST).c_str(); + labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Host Name:", ChildId::SERVER_LABEL)); + serverEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SERVER_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.Get(FlightSqlConnection::PORT).c_str(); + labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Port:", ChildId::PORT_LABEL)); + portEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::PORT_EDIT, ES_NUMBER); + + rowPos += INTERVAL + ROW_HEIGHT; + + connectionSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, + "Connection settings", ChildId::CONNECTION_SETTINGS_GROUP_BOX); + + return rowPos - posY; +} + +int DsnConfigurationWindow::CreateAuthSettingsGroup(int posX, int posY, int sizeX) +{ + enum { LABEL_WIDTH = 120 }; + + const int labelPosX = posX + INTERVAL; + + const int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; + const int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; + + int rowPos = posY + 2 * INTERVAL; + + labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Authentication Type:", ChildId::AUTH_TYPE_LABEL)); + authTypeComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, + "Authentication Type:", ChildId::AUTH_TYPE_COMBOBOX); + authTypeComboBox->AddString("Basic Authentication"); + authTypeComboBox->AddString("Token Authentication"); + + rowPos += INTERVAL + ROW_HEIGHT; + + const char* val = config.Get(FlightSqlConnection::UID).c_str(); + + labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "User:", ChildId::USER_LABEL)); + userEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::USER_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.Get(FlightSqlConnection::PWD).c_str(); + labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Password:", ChildId::PASSWORD_LABEL)); + passwordEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, + val, ChildId::USER_EDIT, ES_PASSWORD); + + rowPos += INTERVAL + ROW_HEIGHT; + + const auto& token = config.Get(FlightSqlConnection::TOKEN); + val = token.c_str(); + labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Authentication Token:", ChildId::AUTH_TOKEN_LABEL)); + authTokenEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, + val, ChildId::AUTH_TOKEN_EDIT); + authTokenEdit->SetEnabled(false); + + // Ensure the right elements are selected. + authTypeComboBox->SetSelection(token.empty() ? 0 : 1); + CheckAuthType(); + + rowPos += INTERVAL + ROW_HEIGHT; + + authSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, + "Authentication settings", ChildId::AUTH_SETTINGS_GROUP_BOX); + + return rowPos - posY; +} + +int DsnConfigurationWindow::CreateEncryptionSettingsGroup(int posX, int posY, int sizeX) +{ + enum { LABEL_WIDTH = 120 }; + + const int labelPosX = posX + INTERVAL; + + const int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; + const int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; + + int rowPos = posY + 2 * INTERVAL; + + const char* val = config.Get(FlightSqlConnection::USE_ENCRYPTION).c_str(); + + const bool enableEncrption = !boost::iequals(val, "false"); + labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Use Encryption:", + ChildId::ENABLE_ENCRYPTION_LABEL)); + enableEncryptionCheckBox = CreateCheckBox(editPosX, rowPos - 2, editSizeX, ROW_HEIGHT, "", + ChildId::ENABLE_ENCRYPTION_CHECKBOX, enableEncrption); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.Get(FlightSqlConnection::TRUSTED_CERTS).c_str(); + + labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Certificate:", ChildId::CERTIFICATE_LABEL)); + certificateEdit = CreateEdit(editPosX, rowPos, editSizeX - MARGIN - BUTTON_WIDTH, ROW_HEIGHT, val, ChildId::CERTIFICATE_EDIT); + certificateBrowseButton = CreateButton(editPosX + editSizeX - BUTTON_WIDTH, rowPos - 2, BUTTON_WIDTH, BUTTON_HEIGHT, + "Browse", ChildId::CERTIFICATE_BROWSE_BUTTON); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.Get(FlightSqlConnection::USE_SYSTEM_TRUST_STORE).c_str(); + + const bool useSystemCertStore = !boost::iequals(val, "false"); + labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, 2 * ROW_HEIGHT, "Use System Certificate Store:", + ChildId::USE_SYSTEM_CERT_STORE_LABEL)); + useSystemCertStoreCheckBox = CreateCheckBox(editPosX, rowPos - 2, 20, 2 * ROW_HEIGHT, "", + ChildId::USE_SYSTEM_CERT_STORE_CHECKBOX, useSystemCertStore); + + + val = config.Get(FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION).c_str(); + + const int rightPosX = labelPosX + (sizeX - (2 * INTERVAL)) / 2; + const int rightCheckPosX = rightPosX + (editPosX - labelPosX); + const bool disableCertVerification = !boost::iequals(val, "false"); + labels.push_back(CreateLabel(rightPosX, rowPos, LABEL_WIDTH, 2 * ROW_HEIGHT, "Disable Certificate Verification:", + ChildId::DISABLE_CERT_VERIFICATION_LABEL)); + disableCertVerificationCheckBox = CreateCheckBox(rightCheckPosX, rowPos - 2, 20, 2 * ROW_HEIGHT, "", + ChildId::DISABLE_CERT_VERIFICATION_CHECKBOX, disableCertVerification); + + rowPos += INTERVAL + static_cast(1.5 * ROW_HEIGHT); + + encryptionSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, + "Encryption settings", ChildId::AUTH_SETTINGS_GROUP_BOX); + + return rowPos - posY; +} + +int DsnConfigurationWindow::CreatePropertiesGroup(int posX, int posY, int sizeX) +{ + enum { LABEL_WIDTH = 120 }; + + const int labelPosX = posX + INTERVAL; + const int listSize = sizeX - 2 * INTERVAL; + const int columnSize = listSize / 2; + + int rowPos = posY + 2 * INTERVAL; + const int listHeight = 5 * ROW_HEIGHT; + + propertyList = CreateList(labelPosX, rowPos, listSize, listHeight, ChildId::PROPERTY_LIST); + propertyList->ListAddColumn("Key", 0, columnSize); + propertyList->ListAddColumn("Value", 1, columnSize); + + const auto keys = config.GetCustomKeys(); + for (const auto& key : keys) { + propertyList->ListAddItem({ key, config.Get(key) }); + } + + SendMessage(propertyList->GetHandle(), LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + + rowPos += INTERVAL + listHeight; + + int deletePosX = width - INTERVAL - MARGIN - BUTTON_WIDTH; + int addPosX = deletePosX - INTERVAL - BUTTON_WIDTH; + addButton = CreateButton(addPosX, rowPos, BUTTON_WIDTH, BUTTON_HEIGHT, "Add", ChildId::ADD_BUTTON); + deleteButton = CreateButton(deletePosX, rowPos, BUTTON_WIDTH, BUTTON_HEIGHT, + "Delete", ChildId::DELETE_BUTTON); + + rowPos += INTERVAL + BUTTON_HEIGHT; + + propertyGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, + "Advanced properties", ChildId::PROPERTY_GROUP_BOX); + + return rowPos - posY; +} + +void DsnConfigurationWindow::SelectTab(int tabIndex) { + if (!isInitialized) { + return; + } + + connectionSettingsGroupBox->SetVisible(COMMON_TAB == tabIndex); + authSettingsGroupBox->SetVisible(COMMON_TAB == tabIndex); + nameEdit->SetVisible(COMMON_TAB == tabIndex); + serverEdit->SetVisible(COMMON_TAB == tabIndex); + portEdit->SetVisible(COMMON_TAB == tabIndex); + authTypeComboBox->SetVisible(COMMON_TAB == tabIndex); + userEdit->SetVisible(COMMON_TAB == tabIndex); + passwordEdit->SetVisible(COMMON_TAB == tabIndex); + authTokenEdit->SetVisible(COMMON_TAB == tabIndex); + for (size_t i = 0; i < 7; ++i) { + labels[i]->SetVisible(COMMON_TAB == tabIndex); + } + + encryptionSettingsGroupBox->SetVisible(ADVANCED_TAB == tabIndex); + enableEncryptionCheckBox->SetVisible(ADVANCED_TAB == tabIndex); + certificateEdit->SetVisible(ADVANCED_TAB == tabIndex); + certificateBrowseButton->SetVisible(ADVANCED_TAB == tabIndex); + useSystemCertStoreCheckBox->SetVisible(ADVANCED_TAB == tabIndex); + disableCertVerificationCheckBox->SetVisible(ADVANCED_TAB == tabIndex); + propertyGroupBox->SetVisible(ADVANCED_TAB == tabIndex); + propertyList->SetVisible(ADVANCED_TAB == tabIndex); + addButton->SetVisible(ADVANCED_TAB == tabIndex); + deleteButton->SetVisible(ADVANCED_TAB == tabIndex); + for (size_t i = 7; i < labels.size(); ++i) { + labels[i]->SetVisible(ADVANCED_TAB == tabIndex); + } +} + +void DsnConfigurationWindow::CheckEnableOk() { + if (!isInitialized) { + return; + } + + bool enableOk = !nameEdit->IsTextEmpty(); + enableOk = enableOk && !serverEdit->IsTextEmpty(); + enableOk = enableOk && !portEdit->IsTextEmpty(); + if (authTokenEdit->IsEnabled()) + { + enableOk = enableOk && !authTokenEdit->IsTextEmpty(); + } + else + { + enableOk = enableOk && !userEdit->IsTextEmpty(); + enableOk = enableOk && !passwordEdit->IsTextEmpty(); + } + + okButton->SetEnabled(enableOk); +} + +void DsnConfigurationWindow::SaveParameters() +{ + config.Clear(); + + std::string text; + nameEdit->GetText(text); + config.Set(FlightSqlConnection::DSN, text); + serverEdit->GetText(text); + config.Set(FlightSqlConnection::HOST, text); + portEdit->GetText(text); + try { + const int portInt = std::stoi(text); + if (0 > portInt || USHRT_MAX < portInt) + { + throw odbcabstraction::DriverException("Invalid port value."); + } + config.Set(FlightSqlConnection::PORT, text); + } + catch (odbcabstraction::DriverException&) { + throw; + } + catch (std::exception&) { + throw odbcabstraction::DriverException("Invalid port value."); + } + + if (0 == authTypeComboBox->GetSelection()) + { + userEdit->GetText(text); + config.Set(FlightSqlConnection::UID, text); + passwordEdit->GetText(text); + config.Set(FlightSqlConnection::PWD, text); + } + else + { + authTokenEdit->GetText(text); + config.Set(FlightSqlConnection::TOKEN, text); + } + + if (enableEncryptionCheckBox->IsChecked()) + { + config.Set(FlightSqlConnection::USE_ENCRYPTION, TRUE_STR); + certificateEdit->GetText(text); + config.Set(FlightSqlConnection::TRUSTED_CERTS, text); + config.Set(FlightSqlConnection::USE_SYSTEM_TRUST_STORE, useSystemCertStoreCheckBox->IsChecked() ? TRUE_STR : FALSE_STR); + config.Set(FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, disableCertVerificationCheckBox->IsChecked() ? TRUE_STR : FALSE_STR); + } + else + { + config.Set(FlightSqlConnection::USE_ENCRYPTION, FALSE_STR); + } + + // Get all the list properties. + const auto properties = propertyList->ListGetAll(); + for (const auto& property : properties) { + config.Set(property[0], property[1]); + } +} + +void DsnConfigurationWindow::CheckAuthType() { + const bool isBasic = COMMON_TAB == authTypeComboBox->GetSelection(); + userEdit->SetEnabled(isBasic); + passwordEdit->SetEnabled(isBasic); + authTokenEdit->SetEnabled(!isBasic); +} + +bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_NOTIFY: + { + switch (((LPNMHDR)lParam)->code) + { + case TCN_SELCHANGING: + { + // Return FALSE to allow the selection to change. + return FALSE; + } + + case TCN_SELCHANGE: + { + SelectTab(TabCtrl_GetCurSel(tabControl->GetHandle())); + break; + } + } + break; + } + + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case ChildId::OK_BUTTON: + { + try + { + SaveParameters(); + accepted = true; + PostMessage(GetHandle(), WM_CLOSE, 0, 0); + } + catch (odbcabstraction::DriverException& err) + { + MessageBox(NULL, err.GetMessageText().c_str(), "Error!", MB_ICONEXCLAMATION | MB_OK); + } + + break; + } + + case IDCANCEL: + case ChildId::CANCEL_BUTTON: + { + PostMessage(GetHandle(), WM_CLOSE, 0, 0); + break; + } + + case ChildId::AUTH_TOKEN_EDIT: + case ChildId::NAME_EDIT: + case ChildId::PASSWORD_EDIT: + case ChildId::PORT_EDIT: + case ChildId::SERVER_EDIT: + case ChildId::USER_EDIT: + { + if (HIWORD(wParam) == EN_CHANGE) + { + CheckEnableOk(); + } + break; + } + + case ChildId::AUTH_TYPE_COMBOBOX: + { + CheckAuthType(); + CheckEnableOk(); + break; + } + + case ChildId::ENABLE_ENCRYPTION_CHECKBOX: + { + const bool toggle = !enableEncryptionCheckBox->IsChecked(); + enableEncryptionCheckBox->SetChecked(toggle); + certificateEdit->SetEnabled(toggle); + certificateBrowseButton->SetEnabled(toggle); + useSystemCertStoreCheckBox->SetEnabled(toggle); + disableCertVerificationCheckBox->SetEnabled(toggle); + break; + } + + case ChildId::CERTIFICATE_BROWSE_BUTTON: + { + OPENFILENAME openFileName; + char fileName[FILENAME_MAX]; + + ZeroMemory(&openFileName, sizeof(openFileName)); + openFileName.lStructSize = sizeof(openFileName); + openFileName.hwndOwner = NULL; + openFileName.lpstrFile = fileName; + openFileName.lpstrFile[0] = '\0'; + openFileName.nMaxFile = FILENAME_MAX; + // TODO: What type should this be? + openFileName.lpstrFilter = "All\0*.*"; + openFileName.nFilterIndex = 1; + openFileName.lpstrFileTitle = NULL; + openFileName.nMaxFileTitle = 0; + openFileName.lpstrInitialDir = NULL; + openFileName.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; + + if (GetOpenFileName(&openFileName)) { + certificateEdit->SetText(fileName); + } + break; + } + + case ChildId::USE_SYSTEM_CERT_STORE_CHECKBOX: + { + useSystemCertStoreCheckBox->SetChecked(!useSystemCertStoreCheckBox->IsChecked()); + break; + } + + case ChildId::DISABLE_CERT_VERIFICATION_CHECKBOX: + { + disableCertVerificationCheckBox->SetChecked(!disableCertVerificationCheckBox->IsChecked()); + break; + } + + case ChildId::DELETE_BUTTON: + { + propertyList->ListDeleteSelectedItem(); + break; + } + + case ChildId::ADD_BUTTON: + { + AddPropertyWindow addWindow(this); + addWindow.Create(); + addWindow.Show(); + addWindow.Update(); + + if (ProcessMessages(addWindow) == Result::OK) + { + std::string key; + std::string value; + addWindow.GetProperty(key, value); + propertyList->ListAddItem({ key, value }); + } + break; + } + + default: + return false; + } + + break; + } + + case WM_DESTROY: + { + PostQuitMessage(accepted ? Result::OK : Result::CANCEL); + + break; + } + + default: + return false; + } + + return true; +} + +} // namespace config +} // namespace flight_sql +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc new file mode 100644 index 0000000000000..b58fc0c851c54 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc @@ -0,0 +1,384 @@ +/* + * 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 "winuser.h" +#include +#include +#include + +#include "ui/window.h" +#include +#include +#include + +namespace driver { +namespace flight_sql { +namespace config { + +HINSTANCE GetHInstance() +{ + TCHAR szFileName[MAX_PATH]; + GetModuleFileName(NULL, szFileName, MAX_PATH); + + // TODO: This needs to be the module name. + HINSTANCE hInstance = GetModuleHandle(szFileName); + + if (hInstance == NULL) + { + std::stringstream buf; + buf << "Can not get hInstance for the module, error code: " << GetLastError(); + throw odbcabstraction::DriverException(buf.str()); + } + + return hInstance; +} + +Window::Window(Window* parent, const char* className, const char* title) : + className(className), + title(title), + handle(NULL), + parent(parent), + created(false) +{ + // No-op. +} + +Window::Window(HWND handle) : + className(), + title(), + handle(handle), + parent(0), + created(false) +{ + // No-op. +} + +Window::~Window() +{ + if (created) + Destroy(); +} + +void Window::Create(DWORD style, int posX, int posY, int width, int height, int id) +{ + if (handle) + { + std::stringstream buf; + buf << "Window already created, error code: " << GetLastError(); + throw odbcabstraction::DriverException(buf.str()); + } + + handle = CreateWindow( + className.c_str(), + title.c_str(), + style, + posX, + posY, + width, + height, + parent ? parent->GetHandle() : NULL, + reinterpret_cast(static_cast(id)), + GetHInstance(), + this + ); + + if (!handle) + { + std::stringstream buf; + buf << "Can not create window, error code: " << GetLastError(); + throw odbcabstraction::DriverException(buf.str()); + } + + created = true; + + const HGDIOBJ hfDefault = GetStockObject(DEFAULT_GUI_FONT); + SendMessage(GetHandle(), WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0)); +} + + +std::unique_ptr Window::CreateTabControl(int id) +{ + std::unique_ptr child(new Window(this, WC_TABCONTROL, "")); + + // Get the dimensions of the parent window's client area, and + // create a tab control child window of that size. + RECT rcClient; + GetClientRect(handle, &rcClient); + + child->Create(WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | WS_TABSTOP, 0, 0, rcClient.right, 20, id); + + return child; +} + +std::unique_ptr Window::CreateList(int posX, int posY, + int sizeX, int sizeY, int id) +{ + std::unique_ptr child(new Window(this, WC_LISTVIEW, "")); + + child->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT | LVS_EDITLABELS | WS_TABSTOP, posX, posY, sizeX, sizeY, id); + + return child; +} + +std::unique_ptr Window::CreateGroupBox(int posX, int posY, + int sizeX, int sizeY, const char* title, int id) +{ + std::unique_ptr child(new Window(this, "Button", title)); + + child->Create(WS_CHILD | WS_VISIBLE | BS_GROUPBOX, posX, posY, sizeX, sizeY, id); + + return child; +} + +std::unique_ptr Window::CreateLabel(int posX, int posY, + int sizeX, int sizeY, const char* title, int id) +{ + std::unique_ptr child(new Window(this, "Static", title)); + + child->Create(WS_CHILD | WS_VISIBLE, posX, posY, sizeX, sizeY, id); + + return child; +} + +std::unique_ptr Window::CreateEdit(int posX, int posY, + int sizeX, int sizeY, const char* title, int id, int style) +{ + std::unique_ptr child(new Window(this, "Edit", title)); + + child->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | WS_TABSTOP | style, + posX, posY, sizeX, sizeY, id); + + return child; +} + +std::unique_ptr Window::CreateButton(int posX, int posY, + int sizeX, int sizeY, const char* title, int id, int style) +{ + std::unique_ptr child(new Window(this, "Button", title)); + + child->Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | style, posX, posY, sizeX, sizeY, id); + + return child; +} + +std::unique_ptr Window::CreateCheckBox(int posX, int posY, + int sizeX, int sizeY, const char* title, int id, bool state) +{ + std::unique_ptr child(new Window(this, "Button", title)); + + child->Create(WS_CHILD | WS_VISIBLE | BS_CHECKBOX | WS_TABSTOP, posX, posY, sizeX, sizeY, id); + + child->SetChecked(state); + + return child; +} + +std::unique_ptr Window::CreateComboBox(int posX, int posY, + int sizeX, int sizeY, const char* title, int id) +{ + std::unique_ptr child(new Window(this, "Combobox", title)); + + child->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_TABSTOP, posX, posY, sizeX, sizeY, id); + + return child; +} + +void Window::Show() +{ + ShowWindow(handle, SW_SHOW); +} + +void Window::Update() +{ + UpdateWindow(handle); +} + +void Window::Destroy() +{ + if (handle) + DestroyWindow(handle); + + handle = NULL; +} + +void Window::SetVisible(bool isVisible) { + ShowWindow(handle, isVisible ? SW_SHOW : SW_HIDE); +} + +bool Window::IsTextEmpty() const +{ + if (!IsEnabled()) + { + return true; + } + int len = GetWindowTextLength(handle); + + return (len <= 0); +} + +void Window::ListAddColumn(const std::string& name, int index, int width) +{ + LVCOLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; + lvc.cx = width; + lvc.pszText = const_cast(name.c_str()); + lvc.iSubItem = index; + + if (ListView_InsertColumn(handle, index, &lvc) == -1) + { + std::stringstream buf; + buf << "Can not add list column, error code: " << GetLastError(); + throw odbcabstraction::DriverException(buf.str()); + } +} + +void Window::ListAddItem(const std::vector& items) +{ + LVITEM lvi = { 0 }; + lvi.mask = LVIF_TEXT; + lvi.pszText = const_cast(items[0].c_str()); + + int ret = ListView_InsertItem(handle, &lvi); + if (ret < 0) { + std::stringstream buf; + buf << "Can not add list item, error code: " << GetLastError(); + throw odbcabstraction::DriverException(buf.str()); + } + + for (size_t i = 1; i < items.size(); ++i) { + ListView_SetItemText(handle, ret, static_cast(i), const_cast(items[i].c_str())); + } +} + +void Window::ListDeleteSelectedItem() +{ + const int rowIndex = ListView_GetSelectionMark(handle); + if (rowIndex >= 0) { + if (ListView_DeleteItem(handle, rowIndex) == -1) { + std::stringstream buf; + buf << "Can not delete list item, error code: " << GetLastError(); + throw odbcabstraction::DriverException(buf.str()); + } + } +} + +std::vector > Window::ListGetAll() +{ + #define BUF_LEN 1024 + char buf[BUF_LEN]; + + std::vector > values; + const int numColumns = Header_GetItemCount(ListView_GetHeader(handle)); + const int numItems = ListView_GetItemCount(handle); + for (int i = 0; i < numItems; ++i) { + std::vector row; + for (int j = 0; j < numColumns; ++j) { + ListView_GetItemText(handle, j, i, buf, BUF_LEN); + row.emplace_back(buf); + } + values.push_back(row); + } + + return values; +} + +void Window::AddTab(const std::string& name, int index) +{ + TCITEM tabControlItem; + tabControlItem.mask = TCIF_TEXT | TCIF_IMAGE; + tabControlItem.iImage = -1; + tabControlItem.pszText = const_cast(name.c_str()); + if (TabCtrl_InsertItem(handle, index, &tabControlItem) == -1) + { + std::stringstream buf; + buf << "Can not add tab, error code: " << GetLastError(); + throw odbcabstraction::DriverException(buf.str()); + } +} + +void Window::GetText(std::string& text) const +{ + if (!IsEnabled()) + { + text.clear(); + + return; + } + + int len = GetWindowTextLength(handle); + + if (len <= 0) + { + text.clear(); + + return; + } + + text.resize(len + 1); + + if (!GetWindowText(handle, &text[0], len + 1)) + text.clear(); + + text.resize(len); + boost::algorithm::trim(text); +} + +void Window::SetText(const std::string& text) const +{ + SNDMSG(handle, WM_SETTEXT, 0, reinterpret_cast(text.c_str())); +} + +bool Window::IsChecked() const +{ + return IsEnabled() && Button_GetCheck(handle) == BST_CHECKED; +} + +void Window::SetChecked(bool state) +{ + Button_SetCheck(handle, state ? BST_CHECKED : BST_UNCHECKED); +} + +void Window::AddString(const std::string & str) +{ + SNDMSG(handle, CB_ADDSTRING, 0, reinterpret_cast(str.c_str())); +} + +void Window::SetSelection(int idx) +{ + SNDMSG(handle, CB_SETCURSEL, static_cast(idx), 0); +} + +int Window::GetSelection() const +{ + return static_cast(SNDMSG(handle, CB_GETCURSEL, 0, 0)); +} + +void Window::SetEnabled(bool enabled) +{ + EnableWindow(GetHandle(), enabled); +} + +bool Window::IsEnabled() const +{ + return IsWindowEnabled(GetHandle()) != 0; +} + +} // namespace config +} // namespace flight_sql +} // namespace driver From 9deea0284b2605c5c8f1f16812e94f64c3f9c0ac Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Tue, 31 May 2022 11:25:15 -0300 Subject: [PATCH 113/183] Add a new converter which perform the conversion from numeric type to string type When trying to bind a column which has an original type of numeric, to a SQL_C_CHAR or SQL_W_CHAR we got an error during conversion. This change adds a new converter which will perform the operation. Change-Id: Iacd4ad2597be30b96d0d602578af69b3c1266458 --- .../flightsql-odbc/flight_sql/utils.cc | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index ffa4e480028b8..068059cb789c1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -16,8 +16,9 @@ // under the License. #include "utils.h" +#include "arrow/builder.h" #include "arrow/type_fwd.h" -#include +#include #include #include #include @@ -710,7 +711,29 @@ ArrayConvertTask GetConverter(arrow::Type::type original_type_id, return CheckConversion(arrow::compute::CallFunction( "cast", {first_converted_array}, &cast_options)); }; - } else if (IsComplexType(original_type_id) && + } else if (original_type_id == arrow::Type::DECIMAL128 && + (target_type == odbcabstraction::CDataType_CHAR || + target_type == odbcabstraction::CDataType_WCHAR)) { + return [=](const std::shared_ptr &original_array) { + arrow::StringBuilder builder; + int64_t length = original_array->length(); + ThrowIfNotOK(builder.ReserveData(length)); + + for (int64_t i = 0; i < length; ++i) { + if (original_array->IsNull(i)) { + ThrowIfNotOK(builder.AppendNull()); + } else { + auto result = original_array->GetScalar(i); + auto scalar = result.ValueOrDie(); + ThrowIfNotOK(builder.Append(scalar->ToString())); + } + } + + auto finish = builder.Finish(); + + return finish.ValueOrDie(); + }; + } else if (IsComplexType(original_type_id) && (target_type == odbcabstraction::CDataType_CHAR || target_type == odbcabstraction::CDataType_WCHAR)) { return [=](const std::shared_ptr &original_array) { @@ -731,7 +754,5 @@ ArrayConvertTask GetConverter(arrow::Type::type original_type_id, }; } } - - } // namespace flight_sql } // namespace driver From 30a210f9403d71cc0b6d3f059b9ac227817b4249 Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 3 Jun 2022 03:28:17 -0700 Subject: [PATCH 114/183] Fix use of invalidated pointers in json_converter - When using data from temporarily-allocated StringScalars (such as visiting date time scalars), have rapidjson copy the data instead of reference it since the data will be deleted when exiting the scope of the Visit call - Handle null correctly when visiting List scalar types. This differs from NullScalars. - Handle null entries in the starting array. This differs from NullScalars. - Reduce code duplication by creating templated helpers. - Address array and list indices using int64_t instead of int. Change-Id: I14dc6a015418a7ce8feb30210f0651bc4258bb4e --- .../flight_sql/json_converter.cc | 142 ++++++++---------- .../flight_sql/json_converter_test.cc | 5 + 2 files changed, 65 insertions(+), 82 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc index 4fb5d8d128a82..efad0c81f67e1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc @@ -31,6 +31,43 @@ using namespace boost::beast::detail; using driver::flight_sql::ThrowIfNotOK; namespace { +template +Status ConvertScalarToStringAndWrite(const ScalarT& scalar, rapidjson::Writer& writer) { + ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) + const auto &view = reinterpret_cast(string_scalar.get())->view(); + writer.String(view.data(), view.length(), true); + return Status::OK(); +} + +template +Status ConvertBinaryToBase64StringAndWrite(const BinaryScalarT& scalar, rapidjson::Writer& writer) { + const auto &view = scalar.view(); + size_t encoded_size = base64::encoded_size(view.length()); + std::vector encoded(std::max(encoded_size, static_cast(1))); + base64::encode(&encoded[0], view.data(), view.length()); + writer.String(&encoded[0], encoded_size, true); + return Status::OK(); +} + +template +Status WriteListScalar(const ListScalarT& scalar, rapidjson::Writer& writer, + arrow::ScalarVisitor* visitor) { + writer.StartArray(); + for (int64_t i = 0; i < scalar.value->length(); ++i) { + if (scalar.value->IsNull(i)) { + writer.Null(); + } else { + const auto &result = scalar.value->GetScalar(i); + ThrowIfNotOK(result.status()); + ThrowIfNotOK(result.ValueOrDie()->Accept(visitor)); + } + } + + writer.EndArray(); + return Status::OK(); +} + + class ScalarToJson : public arrow::ScalarVisitor { private: rapidjson::StringBuffer string_buffer_; @@ -130,13 +167,7 @@ class ScalarToJson : public arrow::ScalarVisitor { } Status Visit(const BinaryScalar &scalar) override { - const auto &view = scalar.view(); - size_t encoded_size = base64::encoded_size(view.length()); - std::vector encoded(std::max(encoded_size, static_cast(1))); - base64::encode(&encoded[0], view.data(), view.length()); - writer_.String(&encoded[0], encoded_size, true); - - return Status::OK(); + return ConvertBinaryToBase64StringAndWrite(scalar, writer_); } Status Visit(const LargeStringScalar &scalar) override { @@ -147,69 +178,48 @@ class ScalarToJson : public arrow::ScalarVisitor { } Status Visit(const LargeBinaryScalar &scalar) override { - const auto &view = scalar.view(); - size_t encoded_size = base64::encoded_size(view.length()); - std::vector encoded(std::max(encoded_size, static_cast(1))); - base64::encode(&encoded[0], view.data(), view.length()); - writer_.String(&encoded[0], encoded_size, true); - - return Status::OK(); + return ConvertBinaryToBase64StringAndWrite(scalar, writer_); } Status Visit(const FixedSizeBinaryScalar &scalar) override { - const auto &view = scalar.view(); - size_t encoded_size = base64::encoded_size(view.length()); - std::vector encoded(std::max(encoded_size, static_cast(1))); - base64::encode(&encoded[0], view.data(), view.length()); - writer_.String(&encoded[0], encoded_size, true); - - return Status::OK(); + return ConvertBinaryToBase64StringAndWrite(scalar, writer_); } Status Visit(const Date64Scalar &scalar) override { - ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) - return string_scalar->Accept(this); + return ConvertScalarToStringAndWrite(scalar, writer_); } Status Visit(const Date32Scalar &scalar) override { - ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) - return string_scalar->Accept(this); + return ConvertScalarToStringAndWrite(scalar, writer_); } Status Visit(const Time32Scalar &scalar) override { - ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) - return string_scalar->Accept(this); + return ConvertScalarToStringAndWrite(scalar, writer_); } Status Visit(const Time64Scalar &scalar) override { - ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) - return string_scalar->Accept(this); + return ConvertScalarToStringAndWrite(scalar, writer_); } Status Visit(const TimestampScalar &scalar) override { - ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) - return string_scalar->Accept(this); + return ConvertScalarToStringAndWrite(scalar, writer_); } Status Visit(const DayTimeIntervalScalar &scalar) override { - ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) - return string_scalar->Accept(this); + return ConvertScalarToStringAndWrite(scalar, writer_); } Status Visit(const MonthDayNanoIntervalScalar &scalar) override { - ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) - return string_scalar->Accept(this); + return ConvertScalarToStringAndWrite(scalar, writer_); } Status Visit(const MonthIntervalScalar &scalar) override { - ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) - return string_scalar->Accept(this); + return ConvertScalarToStringAndWrite(scalar, writer_); } Status Visit(const DurationScalar &scalar) override { // TODO: Append TimeUnit on conversion - ARROW_ASSIGN_OR_RAISE(auto string_scalar, scalar.CastTo(utf8())) - return string_scalar->Accept(this); + return ConvertScalarToStringAndWrite(scalar, writer_); } Status Visit(const Decimal128Scalar &scalar) override { @@ -227,55 +237,19 @@ class ScalarToJson : public arrow::ScalarVisitor { } Status Visit(const ListScalar &scalar) override { - writer_.StartArray(); - for (int i = 0; i < scalar.value->length(); ++i) { - const auto &result = scalar.value->GetScalar(i); - ThrowIfNotOK(result.status()); - ThrowIfNotOK(result.ValueOrDie()->Accept(this)); - } - - writer_.EndArray(); - - return Status::OK(); + return WriteListScalar(scalar, writer_, this); } Status Visit(const LargeListScalar &scalar) override { - writer_.StartArray(); - for (int i = 0; i < scalar.value->length(); ++i) { - const auto &result = scalar.value->GetScalar(i); - ThrowIfNotOK(result.status()); - ThrowIfNotOK(result.ValueOrDie()->Accept(this)); - } - - writer_.EndArray(); - - return Status::OK(); + return WriteListScalar(scalar, writer_, this); } Status Visit(const MapScalar &scalar) override { - writer_.StartArray(); - for (int i = 0; i < scalar.value->length(); ++i) { - const auto &result = scalar.value->GetScalar(i); - ThrowIfNotOK(result.status()); - ThrowIfNotOK(result.ValueOrDie()->Accept(this)); - } - - writer_.EndArray(); - - return Status::OK(); + return WriteListScalar(scalar, writer_, this); } Status Visit(const FixedSizeListScalar &scalar) override { - writer_.StartArray(); - for (int i = 0; i < scalar.value->length(); ++i) { - const auto &result = scalar.value->GetScalar(i); - ThrowIfNotOK(result.status()); - ThrowIfNotOK(result.ValueOrDie()->Accept(this)); - } - - writer_.EndArray(); - - return Status::OK(); + return WriteListScalar(scalar, writer_, this); } Status Visit(const StructScalar &scalar) override { @@ -329,9 +303,13 @@ arrow::Result> ConvertToJson(const std::shared_ptr int64_t length = input->length(); RETURN_NOT_OK(builder.ReserveData(length)); - for (int i = 0; i < length; ++i) { - ARROW_ASSIGN_OR_RAISE(auto scalar, input->GetScalar(i)) - RETURN_NOT_OK(builder.Append(ConvertToJson(*scalar))); + for (int64_t i = 0; i < length; ++i) { + if (input->IsNull(i)) { + RETURN_NOT_OK(builder.AppendNull()); + } else { + ARROW_ASSIGN_OR_RAISE(auto scalar, input->GetScalar(i)) + RETURN_NOT_OK(builder.Append(ConvertToJson(*scalar))); + } } return builder.Finish(); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc index 2d090f31720c2..74c743d69b259 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc @@ -175,6 +175,11 @@ TEST(ConvertToJson, Lists) { ASSERT_EQ(expected_string, ConvertToJson(ListScalar{array})); ASSERT_EQ(expected_string, ConvertToJson(FixedSizeListScalar{array})); ASSERT_EQ(expected_string, ConvertToJson(LargeListScalar{array})); + + StringBuilder builder; + ASSERT_OK(builder.AppendNull()); + ASSERT_EQ("[null]", ConvertToJson(ListScalar{builder.Finish().ValueOrDie()})); + ASSERT_EQ("[]", ConvertToJson(ListScalar{StringBuilder().Finish().ValueOrDie()})); } TEST(ConvertToJson, Struct) { From 3751b4c892991bd0f3cefc316858d40fe82ea6bd Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 2 Jun 2022 18:57:21 -0700 Subject: [PATCH 115/183] Fix iterative SQLGetData - Rework converters so that they properly track the last offset and the end of a GetData call so that iterative SQLGetData will behave properly. - Update unit tests for this behavior. - Minor clean-up of converter code including removal of unused function Change-Id: I8511d62b9fab96104a402bdbbefdecefb91ff555 --- .../accessors/binary_array_accessor.cc | 24 ++++++++++------ .../accessors/binary_array_accessor.h | 2 +- .../accessors/binary_array_accessor_test.cc | 23 +++++++++------ .../accessors/boolean_array_accessor.cc | 2 +- .../accessors/boolean_array_accessor.h | 2 +- .../accessors/boolean_array_accessor_test.cc | 3 +- .../flight_sql/accessors/common.h | 28 ------------------- .../accessors/date_array_accessor.cc | 2 +- .../accessors/date_array_accessor.h | 2 +- .../accessors/date_array_accessor_test.cc | 6 ++-- .../accessors/decimal_array_accessor.cc | 6 ++-- .../accessors/decimal_array_accessor.h | 2 +- .../accessors/decimal_array_accessor_test.cc | 3 +- .../accessors/primitive_array_accessor.cc | 2 +- .../accessors/primitive_array_accessor.h | 3 +- .../primitive_array_accessor_test.cc | 3 +- .../accessors/string_array_accessor.cc | 26 +++++++++++------ .../accessors/string_array_accessor.h | 2 +- .../accessors/string_array_accessor_test.cc | 27 ++++++++---------- .../accessors/time_array_accessor.cc | 2 +- .../accessors/time_array_accessor.h | 2 +- .../accessors/time_array_accessor_test.cc | 12 +++++--- .../accessors/timestamp_array_accessor.cc | 3 +- .../accessors/timestamp_array_accessor.h | 2 +- .../timestamp_array_accessor_test.cc | 12 +++++--- .../flight_sql/accessors/types.h | 21 +++++++------- .../flight_sql/flight_sql_result_set.cc | 23 +++++++++------ .../flight_sql/flight_sql_result_set.h | 5 ++-- .../flight_sql_stream_chunk_iterator.cc | 2 +- 29 files changed, 132 insertions(+), 120 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc index 872aca7417711..7f6bf0ad4d739 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc @@ -31,25 +31,31 @@ namespace { inline void MoveSingleCellToBinaryBuffer(ColumnBinding *binding, BinaryArray *array, int64_t i, - int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { const char *value = array->Value(i).data(); size_t size_in_bytes = array->value_length(i); - // TODO: Handle truncation + size_t remaining_length = static_cast(size_in_bytes - value_offset); size_t value_length = - std::min(static_cast(size_in_bytes - value_offset), + std::min(remaining_length, binding->buffer_length); - if (size_in_bytes - value_offset > binding->buffer_length) { - diagnostics.AddTruncationWarning(); - } auto *byte_buffer = static_cast(binding->buffer) + i * binding->buffer_length; memcpy(byte_buffer, ((char *)value) + value_offset, value_length); + if (remaining_length > binding->buffer_length) { + 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(size_in_bytes); + binding->strlen_buffer[i] = static_cast(remaining_length); } } @@ -64,8 +70,8 @@ BinaryArrayFlightSqlAccessor::BinaryArrayFlightSqlAccessor( template <> void BinaryArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, BinaryArray *array, int64_t i, - int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { - MoveSingleCellToBinaryBuffer(binding, array, i, value_offset, diagnostics); + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { + MoveSingleCellToBinaryBuffer(binding, array, i, value_offset, update_value_offset, diagnostics); } template class BinaryArrayFlightSqlAccessor; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h index eb760d5253ad9..1d322874de1fe 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h @@ -35,7 +35,7 @@ class BinaryArrayFlightSqlAccessor explicit BinaryArrayFlightSqlAccessor(Array *array); void MoveSingleCell_impl(ColumnBinding *binding, BinaryArray *array, - int64_t i, int64_t value_offset, odbcabstraction::Diagnostics &diagnostics); + int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc index 9c0cd19af16b7..b707c77322252 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc @@ -40,9 +40,10 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Basic) { ColumnBinding binding(CDataType_BINARY, 0, 0, buffer.data(), max_strlen, strlen_buffer.data()); + int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(values[i].length(), strlen_buffer[i]); @@ -78,18 +79,22 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Truncation) { odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); do { diagnostics.Clear(); - ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, diagnostics)); - ASSERT_EQ(values[0].length(), strlen_buffer[0]); - - int64_t chunk_length = std::min(static_cast(max_strlen), - strlen_buffer[0] - value_offset); - + int64_t original_value_offset = value_offset; + ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, true, diagnostics)); + ASSERT_EQ(values[0].length() - original_value_offset, strlen_buffer[0]); + + int64_t chunk_length = 0; + if (value_offset == -1) { + chunk_length = strlen_buffer[0]; + } else { + chunk_length = max_strlen; + } + // 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 // ASCII, this doesn't work with arbitrary binary data. ss << std::string(buffer.data(), buffer.data() + chunk_length); - value_offset += chunk_length; - } while (value_offset < strlen_buffer[0]); + } while (value_offset < values[0].length() && value_offset != -1); ASSERT_EQ(values[0], ss.str()); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc index 8912164671e76..7b7e17f35afbb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc @@ -32,7 +32,7 @@ BooleanArrayFlightSqlAccessor::BooleanArrayFlightSqlAccessor( template void BooleanArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, BooleanArray *array, int64_t i, - int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { typedef unsigned char c_type; bool value = array->Value(i); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h index af476ccaa64b8..3f174873fd720 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h @@ -36,7 +36,7 @@ class BooleanArrayFlightSqlAccessor explicit BooleanArrayFlightSqlAccessor(Array *array); void MoveSingleCell_impl(ColumnBinding *binding, BooleanArray *array, - int64_t i, int64_t value_offset, odbcabstraction::Diagnostics &diagnostics); + int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc index 6e5d9ea3764ef..5b9e282c74dd5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc @@ -37,9 +37,10 @@ TEST(BooleanArrayFlightSqlAccessor, Test_BooleanArray_CDataType_BIT) { ColumnBinding binding(CDataType_BIT, 0, 0, buffer.data(), 0, strlen_buffer.data()); + int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(unsigned char), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h index d6ed4afb6e4a6..ab7e33a83bd79 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h @@ -63,33 +63,5 @@ inline size_t CopyFromArrayValuesToBinding(const std::shared_ptr &array, return length; } -inline void MoveToCharBuffer(ColumnBinding *binding, Array *array, int64_t i, - int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { - const std::shared_ptr &scalar = array->GetScalar(i).ValueOrDie(); - const std::shared_ptr &utf8_scalar = - internal::checked_pointer_cast( - scalar->CastTo(utf8()).ValueOrDie()); - - const uint8_t *value = utf8_scalar->value->data(); - - size_t value_length = - std::min(static_cast(utf8_scalar->value->size() - value_offset), - binding->buffer_length); - - if (value_length <= static_cast(utf8_scalar->value->size() - value_offset)) { - diagnostics.AddTruncationWarning(); - } - - char *char_buffer = static_cast(binding->buffer); - memcpy(&char_buffer[i * binding->buffer_length], value + value_offset, - value_length); - if (value_length + 1 < binding->buffer_length) { - char_buffer[i * binding->buffer_length + value_length] = '\0'; - } - if (binding->strlen_buffer) { - binding->strlen_buffer[i] = utf8_scalar->value->size() + 1; - } -} - } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc index 05ff92ae51aab..6ce5473264be4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc @@ -58,7 +58,7 @@ DateArrayFlightSqlAccessor< template void DateArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, - int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { typedef unsigned char c_type; auto *buffer = static_cast(binding->buffer); auto value = convertDate(array->Value(cell_counter)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h index d6d1fff5a99b4..6b49e4b6704f3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h @@ -37,7 +37,7 @@ class DateArrayFlightSqlAccessor explicit DateArrayFlightSqlAccessor(Array *array); void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, - int64_t value_offset, + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc index eb4137036d678..bacb993b09ad2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc @@ -41,9 +41,10 @@ TEST(DateArrayAccessor, Test_Date32Array_CDataType_DATE) { ColumnBinding binding(CDataType_DATE, 0, 0, buffer.data(), 0, strlen_buffer.data()); + int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); for (size_t i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(DATE_STRUCT), strlen_buffer[i]); @@ -72,9 +73,10 @@ TEST(DateArrayAccessor, Test_Date64Array_CDataType_DATE) { ColumnBinding binding(CDataType_DATE, 0, 0, buffer.data(), 0, strlen_buffer.data()); + int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); for (size_t i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(DATE_STRUCT), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc index 4148b995d643b..3c06363bbe738 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc @@ -41,14 +41,14 @@ template DecimalArrayFlightSqlAccessor::DecimalArrayFlightSqlAccessor( Array *array) : FlightSqlAccessor>(array) { - data_type_ = std::static_pointer_cast(array->type()); + DecimalArrayFlightSqlAccessor>(array), + data_type_(std::static_pointer_cast(array->type())) { } template <> void DecimalArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, Decimal128Array *array, int64_t i, - int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { auto result = &(static_cast(binding->buffer)[i]); int32_t original_scale = data_type_->scale(); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h index 633160ceb0fbc..880f6ece599a5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h @@ -37,7 +37,7 @@ class DecimalArrayFlightSqlAccessor explicit DecimalArrayFlightSqlAccessor(Array *array); void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, - int64_t i, int64_t value_offset, + int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); private: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc index 46db7566b33ce..9b0f2cbf65acf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc @@ -75,9 +75,10 @@ void AssertNumericOutput(int input_precision, int input_scale, const std::vector ColumnBinding binding(CDataType_NUMERIC, output_precision, output_scale, buffer.data(), 0, strlen_buffer.data()); + int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(NUMERIC_STRUCT), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc index 3b95087aca8c4..fae785a109376 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc @@ -34,7 +34,7 @@ template size_t PrimitiveArrayFlightSqlAccessor::GetColumnarData_impl( const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { return CopyFromArrayValuesToBinding(sliced_array, binding); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h index fa04097948bbf..d31c26c7c61de 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h @@ -39,7 +39,8 @@ class PrimitiveArrayFlightSqlAccessor explicit PrimitiveArrayFlightSqlAccessor(Array *array); size_t GetColumnarData_impl(const std::shared_ptr &sliced_array, - ColumnBinding *binding, int64_t value_offset, odbcabstraction::Diagnostics &diagnostics); + ColumnBinding *binding, int64_t &value_offset, + bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc index 453f7a052b073..e6270bddbfdc4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc @@ -44,9 +44,10 @@ void TestPrimitiveArraySqlAccessor() { ColumnBinding binding(TARGET_TYPE, 0, 0, buffer.data(), values.size(), strlen_buffer.data()); + int64_t value_offset = 0; driver::odbcabstraction::Diagnostics diagnostics("Dummy", "Dummy", odbcabstraction::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(c_type), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc index 6a3aad34711be..ac5b081b8a50b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -31,7 +31,8 @@ template inline void MoveSingleCellToCharBuffer(CharToWStrConverter *converter, ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset, + int64_t &value_offset, + bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { const char *raw_value = array->Value(i).data(); @@ -47,8 +48,9 @@ inline void MoveSingleCellToCharBuffer(CharToWStrConverter *converter, size_in_bytes = array->value_length(i); } + size_t remaining_length = static_cast(size_in_bytes - value_offset); size_t value_length = - std::min(static_cast(size_in_bytes - value_offset), + std::min(remaining_length, binding->buffer_length); auto *byte_buffer = @@ -57,8 +59,11 @@ inline void MoveSingleCellToCharBuffer(CharToWStrConverter *converter, memcpy(char_buffer, ((char *)value) + value_offset, value_length); // Write a NUL terminator - if (binding->buffer_length > size_in_bytes + sizeof(CHAR_TYPE)) { - char_buffer[size_in_bytes / sizeof(CHAR_TYPE)] = '\0'; + if (binding->buffer_length >= remaining_length + sizeof(CHAR_TYPE)) { + char_buffer[remaining_length / sizeof(CHAR_TYPE)] = '\0'; + if (update_value_offset) { + value_offset = -1; + } } else { diagnostics.AddTruncationWarning(); size_t chars_written = binding->buffer_length / sizeof(CHAR_TYPE); @@ -67,10 +72,13 @@ inline void MoveSingleCellToCharBuffer(CharToWStrConverter *converter, if (chars_written > 0) { char_buffer[(chars_written - 1)] = '\0'; } + if (update_value_offset) { + value_offset += binding->buffer_length - sizeof(CHAR_TYPE); + } } if (binding->strlen_buffer) { - binding->strlen_buffer[i] = static_cast(size_in_bytes); + binding->strlen_buffer[i] = static_cast(remaining_length); } } @@ -86,17 +94,17 @@ StringArrayFlightSqlAccessor::StringArrayFlightSqlAccessor( template <> void StringArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { MoveSingleCellToCharBuffer(&converter_, binding, array, i, - value_offset, diagnostics); + value_offset, update_value_offset, diagnostics); } template <> void StringArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, StringArray *array, int64_t i, - int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { MoveSingleCellToCharBuffer(&converter_, binding, array, i, - value_offset, diagnostics); + value_offset, update_value_offset, diagnostics); } template class StringArrayFlightSqlAccessor; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h index 0e1b285f61aa0..ebf8eca79e088 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h @@ -37,7 +37,7 @@ class StringArrayFlightSqlAccessor explicit StringArrayFlightSqlAccessor(Array *array); void MoveSingleCell_impl(ColumnBinding *binding, StringArray *array, - int64_t i, int64_t value_offset, + int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); private: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc index 7fd0654645e6a..868215fd53707 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc @@ -39,9 +39,10 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Basic) { ColumnBinding binding(CDataType_CHAR, 0, 0, buffer.data(), max_strlen, strlen_buffer.data()); + int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(values[i].length(), strlen_buffer[i]); @@ -72,14 +73,12 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Truncation) { odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); do { diagnostics.Clear(); - ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, diagnostics)); - ASSERT_EQ(values[0].length(), strlen_buffer[0]); + int64_t original_value_offset = value_offset; + ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, true, diagnostics)); + ASSERT_EQ(values[0].length() - original_value_offset, strlen_buffer[0]); - int64_t chunk_length = std::min(static_cast(max_strlen), - strlen_buffer[0] - value_offset); ss << buffer.data(); - value_offset += chunk_length - 1; - } while (value_offset < strlen_buffer[0] - 1); + } while (value_offset < values[0].length() && value_offset != -1); ASSERT_EQ(values[0], ss.str()); } @@ -98,9 +97,10 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Basic) { ColumnBinding binding(CDataType_WCHAR, 0, 0, buffer.data(), max_strlen, strlen_buffer.data()); + int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(values[i].length() * sizeof(SqlWChar), strlen_buffer[i]); @@ -133,15 +133,12 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Truncation) { std::basic_string finalStr; driver::odbcabstraction::Diagnostics diagnostics("Dummy", "Dummy", odbcabstraction::V_3); do { - ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, diagnostics)); - ASSERT_EQ(values[0].length() * sizeof(SqlWChar), strlen_buffer[0]); + int64_t original_value_offset = value_offset; + ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, true, diagnostics)); + ASSERT_EQ(values[0].length() * sizeof(SqlWChar) - original_value_offset, strlen_buffer[0]); - int64_t chunk_length = - std::min(static_cast(max_strlen * sizeof(SqlWChar)), - strlen_buffer[0] - value_offset); finalStr += std::basic_string(buffer.data()); - value_offset += chunk_length - sizeof(SqlWChar); - } while (value_offset < strlen_buffer[0] - sizeof(SqlWChar)); + } while (value_offset < values[0].length() * sizeof(SqlWChar) && value_offset != -1); auto expected = CharToWStrConverter().from_bytes(values[0].c_str()); auto actual = finalStr; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc index 0bce3a31f402b..4065811419daf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc @@ -48,7 +48,7 @@ TimeArrayFlightSqlAccessor< template void TimeArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, - int64_t value_offset, odbcabstraction::Diagnostics &diagnostic) { + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostic) { typedef unsigned char c_type; auto *buffer = static_cast(binding->buffer); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h index 3fe4f932a46f9..3dbe6010d0437 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h @@ -37,7 +37,7 @@ class TimeArrayFlightSqlAccessor explicit TimeArrayFlightSqlAccessor(Array *array); void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, - int64_t value_offset, + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostic); }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc index c4ff63c13571d..b1b2c52f1912c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc @@ -43,9 +43,10 @@ TEST(TEST_TIME32, TIME_WITH_SECONDS) { ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer.data()); + int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(t32_values.size(), - accessor.GetColumnarData(&binding, 0, t32_values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, t32_values.size(), value_offset, false, diagnostics)); for (size_t i = 0; i < t32_values.size(); ++i) { ASSERT_EQ(sizeof(TIME_STRUCT), strlen_buffer[i]); @@ -75,9 +76,10 @@ TEST(TEST_TIME32, TIME_WITH_MILLI) { ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer.data()); + int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(t32_values.size(), - accessor.GetColumnarData(&binding, 0, t32_values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, t32_values.size(), value_offset, false, diagnostics)); for (size_t i = 0; i < t32_values.size(); ++i) { ASSERT_EQ(sizeof(TIME_STRUCT), strlen_buffer[i]); @@ -110,9 +112,10 @@ TEST(TEST_TIME64, TIME_WITH_MICRO) { ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer.data()); + int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(t64_values.size(), - accessor.GetColumnarData(&binding, 0, t64_values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, t64_values.size(), value_offset, false, diagnostics)); for (size_t i = 0; i < t64_values.size(); ++i) { ASSERT_EQ(sizeof(TIME_STRUCT), strlen_buffer[i]); @@ -145,9 +148,10 @@ TEST(TEST_TIME64, TIME_WITH_NANO) { ColumnBinding binding(CDataType_TIME, 0, 0, buffer.data(), 0, strlen_buffer.data()); + int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(t64_values.size(), - accessor.GetColumnarData(&binding, 0, t64_values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, t64_values.size(), value_offset, false, diagnostics)); for (size_t i = 0; i < t64_values.size(); ++i) { ASSERT_EQ(sizeof(TIME_STRUCT), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc index 4627b13c8fd93..897a9bf9f2036 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc @@ -59,7 +59,8 @@ void TimestampArrayFlightSqlAccessor::MoveSingleCell_impl(ColumnBinding *binding, TimestampArray *array, int64_t cell_counter, - int64_t value_offset, + int64_t &value_offset, + bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { typedef unsigned char c_type; auto *buffer = static_cast(binding->buffer); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h index 3bf47db6e1cb2..58ff94e39d60f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h @@ -36,7 +36,7 @@ class TimestampArrayFlightSqlAccessor explicit TimestampArrayFlightSqlAccessor(Array *array); void MoveSingleCell_impl(ColumnBinding *binding, TimestampArray *array, int64_t cell_counter, - int64_t value_offset, + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); private: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc index cea226282c1ef..95370a3e2a354 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc @@ -42,10 +42,11 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MILI) { std::vector buffer(values.size()); std::vector strlen_buffer(values.size()); + int64_t value_offset = 0; ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); for (size_t i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); @@ -80,11 +81,12 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_SECONDS) { std::vector buffer(values.size()); std::vector strlen_buffer(values.size()); + int64_t value_offset = 0; ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); for (size_t i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); @@ -117,11 +119,12 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MICRO) { std::vector buffer(values.size()); std::vector strlen_buffer(values.size()); + int64_t value_offset = 0; ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); for (size_t i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); @@ -155,11 +158,12 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_NANO) { std::vector buffer(values.size()); std::vector strlen_buffer(values.size()); + int64_t value_offset = 0; ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), 0, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); for (size_t i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h index b59224d5b5202..708f5768be96b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h @@ -63,7 +63,7 @@ class Accessor { /// \brief Populates next cells virtual size_t GetColumnarData(ColumnBinding *binding, int64_t starting_row, - size_t cells, int64_t value_offset, + size_t cells, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) = 0; }; @@ -75,27 +75,28 @@ class FlightSqlAccessor : public Accessor { array_(arrow::internal::checked_cast(array)) {} size_t GetColumnarData(ColumnBinding *binding, int64_t starting_row, - size_t cells, int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) override { + size_t cells, int64_t &value_offset, bool update_value_offset, + odbcabstraction::Diagnostics &diagnostics) override { const std::shared_ptr &array = array_->Slice(starting_row, static_cast(cells)); return GetColumnarData( arrow::internal::checked_pointer_cast(array), binding, - value_offset, diagnostics); + value_offset, update_value_offset, diagnostics); } private: ARROW_ARRAY *array_; size_t GetColumnarData(const std::shared_ptr &sliced_array, - ColumnBinding *binding, int64_t value_offset, + ColumnBinding *binding, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { return static_cast(this)->GetColumnarData_impl( - sliced_array, binding, value_offset, diagnostics); + sliced_array, binding, value_offset, update_value_offset, diagnostics); } size_t GetColumnarData_impl(const std::shared_ptr &sliced_array, - ColumnBinding *binding, int64_t value_offset, + ColumnBinding *binding, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { int64_t length = sliced_array->length(); for (int64_t i = 0; i < length; ++i) { @@ -108,7 +109,7 @@ class FlightSqlAccessor : public Accessor { } else { // TODO: Optimize this by creating different versions of MoveSingleCell // depending on if strlen_buffer is null. - MoveSingleCell(binding, sliced_array.get(), i, value_offset, + MoveSingleCell(binding, sliced_array.get(), i, value_offset, update_value_offset, diagnostics); } } @@ -117,13 +118,13 @@ class FlightSqlAccessor : public Accessor { } void MoveSingleCell(ColumnBinding *binding, ARROW_ARRAY *array, int64_t i, - int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { return static_cast(this)->MoveSingleCell_impl(binding, array, i, - value_offset, diagnostics); + value_offset, update_value_offset, diagnostics); } void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, - int64_t i, int64_t value_offset, odbcabstraction::Diagnostics &diagnostics) { + int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { std::stringstream ss; ss << "Unknown type conversion from StringArray to target C type " << TARGET_TYPE; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index f8f5c41d5869c..bac18d1470aa6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -46,15 +46,15 @@ FlightSqlResultSet::FlightSqlResultSet( const std::shared_ptr &flight_info, const std::shared_ptr &transformer, odbcabstraction::Diagnostics& diagnostics) - : num_binding_(0), current_row_(0), - chunk_iterator_(flight_sql_client, call_options, flight_info), + : chunk_iterator_(flight_sql_client, call_options, flight_info), transformer_(transformer), metadata_(transformer ? new FlightSqlResultSetMetadata( transformer->GetTransformedSchema()) : new FlightSqlResultSetMetadata(flight_info)), columns_(metadata_->GetColumnCount()), - get_data_offsets_(metadata_->GetColumnCount()), - diagnostics_(diagnostics) { + get_data_offsets_(metadata_->GetColumnCount(), 0), + diagnostics_(diagnostics), + current_row_(0), num_binding_(0), reset_get_data_(false) { current_chunk_.data = nullptr; for (int i = 0; i < columns_.size(); ++i) { @@ -79,7 +79,7 @@ size_t FlightSqlResultSet::Move(size_t rows) { } // Reset GetData value offsets. - if (num_binding_ != get_data_offsets_.size()) { + if (num_binding_ != get_data_offsets_.size() && reset_get_data_) { std::fill(get_data_offsets_.begin(), get_data_offsets_.end(), 0); } @@ -113,8 +113,9 @@ size_t FlightSqlResultSet::Move(size_t rows) { if (!column.is_bound) continue; + int64_t value_offset = 0; size_t accessor_rows = column.GetAccessorForBinding()->GetColumnarData( - &column.binding, current_row_, rows_to_fetch, 0, diagnostics_); + &column.binding, current_row_, rows_to_fetch, value_offset, false, diagnostics_); if (rows_to_fetch != accessor_rows) { throw DriverException( @@ -142,18 +143,24 @@ void FlightSqlResultSet::Cancel() { bool FlightSqlResultSet::GetData(int column_n, int16_t target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) { + reset_get_data_ = true; + // Check if the offset is already at the end. + int64_t& value_offset = get_data_offsets_[column_n - 1]; + if (value_offset == -1) { + return false; + } + ColumnBinding binding(ConvertCDataTypeFromV2ToV3(target_type), precision, scale, buffer, buffer_length, strlen_buffer); auto &column = columns_[column_n - 1]; Accessor *accessor = column.GetAccessorForGetData(binding.target_type); - int64_t value_offset = get_data_offsets_[column_n - 1]; // Note: current_row_ is always positioned at the index _after_ the one we are // on after calling Move(). So if we want to get data from the _last_ row // fetched, we need to subtract one from the current row. - accessor->GetColumnarData(&binding, current_row_ - 1, 1, value_offset, diagnostics_); + accessor->GetColumnarData(&binding, current_row_ - 1, 1, value_offset, true, diagnostics_); // If there was truncation, the converter would have reported it to the diagnostics. return diagnostics_.HasWarning(); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index 64fe361915dc2..6fe229bb840e1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -53,8 +53,6 @@ class FlightSqlResultSetColumn; class FlightSqlResultSet : public ResultSet { private: - int num_binding_; - int64_t current_row_; FlightStreamChunkIterator chunk_iterator_; FlightStreamChunk current_chunk_; std::shared_ptr schema_; @@ -63,6 +61,9 @@ class FlightSqlResultSet : public ResultSet { std::vector columns_; std::vector get_data_offsets_; odbcabstraction::Diagnostics &diagnostics_; + int64_t current_row_; + int num_binding_; + bool reset_get_data_; public: ~FlightSqlResultSet() override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc index 3bfe21a7fc049..c1924dc67ade1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc @@ -54,7 +54,7 @@ bool FlightStreamChunkIterator::GetNext(FlightStreamChunk *chunk) { if (chunk->data != nullptr) { return true; } - stream_readers_it_++; + ++stream_readers_it_; } return false; } From 58bfc27fbc9314f9770dd3c3e07f3a7da0f494d2 Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 6 Jun 2022 03:12:10 -0700 Subject: [PATCH 116/183] Migrate classes from warpdrive Migrate newly-created code for warpdrive (ODBCHandle and related classes, AttributeUtils, EncodingUtils, and TypeUtilities.h) to a new odbc_impl directory under ODBCAbstraction. Move driver detail interfaces to an spi directory under ODBCAbstraction. Clean-up CMakeFiles such that sources are alphabetical and always include headers to make Visual Studio project generation easier to navigate/search. Clean-up unnecessary includes and fix up incorrect location for pragma once. Fix includes to use angle-brackets for external dependencies and quotes for internal headers. Change-Id: I395f0a2e5b20e2d0bf0cc4c32caeb6006e78e143 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 44 +- .../flight_sql/flight_sql_auth_method.h | 2 +- .../flight_sql/flight_sql_connection.h | 2 +- .../flight_sql_get_tables_reader.cc | 5 +- .../flight_sql/flight_sql_get_tables_reader.h | 3 - .../flight_sql_get_type_info_reader.cc | 4 +- .../flight_sql_get_type_info_reader.h | 3 - .../flight_sql/flight_sql_result_set.cc | 1 - .../flight_sql/flight_sql_result_set.h | 3 +- .../flight_sql_result_set_accessors.cc | 2 +- .../flight_sql_result_set_accessors.h | 2 +- .../flight_sql_result_set_metadata.cc | 4 +- .../flight_sql_result_set_metadata.h | 2 +- .../flight_sql/flight_sql_ssl_config.h | 2 +- .../flight_sql/flight_sql_statement.cc | 2 - .../flight_sql/flight_sql_statement.h | 3 +- .../flight_sql_statement_get_tables.h | 2 +- .../flight_sql/get_info_cache.h | 2 +- .../include/flight_sql/config/configuration.h | 2 +- .../include/flight_sql/flight_sql_driver.h | 2 +- .../flight_sql/json_converter.cc | 1 - .../flightsql-odbc/flight_sql/utils.cc | 6 +- .../odbcabstraction/CMakeLists.txt | 26 +- .../include/odbcabstraction/calendar_utils.h | 4 +- .../include/odbcabstraction/exceptions.h | 2 +- .../odbc_impl/AttributeUtils.h | 158 ++++ .../odbcabstraction/odbc_impl/EncodingUtils.h | 93 +++ .../odbc_impl/ODBCConnection.h | 97 +++ .../odbc_impl/ODBCDescriptor.h | 154 ++++ .../odbc_impl/ODBCEnvironment.h | 61 ++ .../odbcabstraction/odbc_impl/ODBCHandle.h | 95 +++ .../odbcabstraction/odbc_impl/ODBCStatement.h | 123 +++ .../odbcabstraction/odbc_impl/TypeUtilities.h | 42 + .../odbcabstraction/{ => spi}/connection.h | 0 .../odbcabstraction/{ => spi}/driver.h | 0 .../odbcabstraction/{ => spi}/result_set.h | 0 .../{ => spi}/result_set_metadata.h | 0 .../odbcabstraction/{ => spi}/statement.h | 0 .../include/odbcabstraction/utils.h | 6 +- .../odbc_impl/ODBCConnection.cc | 705 +++++++++++++++++ .../odbc_impl/ODBCDescriptor.cc | 545 +++++++++++++ .../odbc_impl/ODBCEnvironment.cc | 80 ++ .../odbc_impl/ODBCStatement.cc | 734 ++++++++++++++++++ .../flightsql-odbc/odbcabstraction/utils.cc | 6 +- 44 files changed, 2983 insertions(+), 47 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/AttributeUtils.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCConnection.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCEnvironment.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCHandle.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/TypeUtilities.h rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/{ => spi}/connection.h (100%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/{ => spi}/driver.h (100%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/{ => spi}/result_set.h (100%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/{ => spi}/result_set_metadata.h (100%) rename flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/{ => spi}/statement.h (100%) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCEnvironment.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index efb85d6521ade..7d659af797f39 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -150,40 +150,76 @@ endif() enable_testing() set(ARROW_ODBC_SPI_SOURCES + 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 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_columns.cc - flight_sql_ssl_config.cc - flight_sql_get_tables_reader.cc - flight_sql_get_type_info_reader.cc + flight_sql_statement_get_type_info.h flight_sql_stream_chunk_iterator.cc + flight_sql_stream_chunk_iterator.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) if (WIN32) include_directories(flight_sql/include) list(APPEND ARROW_ODBC_SPI_SOURCES + 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 diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index 61ba4d1d316fe..b07b3f4cea75d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 95a5da1adc994..844747178503d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -17,7 +17,7 @@ #pragma once -#include +#include #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc index 0fe3f9ea16c3b..99d083c48d596 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc @@ -17,7 +17,10 @@ #include "flight_sql_get_tables_reader.h" #include -#include "arrow/io/memory.h" +#include +#include +#include +#include #include "utils.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.h index 119af90082ed4..1205fc1f34719 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.h @@ -16,9 +16,6 @@ // under the License. #include "record_batch_transformer.h" -#include -#include -#include #include namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.cc index ec7595e147960..f55e8f46a7ec3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.cc @@ -17,8 +17,8 @@ #include "flight_sql_get_type_info_reader.h" #include -#include "arrow/io/memory.h" -#include "arrow/array.h" +#include +#include #include "utils.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.h index 6349a29cf96cc..5742df1b96507 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.h @@ -16,9 +16,6 @@ // under the License. #include "record_batch_transformer.h" -#include -#include -#include #include namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index bac18d1470aa6..1826b006307cd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -20,7 +20,6 @@ #include #include -#include #include #include "flight_sql_result_set_column.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index 6fe229bb840e1..aeeefd78efee8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -26,10 +26,9 @@ #include #include #include -#include #include #include -#include +#include #include namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index e7a9ed71c5f83..e8738968221b0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -18,7 +18,7 @@ #include "accessors/main.h" #include -#include "boost/functional/hash.hpp" +#include namespace driver { namespace flight_sql { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h index bcb788436618a..ddc6017f9a8a1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h @@ -17,7 +17,7 @@ #pragma once -#include "arrow/type_fwd.h" +#include #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index e9ac85f1b2ce8..b0fb8c0935705 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -17,8 +17,8 @@ #include "flight_sql_result_set_metadata.h" #include -#include "arrow/flight/sql/column_metadata.h" -#include "arrow/util/key_value_metadata.h" +#include +#include #include "utils.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h index d851baefb49eb..9c74a22e48093 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h @@ -19,7 +19,7 @@ #include #include -#include +#include namespace driver { namespace flight_sql { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.h index d818d513af2eb..ca3bb38d4ce81 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.h @@ -17,7 +17,7 @@ #pragma once -#include "arrow/flight/types.h" +#include #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index 1b1d4fe6435a2..96a553f94bdc9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -24,7 +24,6 @@ #include "flight_sql_statement_get_type_info.h" #include "record_batch_transformer.h" #include "utils.h" -#include #include #include #include @@ -45,7 +44,6 @@ using arrow::flight::Location; using arrow::flight::TimeoutDuration; using arrow::flight::sql::FlightSqlClient; using arrow::flight::sql::PreparedStatement; -using arrow::flight::sql::SqlSchema; using driver::odbcabstraction::DriverException; using driver::odbcabstraction::ResultSet; using driver::odbcabstraction::ResultSetMetadata; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h index 7786380643762..310a7ddfa7ff2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h @@ -17,9 +17,8 @@ #pragma once -#include "arrow/flight/sql/client.h" #include "flight_sql_statement_get_tables.h" -#include +#include #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h index 9a548ed488395..d31e416a08193 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h @@ -18,7 +18,7 @@ #pragma once #include "arrow/flight/types.h" -#include +#include #include #include "record_batch_transformer.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h index e72d8e83c7eb2..8ee4a5c9ba193 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include namespace arrow { namespace flight { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/configuration.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/configuration.h index 6e6c52bdb5fe4..2f9b02ec6139e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/configuration.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/configuration.h @@ -21,7 +21,7 @@ #include "winuser.h" #include #include -#include +#include namespace driver { namespace flight_sql { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h index 497f1a6d79cf9..f0ac600f2c03b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h @@ -17,7 +17,7 @@ #pragma once -#include +#include #include namespace driver { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc index efad0c81f67e1..50e61c9e25d66 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include "utils.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 068059cb789c1..8fe5131226693 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -16,13 +16,13 @@ // under the License. #include "utils.h" -#include "arrow/builder.h" -#include "arrow/type_fwd.h" +#include +#include #include #include #include #include -#include +#include "json_converter.h" namespace driver { namespace flight_sql { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index 8bd11104c24b7..ef12e7d07ed0a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -19,14 +19,36 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) include_directories(include) -add_library(odbcabstraction +add_library(odbcabstraction + include/odbcabstraction/calendar_utils.h include/odbcabstraction/diagnostics.h include/odbcabstraction/error_codes.h + include/odbcabstraction/exceptions.h + include/odbcabstraction/platform.h + include/odbcabstraction/types.h include/odbcabstraction/utils.h + include/odbcabstraction/odbc_impl/AttributeUtils.h + include/odbcabstraction/odbc_impl/EncodingUtils.h + include/odbcabstraction/odbc_impl/ODBCConnection.h + include/odbcabstraction/odbc_impl/ODBCDescriptor.h + include/odbcabstraction/odbc_impl/ODBCEnvironment.h + include/odbcabstraction/odbc_impl/ODBCHandle.h + include/odbcabstraction/odbc_impl/ODBCStatement.h + include/odbcabstraction/odbc_impl/TypeUtilities.h + include/odbcabstraction/spi/connection.h + include/odbcabstraction/spi/driver.h + include/odbcabstraction/spi/result_set.h + include/odbcabstraction/spi/result_set_metadata.h + include/odbcabstraction/spi/statement.h calendar_utils.cc diagnostics.cc exceptions.cc - utils.cc) + utils.cc + odbc_impl/ODBCConnection.cc + odbc_impl/ODBCDescriptor.cc + odbc_impl/ODBCEnvironment.cc + odbc_impl/ODBCStatement.cc +) set_target_properties(odbcabstraction PROPERTIES diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h index caadf964866ea..ef82d884078f9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h @@ -15,11 +15,11 @@ // specific language governing permissions and limitations // under the License. +#pragma once + #include #include -#pragma once - namespace driver { namespace odbcabstraction { void GetTimeForMillisSinceEpoch(tm& date, int64_t value); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h index d60a23c48e1bf..c1f17c805cae9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h @@ -20,7 +20,7 @@ #include #include #include -#include "error_codes.h" +#include namespace driver { namespace odbcabstraction { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/AttributeUtils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/AttributeUtils.h new file mode 100644 index 0000000000000..e53d9c8b7d304 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/AttributeUtils.h @@ -0,0 +1,158 @@ +// 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. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace ODBC { +template +inline void GetAttribute(T attributeValue, SQLPOINTER output, O outputSize, + O *outputLenPtr) { + if (output) { + T *typedOutput = reinterpret_cast(output); + *typedOutput = attributeValue; + } + + if (outputLenPtr) { + *outputLenPtr = sizeof(T); + } +} + +template +inline SQLRETURN GetAttributeUTF8(const std::string &attributeValue, + SQLPOINTER output, O outputSize, O *outputLenPtr) { + if (output) { + size_t outputLenBeforeNul = + std::min(static_cast(attributeValue.size()), static_cast(outputSize - 1)); + memcpy(output, attributeValue.c_str(), outputLenBeforeNul); + reinterpret_cast(output)[outputLenBeforeNul] = '\0'; + } + + if (outputLenPtr) { + *outputLenPtr = static_cast(attributeValue.size()); + } + + if (output && outputSize < attributeValue.size() + 1) { + return SQL_SUCCESS_WITH_INFO; + } + return SQL_SUCCESS; +} + +template +inline SQLRETURN GetAttributeUTF8(const std::string &attributeValue, + SQLPOINTER output, O outputSize, O *outputLenPtr, driver::odbcabstraction::Diagnostics& diagnostics) { + SQLRETURN result = GetAttributeUTF8(attributeValue, output, outputSize, outputLenPtr); + if (SQL_SUCCESS_WITH_INFO == result) { + diagnostics.AddTruncationWarning(); + } + return result; +} + +template +inline SQLRETURN GetAttributeSQLWCHAR(const std::string &attributeValue, bool isLengthInBytes, + SQLPOINTER output, O outputSize, + O *outputLenPtr) { + size_t result = ConvertToSqlWChar( + attributeValue, reinterpret_cast(output), isLengthInBytes ? outputSize : outputSize * sizeof(SQLWCHAR)); + + if (outputLenPtr) { + *outputLenPtr = static_cast(isLengthInBytes ? result : result / sizeof(SQLWCHAR)); + } + + if (output && outputSize < result + (isLengthInBytes ? sizeof(SQLWCHAR) : 1)) { + return SQL_SUCCESS_WITH_INFO; + } + return SQL_SUCCESS; +} + +template +inline SQLRETURN GetAttributeSQLWCHAR(const std::string &attributeValue, bool isLengthInBytes, + SQLPOINTER output, O outputSize, + O *outputLenPtr, driver::odbcabstraction::Diagnostics& diagnostics) { + SQLRETURN result = GetAttributeSQLWCHAR(attributeValue, isLengthInBytes, output, outputSize, outputLenPtr); + if (SQL_SUCCESS_WITH_INFO == result) { + diagnostics.AddTruncationWarning(); + } + return result; +} + +template +inline SQLRETURN +GetStringAttribute(bool isUnicode, const std::string &attributeValue, bool isLengthInBytes, + SQLPOINTER output, O outputSize, O *outputLenPtr, driver::odbcabstraction::Diagnostics& diagnostics) { + SQLRETURN result = SQL_SUCCESS; + if (isUnicode) { + result = GetAttributeSQLWCHAR(attributeValue, isLengthInBytes, output, outputSize, outputLenPtr); + } else { + result = GetAttributeUTF8(attributeValue, output, outputSize, outputLenPtr); + } + + if (SQL_SUCCESS_WITH_INFO == result) { + diagnostics.AddTruncationWarning(); + } + return result; +} + +template +inline void SetAttribute(SQLPOINTER newValue, T &attributeToWrite) { + SQLLEN valueAsLen = reinterpret_cast(newValue); + attributeToWrite = static_cast(valueAsLen); +} + +template +inline void SetPointerAttribute(SQLPOINTER newValue, T &attributeToWrite) { + attributeToWrite = static_cast(newValue); +} + +inline void SetAttributeUTF8(SQLPOINTER newValue, SQLINTEGER inputLength, + std::string &attributeToWrite) { + const char *newValueAsChar = static_cast(newValue); + attributeToWrite.assign(newValueAsChar, inputLength == SQL_NTS + ? strlen(newValueAsChar) + : inputLength); +} + +inline void SetAttributeSQLWCHAR(SQLPOINTER newValue, + SQLINTEGER inputLengthInBytes, + std::string &attributeToWrite) { + SqlWString wstr; + if (inputLengthInBytes == SQL_NTS) { + wstr.assign(reinterpret_cast(newValue)); + } else { + wstr.assign(reinterpret_cast(newValue), + inputLengthInBytes / sizeof(SqlWChar)); + } + attributeToWrite = CharToWStrConverter().to_bytes(wstr.c_str()); +} + +template +void CheckIfAttributeIsSetToOnlyValidValue(SQLPOINTER value, T allowed_value) { + if (static_cast(reinterpret_cast(value)) != allowed_value) { + throw driver::odbcabstraction::DriverException("Optional feature not implemented", "HYC00"); + } +} +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h new file mode 100644 index 0000000000000..68d5815df2bd6 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h @@ -0,0 +1,93 @@ +// 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. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING + +namespace ODBC { + #ifdef WITH_IODBC + typedef char32_t SqlWChar; + typedef std::u32string SqlWString; + typedef std::wstring_convert, char32_t> CharToWStrConverter; + #else + typedef char16_t SqlWChar; + typedef std::u16string SqlWString; + typedef std::wstring_convert, char16_t> CharToWStrConverter; + #endif + + // Return the number of bytes required for the conversion. + inline size_t ConvertToSqlWChar(const std::string& str, SQLWCHAR* buffer, SQLLEN bufferSizeInBytes) { + SqlWString wstr = CharToWStrConverter().from_bytes(str); + SQLLEN valueLengthInBytes = wstr.size() * sizeof(SqlWChar); + + if (buffer) { + memcpy(buffer, wstr.data(), std::min(static_cast(wstr.size() * sizeof(SqlWChar)), bufferSizeInBytes)); + + // Write a NUL terminator + if (bufferSizeInBytes >= valueLengthInBytes + sizeof(SqlWChar)) { + reinterpret_cast(buffer)[wstr.size()] = '\0'; + } else { + SQLLEN numCharsWritten = bufferSizeInBytes / sizeof(SqlWChar); + // If we failed to even write one char, the buffer is too small to hold a NUL-terminator. + if (numCharsWritten > 0) { + reinterpret_cast(buffer)[numCharsWritten-1] = '\0'; + } + } + } + return valueLengthInBytes; + } + + // Return the number of bytes required for the conversion. + inline size_t ConvertToSqlWChar(const SQLCHAR* str, SQLLEN numChars, SQLWCHAR* buffer, SQLLEN bufferSizeInBytes) { + if (numChars != SQL_NTS) { + return ConvertToSqlWChar(std::string(reinterpret_cast(str), numChars), buffer, bufferSizeInBytes); + } + return ConvertToSqlWChar(std::string(reinterpret_cast(str)), buffer, bufferSizeInBytes); + } + + // Return the number of bytes required for the conversion. + inline size_t ConvertToSqlChar(const SQLWCHAR* str, SQLLEN numChars, SQLCHAR* buffer, SQLLEN bufferSizeInBytes) { + SqlWString wstr; + if (numChars != SQL_NTS) { + wstr = SqlWString(reinterpret_cast(str), numChars); + } else { + wstr = SqlWString(reinterpret_cast(str)); + } + + std::string converted = CharToWStrConverter().to_bytes(wstr.c_str()); + if (buffer) { + memcpy(buffer, converted.c_str(), std::min(bufferSizeInBytes, static_cast(converted.size()))); + if (bufferSizeInBytes >= converted.size() + 1) { + buffer[converted.size()] = '\0'; + } else if (bufferSizeInBytes > 0){ + buffer[bufferSizeInBytes - 1] = '\0'; + } + } + return converted.size(); + } +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCConnection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCConnection.h new file mode 100644 index 0000000000000..08ca1790832a9 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCConnection.h @@ -0,0 +1,97 @@ +// 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. + +#pragma once + +#include + +#include +#include +#include +#include +#include + +namespace ODBC +{ + class ODBCEnvironment; + class ODBCDescriptor; + class ODBCStatement; +} + +/** + * @brief An abstraction over an ODBC connection handle. This also wraps an SPI Connection. + */ +namespace ODBC +{ +class ODBCConnection : public ODBCHandle { + public: + ODBCConnection(const ODBCConnection&) = delete; + ODBCConnection& operator=(const ODBCConnection&) = delete; + + ODBCConnection(ODBCEnvironment& environment, + std::shared_ptr spiConnection); + + driver::odbcabstraction::Diagnostics& GetDiagnostics_Impl(); + + const std::string& GetDSN() const; + bool isConnected() const; + void connect(std::string dsn, const driver::odbcabstraction::Connection::ConnPropertyMap &properties, + std::vector &missing_properties); + + void GetInfo(SQLUSMALLINT infoType, SQLPOINTER value, SQLSMALLINT bufferLength, SQLSMALLINT* outputLength, bool isUnicode); + void SetConnectAttr(SQLINTEGER attribute, SQLPOINTER value, SQLINTEGER stringLength, bool isUnicode); + void GetConnectAttr(SQLINTEGER attribute, SQLPOINTER value, SQLINTEGER bufferLength, SQLINTEGER* outputLength, bool isUnicode); + + ~ODBCConnection() = default; + + inline ODBCStatement& GetTrackingStatement() { + return *m_attributeTrackingStatement; + } + + void disconnect(); + + void releaseConnection(); + + std::shared_ptr createStatement(); + void dropStatement(ODBCStatement* statement); + + std::shared_ptr createDescriptor(); + void dropDescriptor(ODBCDescriptor* descriptor); + + inline bool IsOdbc2Connection() const { + return m_is2xConnection; + } + + /// @return the DSN or empty string if Driver was used. + static std::string getPropertiesFromConnString(const std::string& connStr, + driver::odbcabstraction::Connection::ConnPropertyMap &properties); + + private: + ODBCEnvironment& m_environment; + std::shared_ptr m_spiConnection; + // Extra ODBC statement that's used to track and validate when statement attributes are + // set through the connection handle. These attributes get copied to new ODBC statements + // when they are allocated. + std::shared_ptr m_attributeTrackingStatement; + std::vector > m_statements; + std::vector > m_descriptors; + std::string m_dsn; + const bool m_is2xConnection; + bool m_isConnected; +}; + +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h new file mode 100644 index 0000000000000..7bea11aa8569f --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h @@ -0,0 +1,154 @@ +// 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. + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +namespace driver { +namespace odbcabstraction { + class ResultSetMetadata; +} +} +namespace ODBC { + class ODBCConnection; + class ODBCStatement; +} + +namespace ODBC +{ + struct DescriptorRecord { + std::string m_baseColumnName; + std::string m_baseTableName; + std::string m_catalogName; + std::string m_label; + std::string m_literalPrefix; + std::string m_literalSuffix; + std::string m_localTypeName; + std::string m_name; + std::string m_schemaName; + std::string m_tableName; + std::string m_typeName; + SQLPOINTER m_dataPtr = NULL; + SQLLEN* m_indicatorPtr = NULL; + SQLLEN m_displaySize = 0; + SQLLEN m_octetLength = 0; + SQLULEN m_length = 0; + SQLINTEGER m_autoUniqueValue; + SQLINTEGER m_caseSensitive = SQL_TRUE; + SQLINTEGER m_datetimeIntervalPrecision = 0; + SQLINTEGER m_numPrecRadix = 0; + SQLSMALLINT m_conciseType = SQL_C_DEFAULT; + SQLSMALLINT m_datetimeIntervalCode = 0; + SQLSMALLINT m_fixedPrecScale = 0; + SQLSMALLINT m_nullable = SQL_NULLABLE_UNKNOWN; + SQLSMALLINT m_paramType = SQL_PARAM_INPUT; + SQLSMALLINT m_precision = 0; + SQLSMALLINT m_rowVer = 0; + SQLSMALLINT m_scale = 0; + SQLSMALLINT m_searchable = SQL_SEARCHABLE; + SQLSMALLINT m_type = SQL_C_DEFAULT; + SQLSMALLINT m_unnamed = SQL_TRUE; + SQLSMALLINT m_unsigned = SQL_FALSE; + SQLSMALLINT m_updatable = SQL_FALSE; + bool m_isBound = false; + + void CheckConsistency(); + }; + + class ODBCDescriptor : public ODBCHandle{ + public: + /** + * @brief Construct a new ODBCDescriptor object. Link the descriptor to a connection, + * if applicable. A nullptr should be supplied for conn if the descriptor should not be linked. + */ + ODBCDescriptor(driver::odbcabstraction::Diagnostics& baseDiagnostics, + ODBCConnection* conn, ODBCStatement* stmt, bool isAppDescriptor, bool isWritable, bool is2xConnection); + + driver::odbcabstraction::Diagnostics& GetDiagnostics_Impl(); + + ODBCConnection &GetConnection(); + + void SetHeaderField(SQLSMALLINT fieldIdentifier, SQLPOINTER value, SQLINTEGER bufferLength); + void SetField(SQLSMALLINT recordNumber, SQLSMALLINT fieldIdentifier, SQLPOINTER value, SQLINTEGER bufferLength); + void GetHeaderField(SQLSMALLINT fieldIdentifier, SQLPOINTER value, SQLINTEGER bufferLength, SQLINTEGER* outputLength) const; + void GetField(SQLSMALLINT recordNumber, SQLSMALLINT fieldIdentifier, SQLPOINTER value, SQLINTEGER bufferLength, SQLINTEGER* outputLength); + SQLSMALLINT getAllocType() const; + bool IsAppDescriptor() const; + bool HaveBindingsChanged() const; + void RegisterToStatement(ODBCStatement* statement, bool isApd); + void DetachFromStatement(ODBCStatement* statement, bool isApd); + void ReleaseDescriptor(); + + void PopulateFromResultSetMetadata(driver::odbcabstraction::ResultSetMetadata* rsmd); + + const std::vector& GetRecords() const; + std::vector& GetRecords(); + + void BindCol(SQLSMALLINT recordNumber, SQLSMALLINT cType, SQLPOINTER dataPtr, SQLLEN bufferLength, SQLLEN* indicatorPtr); + void SetDataPtrOnRecord(SQLPOINTER dataPtr, SQLSMALLINT recNumber); + + inline SQLULEN GetBindOffset() { + return m_bindOffsetPtr ? *m_bindOffsetPtr : 0UL; + } + + inline SQLULEN GetBoundStructOffset() { + // If this is SQL_BIND_BY_COLUMN, m_bindType is zero which indicates no offset due to use of a bound struct. + // If this is non-zero, row-wise binding is being used so the app should set this to sizeof(their struct). + return m_bindType; + } + + inline SQLULEN GetArraySize() { + return m_arraySize; + } + + inline void SetRowsProcessed(SQLULEN rows) { + if (m_rowsProccessedPtr) { + *m_rowsProccessedPtr = rows; + } + } + + void NotifyBindingsHavePropagated() { + m_hasBindingsChanged = false; + } + + private: + driver::odbcabstraction::Diagnostics m_diagnostics; + std::vector m_registeredOnStatementsAsApd; + std::vector m_registeredOnStatementsAsArd; + std::vector m_records; + ODBCConnection* m_owningConnection; + ODBCStatement* m_parentStatement; + SQLUSMALLINT* m_arrayStatusPtr; + SQLLEN* m_bindOffsetPtr; + SQLULEN* m_rowsProccessedPtr; + SQLULEN m_arraySize; + SQLINTEGER m_bindType; + SQLSMALLINT m_highestOneBasedBoundRecord; + const bool m_is2xConnection; + bool m_isAppDescriptor; + bool m_isWritable; + bool m_hasBindingsChanged; + }; +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCEnvironment.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCEnvironment.h new file mode 100644 index 0000000000000..a10b1d5feb9e6 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCEnvironment.h @@ -0,0 +1,61 @@ +// 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. + +#pragma once + +#include + +#include +#include +#include + +namespace driver { +namespace odbcabstraction { + class Driver; +} +} + +namespace ODBC { + class ODBCConnection; +} + +/** + * @brief An abstraction over an ODBC environment handle. + */ +namespace ODBC +{ +class ODBCEnvironment : public ODBCHandle { + public: + ODBCEnvironment(std::shared_ptr driver); + driver::odbcabstraction::Diagnostics& GetDiagnostics_Impl(); + SQLINTEGER getODBCVersion() const; + void setODBCVersion(SQLINTEGER version); + SQLINTEGER getConnectionPooling() const; + void setConnectionPooling(SQLINTEGER pooling); + std::shared_ptr CreateConnection(); + void DropConnection(ODBCConnection* conn); + ~ODBCEnvironment() = default; + + private: + std::vector > m_connections; + std::shared_ptr m_driver; + std::unique_ptr m_diagnostics; + SQLINTEGER m_version; + SQLINTEGER m_connectionPooling; +}; + +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCHandle.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCHandle.h new file mode 100644 index 0000000000000..c97c3e54d6514 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCHandle.h @@ -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. + +#pragma once + +#include +#include +#include +#include +#include +#include + +/** + * @brief An abstraction over a generic ODBC handle. + */ +namespace ODBC { + +template +class ODBCHandle { + +public: + inline driver::odbcabstraction::Diagnostics& GetDiagnostics() { + return static_cast(this)->GetDiagnostics_Impl(); + } + + inline driver::odbcabstraction::Diagnostics& GetDiagnostics_Impl() { + throw std::runtime_error("Illegal state -- diagnostics requested on invalid handle"); + } + + template + inline SQLRETURN execute(SQLRETURN rc, Function function) { + try { + GetDiagnostics().Clear(); + rc = function(); + } catch (const driver::odbcabstraction::DriverException& ex) { + GetDiagnostics().AddError(ex); + } catch (const std::bad_alloc& ex) { + GetDiagnostics().AddError( + driver::odbcabstraction::DriverException("A memory allocation error occurred.", "HY001")); + } catch (const std::exception& ex) { + GetDiagnostics().AddError( + driver::odbcabstraction::DriverException(ex.what())); + } catch (...) { + GetDiagnostics().AddError( + driver::odbcabstraction::DriverException("An unknown error occurred.")); + } + + if (GetDiagnostics().HasError()) { + return SQL_ERROR; + } if (SQL_SUCCEEDED(rc) && GetDiagnostics().HasWarning()) { + return SQL_SUCCESS_WITH_INFO; + } + return rc; + } + + template + inline SQLRETURN executeWithLock(SQLRETURN rc, Function function) { + const std::lock_guard lock(mtx_); + return execute(rc, function); + } + + template + static inline SQLRETURN ExecuteWithDiagnostics(SQLHANDLE handle, SQLRETURN rc, Function func) { + if (!handle) { + return SQL_INVALID_HANDLE; + } + if (SHOULD_LOCK) { + return reinterpret_cast(handle)->executeWithLock(rc, func); + } else { + return reinterpret_cast(handle)->execute(rc, func); + } + } + + static Derived* of(SQLHANDLE handle) { + return reinterpret_cast(handle); + } + +private: + std::mutex mtx_; +}; +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h new file mode 100644 index 0000000000000..ac57d0fda22cf --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h @@ -0,0 +1,123 @@ +// 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. + +#pragma once + +#include + +#include +#include +#include +#include + +namespace driver { +namespace odbcabstraction { + class Statement; + class ResultSet; +} +} + +namespace ODBC { + class ODBCConnection; + class ODBCDescriptor; +} + +/** + * @brief An abstraction over an ODBC connection handle. This also wraps an SPI Connection. + */ +namespace ODBC +{ +class ODBCStatement : public ODBCHandle { + public: + ODBCStatement(const ODBCStatement&) = delete; + ODBCStatement& operator=(const ODBCStatement&) = delete; + + ODBCStatement(ODBCConnection& connection, + std::shared_ptr spiStatement); + + ~ODBCStatement() = default; + + driver::odbcabstraction::Diagnostics& GetDiagnostics_Impl(); + + ODBCConnection &GetConnection(); + + void CopyAttributesFromConnection(ODBCConnection& connection); + void Prepare(const std::string& query); + void ExecutePrepared(); + void ExecuteDirect(const std::string& query); + + /** + * @brief Returns true if the number of rows fetch was greater than zero. + */ + bool Fetch(size_t rows); + bool isPrepared() const; + + void GetStmtAttr(SQLINTEGER statementAttribute, SQLPOINTER output, + SQLINTEGER bufferSize, SQLINTEGER *strLenPtr, bool isUnicode); + void SetStmtAttr(SQLINTEGER statementAttribute, SQLPOINTER value, + SQLINTEGER bufferSize, bool isUnicode); + + void RevertAppDescriptor(bool isApd); + + inline const ODBCDescriptor* GetIRD() const { + return m_ird.get(); + } + + inline ODBCDescriptor* GetARD() { + return m_currentArd; + } + + inline SQLULEN GetRowsetSize() { + return m_rowsetSize; + } + + bool GetData(SQLSMALLINT recordNumber, SQLSMALLINT cType, SQLPOINTER dataPtr, SQLLEN bufferLength, SQLLEN* indicatorPtr); + + /** + * @brief Closes the cursor. This does _not_ un-prepare the statement or change + * bindings. + */ + void closeCursor(bool suppressErrors); + + /** + * @brief Releases this statement from memory. + */ + void releaseStatement(); + + void GetTables(const std::string* catalog, const std::string* schema, const std::string* table, const std::string* tableType); + void GetColumns(const std::string* catalog, const std::string* schema, const std::string* table, const std::string* column); + void GetTypeInfo(SQLSMALLINT dataType); + void Cancel(); + + private: + ODBCConnection& m_connection; + std::shared_ptr m_spiStatement; + std::shared_ptr m_currenResult; + + std::shared_ptr m_builtInArd; + std::shared_ptr m_builtInApd; + std::shared_ptr m_ipd; + std::shared_ptr m_ird; + ODBCDescriptor* m_currentArd; + ODBCDescriptor* m_currentApd; + SQLULEN m_rowNumber; + SQLULEN m_maxRows; + SQLULEN m_rowsetSize; // Used by SQLExtendedFetch instead of the ARD array size. + bool m_isPrepared; + bool m_hasReachedEndOfResult; +}; +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/TypeUtilities.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/TypeUtilities.h new file mode 100644 index 0000000000000..1fd44643cfe8d --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/TypeUtilities.h @@ -0,0 +1,42 @@ +// 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. + +#pragma once + +#include +#include + +namespace ODBC { + inline SQLSMALLINT GetSqlTypeForODBCVersion(SQLSMALLINT type, bool isOdbc2x) { + switch (type) { + case SQL_DATE: + case SQL_TYPE_DATE: + return isOdbc2x ? SQL_DATE : SQL_TYPE_DATE; + + case SQL_TIME: + case SQL_TYPE_TIME: + return isOdbc2x ? SQL_TIME : SQL_TYPE_TIME; + + case SQL_TIMESTAMP: + case SQL_TYPE_TIMESTAMP: + return isOdbc2x ? SQL_TIMESTAMP : SQL_TYPE_TIMESTAMP; + + default: + return type; + } + } +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/connection.h similarity index 100% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/connection.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/connection.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h similarity index 100% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/driver.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h similarity index 100% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set_metadata.h similarity index 100% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/result_set_metadata.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set_metadata.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/statement.h similarity index 100% rename from flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/statement.h rename to flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/statement.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h index 1a9bd800a3cdb..537b68973aaee 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h @@ -18,7 +18,7 @@ #pragma once #include -#include +#include namespace driver { namespace odbcabstraction { @@ -29,7 +29,7 @@ using driver::odbcabstraction::Connection; /// \param value the value to be parsed. /// \param default_value the default value in case the parse fails. /// \return the parsed valued. -bool AsBool(const std::string& value, const bool default_value); +bool AsBool(const std::string& value, bool default_value); /// Looks up for a value inside the ConnPropertyMap and then try to parse it. /// In case it does not find or it cannot parse, the default value will be returned. @@ -37,7 +37,7 @@ bool AsBool(const std::string& value, const bool default_value); /// \param connPropertyMap the map with the connection properties. /// \param property_name the name of the property that will be looked up. /// \return the parsed valued. -bool AsBool(const bool default_value, const Connection::ConnPropertyMap& connPropertyMap, +bool AsBool(bool default_value, const Connection::ConnPropertyMap& connPropertyMap, const std::string& property_name); } // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc new file mode 100644 index 0000000000000..9c1157b2fba5a --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc @@ -0,0 +1,705 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include + +using namespace ODBC; +using namespace driver::odbcabstraction; +using driver::odbcabstraction::Connection; +using driver::odbcabstraction::DriverException; + +namespace +{ + // Key-value pairs separated by semi-colon. + // Note that the value can be wrapped in curly braces to escape other significant characters + // such as semi-colons and equals signs. + // NOTE: This can be optimized to be built statically. + const boost::xpressive::sregex CONNECTION_STR_REGEX(boost::xpressive::sregex::compile( + "([^=;]+)=({.+}|[^=;]+|[^;])")); + +// Load properties from the given DSN. The properties loaded do _not_ overwrite existing +// entries in the properties. +void loadPropertiesFromDSN(const std::string& dsn, Connection::ConnPropertyMap& properties) { + const size_t BUFFER_SIZE = 1024 * 10; + std::vector outputBuffer; + outputBuffer.resize(BUFFER_SIZE, '\0'); + SQLSetConfigMode(ODBC_BOTH_DSN); + SQLGetPrivateProfileString(dsn.c_str(), NULL, "", &outputBuffer[0], BUFFER_SIZE, "odbc.ini"); + + // The output buffer holds the list of keys in a series of NUL-terminated strings. + // The series is terminated with an empty string (eg a NUL-terminator terminating the last + // key followed by a NUL terminator after). + std::vector keys; + size_t pos = 0; + while (pos < BUFFER_SIZE) { + std::string key(&outputBuffer[pos]); + if (key.empty()) { + break; + } + size_t len = key.size(); + + // Skip over Driver or DSN keys. + if (!boost::iequals(key, "DSN") && + !boost::iequals(key, "Driver")) { + keys.emplace_back(std::move(key)); + } + pos += len + 1; + } + + for (auto& key : keys) { + outputBuffer.clear(); + outputBuffer.resize(BUFFER_SIZE, '\0'); + SQLGetPrivateProfileString(dsn.c_str(), key.c_str(), "", &outputBuffer[0], BUFFER_SIZE, "odbc.ini"); + std::string value = std::string(&outputBuffer[0]); + auto propIter = properties.find(key); + if (propIter == properties.end()) { + properties.emplace(std::make_pair(std::move(key), std::move(value))); + } + } +} + +} + +// Public ========================================================================================= +ODBCConnection::ODBCConnection(ODBCEnvironment& environment, + std::shared_ptr spiConnection) : + m_environment(environment), + m_spiConnection(std::move(spiConnection)), + m_is2xConnection(environment.getODBCVersion() == SQL_OV_ODBC2), + m_isConnected(false) +{ + +} + +Diagnostics &ODBCConnection::GetDiagnostics_Impl() { + return m_spiConnection->GetDiagnostics(); +} + +bool ODBCConnection::isConnected() const +{ + return m_isConnected; +} + +const std::string& ODBCConnection::GetDSN() const { + return m_dsn; +} + +void ODBCConnection::connect(std::string dsn, const Connection::ConnPropertyMap &properties, + std::vector &missing_properties) +{ + if (m_isConnected) { + throw DriverException("Already connected.", "HY010"); + } + + m_dsn = std::move(dsn); + m_spiConnection->Connect(properties, missing_properties); + m_isConnected = true; + std::shared_ptr spiStatement = m_spiConnection->CreateStatement(); + m_attributeTrackingStatement = std::make_shared(*this, spiStatement); +} + +void ODBCConnection::GetInfo(SQLUSMALLINT infoType, SQLPOINTER value, SQLSMALLINT bufferLength, SQLSMALLINT* outputLength, bool isUnicode) +{ + + switch (infoType) { + case SQL_ACTIVE_ENVIRONMENTS: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + #ifdef SQL_ASYNC_DBC_FUNCTIONS + case SQL_ASYNC_DBC_FUNCTIONS: + GetAttribute(static_cast(SQL_ASYNC_DBC_NOT_CAPABLE), value, bufferLength, outputLength); + break; + #endif + case SQL_ASYNC_MODE: + GetAttribute(static_cast(SQL_AM_NONE), value, bufferLength, outputLength); + break; + #ifdef SQL_ASYNC_NOTIFICATION + case SQL_ASYNC_NOTIFICATION: + GetAttribute(static_cast(SQL_ASYNC_NOTIFICATION_NOT_CAPABLE), value, bufferLength, outputLength); + break; + #endif + case SQL_DATA_SOURCE_NAME: + GetStringAttribute(isUnicode, m_dsn, true, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_DRIVER_ODBC_VER: + GetStringAttribute(isUnicode, "03.80", true, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_DYNAMIC_CURSOR_ATTRIBUTES1: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_DYNAMIC_CURSOR_ATTRIBUTES2: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1: + GetAttribute(static_cast(SQL_CA1_NEXT), value, bufferLength, outputLength); + break; + case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2: + GetAttribute(static_cast(SQL_CA2_READ_ONLY_CONCURRENCY), value, bufferLength, outputLength); + break; + case SQL_FILE_USAGE: + GetAttribute(static_cast(SQL_FILE_NOT_SUPPORTED), value, bufferLength, outputLength); + break; + case SQL_KEYSET_CURSOR_ATTRIBUTES1: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_KEYSET_CURSOR_ATTRIBUTES2: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_MAX_ASYNC_CONCURRENT_STATEMENTS: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_ODBC_INTERFACE_CONFORMANCE: + GetAttribute(static_cast(SQL_OIC_CORE), value, bufferLength, outputLength); + break; + // case SQL_ODBC_STANDARD_CLI_CONFORMANCE: - mentioned in SQLGetInfo spec with no description + // and there is no constant for this. + case SQL_PARAM_ARRAY_ROW_COUNTS: + GetAttribute(static_cast(SQL_PARC_NO_BATCH), value, bufferLength, outputLength); + break; + case SQL_PARAM_ARRAY_SELECTS: + GetAttribute(static_cast(SQL_PAS_NO_SELECT), value, bufferLength, outputLength); + break; + case SQL_ROW_UPDATES: + GetStringAttribute(isUnicode, "N", true, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_SCROLL_OPTIONS: + GetAttribute(static_cast(SQL_SO_FORWARD_ONLY), value, bufferLength, outputLength); + break; + case SQL_STATIC_CURSOR_ATTRIBUTES1: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_STATIC_CURSOR_ATTRIBUTES2: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_BOOKMARK_PERSISTENCE: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_DESCRIBE_PARAMETER: + GetStringAttribute(isUnicode, "N", true, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_MULT_RESULT_SETS: + GetStringAttribute(isUnicode, "N", true, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_MULTIPLE_ACTIVE_TXN: + GetStringAttribute(isUnicode, "N", true, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_NEED_LONG_DATA_LEN: + GetStringAttribute(isUnicode, "N", true, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_TXN_CAPABLE: + GetAttribute(static_cast(SQL_TC_NONE), value, bufferLength, outputLength); + break; + case SQL_TXN_ISOLATION_OPTION: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_TABLE_TERM: + GetStringAttribute(isUnicode, "table", true, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_COLUMN_ALIAS: + GetStringAttribute(isUnicode, "Y", true, value, bufferLength, outputLength, GetDiagnostics()); + break; + // Deprecated ODBC 2.x fields required for backwards compatibility. + case SQL_ODBC_API_CONFORMANCE: + GetAttribute(static_cast(SQL_OAC_LEVEL1), value, bufferLength, outputLength); + break; + case SQL_FETCH_DIRECTION: + GetAttribute(static_cast(SQL_FETCH_NEXT), value, bufferLength, outputLength); + break; + case SQL_LOCK_TYPES: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_POS_OPERATIONS: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_POSITIONED_STATEMENTS: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_SCROLL_CONCURRENCY: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_STATIC_SENSITIVITY: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + + // Driver-level string properties. + case SQL_USER_NAME: + case SQL_DBMS_NAME: + case SQL_DBMS_VER: + case SQL_DRIVER_NAME: + case SQL_DRIVER_VER: + case SQL_SEARCH_PATTERN_ESCAPE: + case SQL_SERVER_NAME: + case SQL_DATA_SOURCE_READ_ONLY: + case SQL_ACCESSIBLE_TABLES: + case SQL_ACCESSIBLE_PROCEDURES: + case SQL_CATALOG_TERM: + case SQL_COLLATION_SEQ: + case SQL_SCHEMA_TERM: + case SQL_CATALOG_NAME: + case SQL_CATALOG_NAME_SEPARATOR: + case SQL_EXPRESSIONS_IN_ORDERBY: + case SQL_IDENTIFIER_QUOTE_CHAR: + case SQL_INTEGRITY: + case SQL_KEYWORDS: + case SQL_OUTER_JOINS: // Not documented in SQLGetInfo, but other drivers return Y/N strings + case SQL_PROCEDURES: + case SQL_SPECIAL_CHARACTERS: + case SQL_MAX_ROW_SIZE_INCLUDES_LONG: + { + const auto& info = m_spiConnection->GetInfo(infoType); + const std::string& infoValue = boost::get(info); + GetStringAttribute(isUnicode, infoValue, true, value, bufferLength, outputLength, GetDiagnostics()); + break; + } + + // Driver-level 32-bit integer propreties. + case SQL_GETDATA_EXTENSIONS: + case SQL_INFO_SCHEMA_VIEWS: + case SQL_CURSOR_SENSITIVITY: + case SQL_DEFAULT_TXN_ISOLATION: + case SQL_AGGREGATE_FUNCTIONS: + case SQL_ALTER_DOMAIN: +// case SQL_ALTER_SCHEMA: + case SQL_ALTER_TABLE: + case SQL_DATETIME_LITERALS: + case SQL_CATALOG_USAGE: + case SQL_CREATE_ASSERTION: + case SQL_CREATE_CHARACTER_SET: + case SQL_CREATE_COLLATION: + case SQL_CREATE_DOMAIN: + case SQL_CREATE_SCHEMA: + case SQL_CREATE_TABLE: + case SQL_INDEX_KEYWORDS: + case SQL_INSERT_STATEMENT: + case SQL_LIKE_ESCAPE_CLAUSE: + case SQL_OJ_CAPABILITIES: + case SQL_ORDER_BY_COLUMNS_IN_SELECT: + case SQL_SCHEMA_USAGE: + case SQL_SQL_CONFORMANCE: + case SQL_SUBQUERIES: + case SQL_UNION: + case SQL_MAX_BINARY_LITERAL_LEN: + case SQL_MAX_CHAR_LITERAL_LEN: + case SQL_MAX_ROW_SIZE: + case SQL_MAX_STATEMENT_LEN: + case SQL_CONVERT_FUNCTIONS: + case SQL_NUMERIC_FUNCTIONS: + case SQL_STRING_FUNCTIONS: + case SQL_SYSTEM_FUNCTIONS: + case SQL_TIMEDATE_ADD_INTERVALS: + case SQL_TIMEDATE_DIFF_INTERVALS: + case SQL_TIMEDATE_FUNCTIONS: + case SQL_CONVERT_BIGINT: + case SQL_CONVERT_BINARY: + case SQL_CONVERT_BIT: + case SQL_CONVERT_CHAR: + case SQL_CONVERT_DATE: + case SQL_CONVERT_DECIMAL: + case SQL_CONVERT_DOUBLE: + case SQL_CONVERT_FLOAT: + case SQL_CONVERT_INTEGER: + case SQL_CONVERT_INTERVAL_DAY_TIME: + case SQL_CONVERT_INTERVAL_YEAR_MONTH: + case SQL_CONVERT_LONGVARBINARY: + case SQL_CONVERT_LONGVARCHAR: + case SQL_CONVERT_NUMERIC: + case SQL_CONVERT_REAL: + case SQL_CONVERT_SMALLINT: + case SQL_CONVERT_TIME: + case SQL_CONVERT_TIMESTAMP: + case SQL_CONVERT_TINYINT: + case SQL_CONVERT_VARBINARY: + case SQL_CONVERT_VARCHAR: + { + const auto& info = m_spiConnection->GetInfo(infoType); + uint32_t infoValue = boost::get(info); + GetAttribute(infoValue, value, bufferLength, outputLength); + break; + } + + // Driver-level 16-bit integer properties. + case SQL_MAX_CONCURRENT_ACTIVITIES: + case SQL_MAX_DRIVER_CONNECTIONS: + case SQL_CONCAT_NULL_BEHAVIOR: + case SQL_CURSOR_COMMIT_BEHAVIOR: + case SQL_CURSOR_ROLLBACK_BEHAVIOR: + case SQL_NULL_COLLATION: + case SQL_CATALOG_LOCATION: + case SQL_CORRELATION_NAME: + case SQL_CREATE_TRANSLATION: + case SQL_DDL_INDEX: + case SQL_DROP_ASSERTION: + case SQL_DROP_CHARACTER_SET: + case SQL_DROP_COLLATION: + case SQL_DROP_DOMAIN: + case SQL_DROP_SCHEMA: + case SQL_DROP_TABLE: + case SQL_DROP_TRANSLATION: + case SQL_DROP_VIEW: + case SQL_GROUP_BY: + case SQL_IDENTIFIER_CASE: + case SQL_NON_NULLABLE_COLUMNS: + case SQL_QUOTED_IDENTIFIER_CASE: + case SQL_MAX_CATALOG_NAME_LEN: + case SQL_MAX_COLUMN_NAME_LEN: + case SQL_MAX_COLUMNS_IN_GROUP_BY: + case SQL_MAX_COLUMNS_IN_INDEX: + case SQL_MAX_COLUMNS_IN_ORDER_BY: + case SQL_MAX_COLUMNS_IN_SELECT: + case SQL_MAX_COLUMNS_IN_TABLE: + case SQL_MAX_CURSOR_NAME_LEN: + case SQL_MAX_IDENTIFIER_LEN: + case SQL_MAX_SCHEMA_NAME_LEN: + case SQL_MAX_TABLE_NAME_LEN: + case SQL_MAX_TABLES_IN_SELECT: + case SQL_MAX_USER_NAME_LEN: + { + const auto& info = m_spiConnection->GetInfo(infoType); + uint16_t infoValue = boost::get(info); + GetAttribute(infoValue, value, bufferLength, outputLength); + break; + } + + // Special case - SQL_DATABASE_NAME is an alias for SQL_ATTR_CURRENT_CATALOG. + case SQL_DATABASE_NAME: + { + const auto &attr = + m_spiConnection->GetAttribute(Connection::CURRENT_CATALOG); + if (!attr) { + throw DriverException("Optional feature not supported.", "HYC00"); + } + const std::string &infoValue = boost::get(*attr); + GetStringAttribute(isUnicode, infoValue, true, value, bufferLength,outputLength, GetDiagnostics()); + break; + } + default: + throw DriverException("Unknown SQLGetInfo type: " + std::to_string(infoType)); + } +} + +void ODBCConnection::SetConnectAttr(SQLINTEGER attribute, SQLPOINTER value, SQLINTEGER stringLength, bool isUnicode) { + uint32_t attributeToWrite = 0; + bool successfully_written = false; + switch (attribute) { + // Internal connection attributes +#ifdef SQL_ATR_ASYNC_DBC_EVENT + case SQL_ATTR_ASYNC_DBC_EVENT: + throw DriverException("Optional feature not supported.", "HYC00"); +#endif +#ifdef SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE + case SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE: + throw DriverException("Optional feature not supported.", "HYC00"); +#endif +#ifdef SQL_ATTR_ASYNC_PCALLBACK + case SQL_ATTR_ASYNC_DBC_PCALLBACK: + throw DriverException("Optional feature not supported.", "HYC00"); +#endif +#ifdef SQL_ATTR_ASYNC_DBC_PCONTEXT + case SQL_ATTR_ASYNC_DBC_PCONTEXT: + throw DriverException("Optional feature not supported.", "HYC00"); +#endif + case SQL_ATTR_AUTO_IPD: + throw DriverException("Cannot set read-only attribute", "HY092"); + case SQL_ATTR_AUTOCOMMIT: + CheckIfAttributeIsSetToOnlyValidValue(value, static_cast(SQL_AUTOCOMMIT_ON)); + return; + case SQL_ATTR_CONNECTION_DEAD: + throw DriverException("Cannot set read-only attribute", "HY092"); +#ifdef SQL_ATTR_DBC_INFO_TOKEN + case SQL_ATTR_DBC_INFO_TOKEN: + throw DriverException("Optional feature not supported.", "HYC00"); +#endif + case SQL_ATTR_ENLIST_IN_DTC: + throw DriverException("Optional feature not supported.", "HYC00"); + case SQL_ATTR_ODBC_CURSORS: // DM-only. + throw DriverException("Invalid attribute", "HY092"); + case SQL_ATTR_QUIET_MODE: + throw DriverException("Cannot set read-only attribute", "HY092"); + case SQL_ATTR_TRACE: // DM-only + throw DriverException("Cannot set read-only attribute", "HY092"); + case SQL_ATTR_TRACEFILE: + throw DriverException("Optional feature not supported.", "HYC00"); + case SQL_ATTR_TRANSLATE_LIB: + throw DriverException("Optional feature not supported.", "HYC00"); + case SQL_ATTR_TRANSLATE_OPTION: + throw DriverException("Optional feature not supported.", "HYC00"); + case SQL_ATTR_TXN_ISOLATION: + throw DriverException("Optional feature not supported.", "HYC00"); + + // ODBCAbstraction-level attributes + case SQL_ATTR_CURRENT_CATALOG: { + std::string catalog; + if (isUnicode) { + SetAttributeUTF8(value, stringLength, catalog); + } else { + SetAttributeSQLWCHAR(value, stringLength, catalog); + } + if (!m_spiConnection->SetAttribute(Connection::CURRENT_CATALOG, catalog)) { + throw DriverException("Option value changed.", "01S02"); + } + return; + } + + // Statement attributes that can be set through the connection. + // Only applies to SQL_ATTR_METADATA_ID, SQL_ATTR_ASYNC_ENABLE, and ODBC 2.x statement attributes. + // SQL_ATTR_ROW_NUMBER is excluded because it is read-only. + // Note that SQLGetConnectAttr cannot retrieve these attributes. + case SQL_ATTR_ASYNC_ENABLE: + case SQL_ATTR_METADATA_ID: + case SQL_ATTR_CONCURRENCY: + case SQL_ATTR_CURSOR_TYPE: + case SQL_ATTR_KEYSET_SIZE: + case SQL_ATTR_MAX_LENGTH: + case SQL_ATTR_MAX_ROWS: + case SQL_ATTR_NOSCAN: + case SQL_ATTR_QUERY_TIMEOUT: + case SQL_ATTR_RETRIEVE_DATA: + case SQL_ATTR_ROW_BIND_TYPE: + case SQL_ATTR_SIMULATE_CURSOR: + case SQL_ATTR_USE_BOOKMARKS: + m_attributeTrackingStatement->SetStmtAttr(attribute, value, stringLength, isUnicode); + return; + + case SQL_ATTR_ACCESS_MODE: + SetAttribute(value, attributeToWrite); + successfully_written = m_spiConnection->SetAttribute(Connection::ACCESS_MODE, attributeToWrite); + break; + case SQL_ATTR_CONNECTION_TIMEOUT: + SetAttribute(value, attributeToWrite); + successfully_written = m_spiConnection->SetAttribute(Connection::CONNECTION_TIMEOUT, attributeToWrite); + break; + case SQL_ATTR_LOGIN_TIMEOUT: + SetAttribute(value, attributeToWrite); + successfully_written = m_spiConnection->SetAttribute(Connection::LOGIN_TIMEOUT, attributeToWrite); + break; + case SQL_ATTR_PACKET_SIZE: + SetAttribute(value, attributeToWrite); + successfully_written = m_spiConnection->SetAttribute(Connection::PACKET_SIZE, attributeToWrite); + break; + default: + throw DriverException("Invalid attribute: " + std::to_string(attribute), "HY092"); + } + + if (!successfully_written) { + GetDiagnostics().AddWarning("Option value changed.", "01S02", ODBCErrorCodes_GENERAL_WARNING); + } +} + +void ODBCConnection::GetConnectAttr(SQLINTEGER attribute, SQLPOINTER value, + SQLINTEGER bufferLength, + SQLINTEGER *outputLength, bool isUnicode) { + using driver::odbcabstraction::Connection; + boost::optional spiAttribute; + + switch (attribute) { + // Internal connection attributes +#ifdef SQL_ATR_ASYNC_DBC_EVENT + case SQL_ATTR_ASYNC_DBC_EVENT: + GetAttribute(static_cast(NULL), value, bufferLength, outputLength); + return; +#endif +#ifdef SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE + case SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE: + GetAttribute(static_cast(SQL_ASYNC_DBC_ENABLE_OFF), value, bufferLength, outputLength); + return; +#endif +#ifdef SQL_ATTR_ASYNC_PCALLBACK + case SQL_ATTR_ASYNC_DBC_PCALLBACK: + GetAttribute(static_cast(NULL), value, bufferLength, outputLength); + return; +#endif +#ifdef SQL_ATTR_ASYNC_DBC_PCONTEXT + case SQL_ATTR_ASYNC_DBC_PCONTEXT: + GetAttribute(static_cast(NULL), value, bufferLength, outputLength); + return; +#endif + case SQL_ATTR_ASYNC_ENABLE: + GetAttribute(static_cast(SQL_ASYNC_ENABLE_OFF), value, bufferLength, outputLength); + return; + case SQL_ATTR_AUTO_IPD: + GetAttribute(static_cast(SQL_FALSE), value, bufferLength, outputLength); + return; + case SQL_ATTR_AUTOCOMMIT: + GetAttribute(static_cast(SQL_AUTOCOMMIT_ON), value, bufferLength, outputLength); + return; +#ifdef SQL_ATTR_DBC_INFO_TOKEN + case SQL_ATTR_DBC_INFO_TOKEN: + throw DriverException("Cannot read set-only attribute", "HY092"); +#endif + case SQL_ATTR_ENLIST_IN_DTC: + GetAttribute(static_cast(NULL), value, bufferLength, outputLength); + return; + case SQL_ATTR_ODBC_CURSORS: // DM-only. + throw DriverException("Invalid attribute", "HY092"); + case SQL_ATTR_QUIET_MODE: + GetAttribute(static_cast(NULL), value, bufferLength, outputLength); + return; + case SQL_ATTR_TRACE: // DM-only + throw DriverException("Invalid attribute", "HY092"); + case SQL_ATTR_TRACEFILE: + throw DriverException("Optional feature not supported.", "HYC00"); + case SQL_ATTR_TRANSLATE_LIB: + throw DriverException("Optional feature not supported.", "HYC00"); + case SQL_ATTR_TRANSLATE_OPTION: + throw DriverException("Optional feature not supported.", "HYC00"); + case SQL_ATTR_TXN_ISOLATION: + throw DriverException("Optional feature not supported.", "HCY00"); + + // ODBCAbstraction-level connection attributes. + case SQL_ATTR_CURRENT_CATALOG: + { + const auto &catalog = + m_spiConnection->GetAttribute(Connection::CURRENT_CATALOG); + if (!catalog) { + throw DriverException("Optional feature not supported.", "HYC00"); + } + const std::string &infoValue = boost::get(*catalog); + GetStringAttribute(isUnicode, infoValue, true, value, bufferLength,outputLength, GetDiagnostics()); + return; + } + + // These all are uint32_t attributes. + case SQL_ATTR_ACCESS_MODE: + spiAttribute = m_spiConnection->GetAttribute(Connection::ACCESS_MODE); + break; + case SQL_ATTR_CONNECTION_DEAD: + spiAttribute = m_spiConnection->GetAttribute(Connection::CONNECTION_DEAD); + break; + case SQL_ATTR_CONNECTION_TIMEOUT: + spiAttribute = m_spiConnection->GetAttribute(Connection::CONNECTION_TIMEOUT); + break; + case SQL_ATTR_LOGIN_TIMEOUT: + spiAttribute = m_spiConnection->GetAttribute(Connection::LOGIN_TIMEOUT); + break; + case SQL_ATTR_PACKET_SIZE: + spiAttribute = m_spiConnection->GetAttribute(Connection::PACKET_SIZE); + break; + default: + throw DriverException("Invalid attribute", "HY092"); + } + + if (!spiAttribute) { + throw DriverException("Invalid attribute", "HY092"); + } + + GetAttribute(static_cast(boost::get(*spiAttribute)), value, bufferLength, outputLength); +} + +void ODBCConnection::disconnect() { + if (m_isConnected) { + m_spiConnection->Close(); + m_isConnected = false; + } +} + +void ODBCConnection::releaseConnection() { + disconnect(); + m_environment.DropConnection(this); +} + +std::shared_ptr ODBCConnection::createStatement() { + std::shared_ptr spiStatement = m_spiConnection->CreateStatement(); + std::shared_ptr statement = std::make_shared(*this, spiStatement); + m_statements.push_back(statement); + statement->CopyAttributesFromConnection(*this); + return statement; +} + +void ODBCConnection::dropStatement(ODBCStatement* stmt) { + auto it = std::find_if(m_statements.begin(), m_statements.end(), + [&stmt] (const std::shared_ptr& statement) { return statement.get() == stmt; }); + if (m_statements.end() != it) { + m_statements.erase(it); + } +} + +std::shared_ptr ODBCConnection::createDescriptor() { + std::shared_ptr desc = std::make_shared( + m_spiConnection->GetDiagnostics(), this, nullptr, true, true, false); + m_descriptors.push_back(desc); + return desc; +} + +void ODBCConnection::dropDescriptor(ODBCDescriptor* desc) { + auto it = std::find_if(m_descriptors.begin(), m_descriptors.end(), + [&desc] (const std::shared_ptr& descriptor) { return descriptor.get() == desc; }); + if (m_descriptors.end() != it) { + m_descriptors.erase(it); + } +} + +// Public Static =================================================================================== +std::string ODBCConnection::getPropertiesFromConnString(const std::string& connStr, + Connection::ConnPropertyMap &properties) +{ + const int groups[] = { 1, 2 }; // CONNECTION_STR_REGEX has two groups. key: 1, value: 2 + boost::xpressive::sregex_token_iterator regexIter(connStr.begin(), connStr.end(), + CONNECTION_STR_REGEX, groups), end; + + bool isDsnFirst = false; + bool isDriverFirst = false; + std::string dsn; + for (auto it = regexIter; end != regexIter; ++regexIter) { + std::string key = *regexIter; + std::string value = *++regexIter; + + // If the DSN shows up before driver key, load settings from the DSN. + // Only load values from the DSN once regardless of how many times the DSN + // key shows up. + if (boost::iequals(key, "DSN")) { + if (!isDriverFirst) { + if (!isDsnFirst) { + isDsnFirst = true; + loadPropertiesFromDSN(value, properties); + dsn.swap(value); + } + } + continue; + } else if (boost::iequals(key, "Driver")) { + if (!isDsnFirst) { + isDriverFirst = true; + } + continue; + } + + // Strip wrapping curly braces. + if (value.size() >= 2 && value[0] == '{' && value[value.size() - 1] == '}') { + value = value.substr(1, value.size() - 2); + } + + // Overwrite the existing value. Later copies of the key take precedence, + // including over entries in the DSN. + properties[key] = std::move(value); + } + return dsn; +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc new file mode 100644 index 0000000000000..adf9d05cc474e --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc @@ -0,0 +1,545 @@ +// 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 +#include +#include + +using namespace ODBC; +using namespace driver::odbcabstraction; + +namespace { + SQLSMALLINT CalculateHighestBoundRecord(const std::vector& records) { + // Most applications will bind every column, so optimistically assume that we'll + // find the next bound record fastest by counting backwards. + for (size_t i = records.size(); i > 0; --i) { + if (records[i-1].m_isBound) { + return i; + } + } + return 0; + } +} + +// Public ========================================================================================= +ODBCDescriptor::ODBCDescriptor(Diagnostics& baseDiagnostics, + ODBCConnection* conn, ODBCStatement* stmt, bool isAppDescriptor, bool isWritable, bool is2xConnection) : + m_diagnostics(baseDiagnostics.GetVendor(), baseDiagnostics.GetDataSourceComponent(), V_3), + m_owningConnection(conn), + m_parentStatement(stmt), + m_arrayStatusPtr(nullptr), + m_bindOffsetPtr(nullptr), + m_rowsProccessedPtr(nullptr), + m_arraySize(1), + m_bindType(SQL_BIND_BY_COLUMN), + m_highestOneBasedBoundRecord(0), + m_is2xConnection(is2xConnection), + m_isAppDescriptor(isAppDescriptor), + m_isWritable(isWritable), + m_hasBindingsChanged(true) { +} + +Diagnostics &ODBCDescriptor::GetDiagnostics_Impl() { + return m_diagnostics; +} + +ODBCConnection &ODBCDescriptor::GetConnection() { + if (m_owningConnection) { + return *m_owningConnection; + } + assert(m_parentStatement); + return m_parentStatement->GetConnection(); +} + +void ODBCDescriptor::SetHeaderField(SQLSMALLINT fieldIdentifier, SQLPOINTER value, SQLINTEGER bufferLength) { + // Only these two fields can be set on the IRD. + if (!m_isWritable && fieldIdentifier != SQL_DESC_ARRAY_STATUS_PTR && fieldIdentifier != SQL_DESC_ROWS_PROCESSED_PTR) { + throw DriverException("Cannot modify read-only descriptor", "HY016"); + } + + switch (fieldIdentifier) { + case SQL_DESC_ALLOC_TYPE: + throw DriverException("Invalid descriptor field", "HY091"); + case SQL_DESC_ARRAY_SIZE: + SetAttribute(value, m_arraySize); + m_hasBindingsChanged = true; + break; + case SQL_DESC_ARRAY_STATUS_PTR: + SetPointerAttribute(value, m_arrayStatusPtr); + m_hasBindingsChanged = true; + break; + case SQL_DESC_BIND_OFFSET_PTR: + SetPointerAttribute(value, m_bindOffsetPtr); + m_hasBindingsChanged = true; + break; + case SQL_DESC_BIND_TYPE: + SetAttribute(value, m_bindType); + m_hasBindingsChanged = true; + break; + case SQL_DESC_ROWS_PROCESSED_PTR: + SetPointerAttribute(value, m_rowsProccessedPtr); + m_hasBindingsChanged = true; + break; + case SQL_DESC_COUNT: { + SQLSMALLINT newCount; + SetAttribute(value, newCount); + m_records.resize(newCount); + + if (m_isAppDescriptor && newCount <= m_highestOneBasedBoundRecord) { + m_highestOneBasedBoundRecord = CalculateHighestBoundRecord(m_records); + } else { + m_highestOneBasedBoundRecord = newCount; + } + m_hasBindingsChanged = true; + break; + } + default: + throw DriverException("Invalid descriptor field", "HY091"); + } +} + +void ODBCDescriptor::SetField(SQLSMALLINT recordNumber, SQLSMALLINT fieldIdentifier, SQLPOINTER value, SQLINTEGER bufferLength) { + if (!m_isWritable) { + throw DriverException("Cannot modify read-only descriptor", "HY016"); + } + + // Handle header fields before validating the record number. + switch (fieldIdentifier) { + case SQL_DESC_ALLOC_TYPE: + case SQL_DESC_ARRAY_SIZE: + case SQL_DESC_ARRAY_STATUS_PTR: + case SQL_DESC_BIND_OFFSET_PTR: + case SQL_DESC_BIND_TYPE: + case SQL_DESC_ROWS_PROCESSED_PTR: + case SQL_DESC_COUNT: + SetHeaderField(fieldIdentifier, value, bufferLength); + return; + default: + break; + } + + if (recordNumber == 0) { + throw DriverException("Bookmarks are unsupported.", "07009"); + } + + if (recordNumber > m_records.size()) { + throw DriverException("Invalid descriptor index", "HY009"); + } + + SQLSMALLINT zeroBasedRecord = recordNumber - 1; + DescriptorRecord& record = m_records[zeroBasedRecord]; + switch (fieldIdentifier) { + case SQL_DESC_AUTO_UNIQUE_VALUE: + case SQL_DESC_BASE_COLUMN_NAME: + case SQL_DESC_BASE_TABLE_NAME: + case SQL_DESC_CASE_SENSITIVE: + case SQL_DESC_CATALOG_NAME: + case SQL_DESC_DISPLAY_SIZE: + case SQL_DESC_FIXED_PREC_SCALE: + case SQL_DESC_LABEL: + case SQL_DESC_LITERAL_PREFIX: + case SQL_DESC_LITERAL_SUFFIX: + case SQL_DESC_LOCAL_TYPE_NAME: + case SQL_DESC_NULLABLE: + case SQL_DESC_NUM_PREC_RADIX: + case SQL_DESC_ROWVER: + case SQL_DESC_SCHEMA_NAME: + case SQL_DESC_SEARCHABLE: + case SQL_DESC_TABLE_NAME: + case SQL_DESC_TYPE_NAME: + case SQL_DESC_UNNAMED: + case SQL_DESC_UNSIGNED: + case SQL_DESC_UPDATABLE: + throw DriverException("Cannot modify read-only field.", "HY092"); + case SQL_DESC_CONCISE_TYPE: + SetAttribute(value, record.m_conciseType); + record.m_isBound = false; + m_hasBindingsChanged = true; + break; + case SQL_DESC_DATA_PTR: + SetDataPtrOnRecord(value, recordNumber); + break; + case SQL_DESC_DATETIME_INTERVAL_CODE: + SetAttribute(value, record.m_datetimeIntervalCode); + record.m_isBound = false; + m_hasBindingsChanged = true; + break; + case SQL_DESC_DATETIME_INTERVAL_PRECISION: + SetAttribute(value, record.m_datetimeIntervalPrecision); + record.m_isBound = false; + m_hasBindingsChanged = true; + break; + case SQL_DESC_INDICATOR_PTR: + case SQL_DESC_OCTET_LENGTH_PTR: + SetPointerAttribute(value, record.m_indicatorPtr); + m_hasBindingsChanged = true; + break; + case SQL_DESC_LENGTH: + SetAttribute(value, record.m_length); + record.m_isBound = false; + m_hasBindingsChanged = true; + break; + case SQL_DESC_NAME: + SetAttributeUTF8(value, bufferLength, record.m_name); + m_hasBindingsChanged = true; + break; + case SQL_DESC_OCTET_LENGTH: + SetAttribute(value, record.m_octetLength); + record.m_isBound = false; + m_hasBindingsChanged = true; + break; + case SQL_DESC_PARAMETER_TYPE: + SetAttribute(value, record.m_paramType); + record.m_isBound = false; + m_hasBindingsChanged = true; + break; + case SQL_DESC_PRECISION: + SetAttribute(value, record.m_precision); + record.m_isBound = false; + m_hasBindingsChanged = true; + break; + case SQL_DESC_SCALE: + SetAttribute(value, record.m_scale); + record.m_isBound = false; + m_hasBindingsChanged = true; + break; + case SQL_DESC_TYPE: + SetAttribute(value, record.m_type); + record.m_isBound = false; + m_hasBindingsChanged = true; + break; + default: + throw DriverException("Invalid descriptor field", "HY091"); + } +} + +void ODBCDescriptor::GetHeaderField(SQLSMALLINT fieldIdentifier, SQLPOINTER value, SQLINTEGER bufferLength, SQLINTEGER* outputLength) const { + switch (fieldIdentifier) { + case SQL_DESC_ALLOC_TYPE: { + SQLSMALLINT result; + if (m_owningConnection) { + result = SQL_DESC_ALLOC_USER; + } else { + result = SQL_DESC_ALLOC_AUTO; + } + GetAttribute(result, value, bufferLength, outputLength); + break; + } + case SQL_DESC_ARRAY_SIZE: + GetAttribute(m_arraySize, value, bufferLength, outputLength); + break; + case SQL_DESC_ARRAY_STATUS_PTR: + GetAttribute(m_arrayStatusPtr, value, bufferLength, outputLength); + break; + case SQL_DESC_BIND_OFFSET_PTR: + GetAttribute(m_bindOffsetPtr, value, bufferLength, outputLength); + break; + case SQL_DESC_BIND_TYPE: + GetAttribute(m_bindType, value, bufferLength, outputLength); + break; + case SQL_DESC_ROWS_PROCESSED_PTR: + GetAttribute(m_rowsProccessedPtr, value, bufferLength, outputLength); + break; + case SQL_DESC_COUNT: { + GetAttribute(m_highestOneBasedBoundRecord, value, bufferLength, outputLength); + break; + } + default: + throw DriverException("Invalid descriptor field", "HY091"); + } +} + +void ODBCDescriptor::GetField(SQLSMALLINT recordNumber, SQLSMALLINT fieldIdentifier, SQLPOINTER value, SQLINTEGER bufferLength, SQLINTEGER* outputLength) { + // Handle header fields before validating the record number. + switch (fieldIdentifier) { + case SQL_DESC_ALLOC_TYPE: + case SQL_DESC_ARRAY_SIZE: + case SQL_DESC_ARRAY_STATUS_PTR: + case SQL_DESC_BIND_OFFSET_PTR: + case SQL_DESC_BIND_TYPE: + case SQL_DESC_ROWS_PROCESSED_PTR: + case SQL_DESC_COUNT: + GetHeaderField(fieldIdentifier, value, bufferLength, outputLength); + return; + default: + break; + } + + if (recordNumber == 0) { + throw DriverException("Bookmarks are unsupported.", "07009"); + } + + if (recordNumber > m_records.size()) { + throw DriverException("Invalid descriptor index", "07009"); + } + + // TODO: Restrict fields based on AppDescriptor IPD, and IRD. + + SQLSMALLINT zeroBasedRecord = recordNumber - 1; + const DescriptorRecord& record = m_records[zeroBasedRecord]; + switch (fieldIdentifier) { + case SQL_DESC_BASE_COLUMN_NAME: + GetAttributeUTF8(record.m_baseColumnName, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_DESC_BASE_TABLE_NAME: + GetAttributeUTF8(record.m_baseTableName, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_DESC_CATALOG_NAME: + GetAttributeUTF8(record.m_catalogName, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_DESC_LABEL: + GetAttributeUTF8(record.m_label, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_DESC_LITERAL_PREFIX: + GetAttributeUTF8(record.m_literalPrefix, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_DESC_LITERAL_SUFFIX: + GetAttributeUTF8(record.m_literalSuffix, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_DESC_LOCAL_TYPE_NAME: + GetAttributeUTF8(record.m_localTypeName, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_DESC_NAME: + GetAttributeUTF8(record.m_name, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_DESC_SCHEMA_NAME: + GetAttributeUTF8(record.m_schemaName, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_DESC_TABLE_NAME: + GetAttributeUTF8(record.m_tableName, value, bufferLength, outputLength, GetDiagnostics()); + break; + case SQL_DESC_TYPE_NAME: + GetAttributeUTF8(record.m_typeName, value, bufferLength, outputLength, GetDiagnostics()); + break; + + case SQL_DESC_DATA_PTR: + GetAttribute(record.m_dataPtr, value, bufferLength, outputLength); + break; + case SQL_DESC_INDICATOR_PTR: + case SQL_DESC_OCTET_LENGTH_PTR: + GetAttribute(record.m_indicatorPtr, value, bufferLength, outputLength); + break; + + case SQL_DESC_LENGTH: + GetAttribute(record.m_length, value, bufferLength, outputLength); + break; + case SQL_DESC_OCTET_LENGTH: + GetAttribute(record.m_octetLength, value, bufferLength, outputLength); + break; + + case SQL_DESC_AUTO_UNIQUE_VALUE: + GetAttribute(record.m_autoUniqueValue, value, bufferLength, outputLength); + break; + case SQL_DESC_CASE_SENSITIVE: + GetAttribute(record.m_caseSensitive, value, bufferLength, outputLength); + break; + case SQL_DESC_DATETIME_INTERVAL_PRECISION: + GetAttribute(record.m_datetimeIntervalPrecision, value, bufferLength, outputLength); + break; + case SQL_DESC_NUM_PREC_RADIX: + GetAttribute(record.m_numPrecRadix, value, bufferLength, outputLength); + break; + + case SQL_DESC_CONCISE_TYPE: + GetAttribute(record.m_conciseType, value, bufferLength, outputLength); + break; + case SQL_DESC_DATETIME_INTERVAL_CODE: + GetAttribute(record.m_datetimeIntervalCode, value, bufferLength, outputLength); + break; + case SQL_DESC_DISPLAY_SIZE: + GetAttribute(record.m_displaySize, value, bufferLength, outputLength); + break; + case SQL_DESC_FIXED_PREC_SCALE: + GetAttribute(record.m_fixedPrecScale, value, bufferLength, outputLength); + break; + case SQL_DESC_NULLABLE: + GetAttribute(record.m_nullable, value, bufferLength, outputLength); + break; + case SQL_DESC_PARAMETER_TYPE: + GetAttribute(record.m_paramType, value, bufferLength, outputLength); + break; + case SQL_DESC_PRECISION: + GetAttribute(record.m_precision, value, bufferLength, outputLength); + break; + case SQL_DESC_ROWVER: + GetAttribute(record.m_rowVer, value, bufferLength, outputLength); + break; + case SQL_DESC_SCALE: + GetAttribute(record.m_scale, value, bufferLength, outputLength); + break; + case SQL_DESC_SEARCHABLE: + GetAttribute(record.m_searchable, value, bufferLength, outputLength); + break; + case SQL_DESC_TYPE: + GetAttribute(record.m_type, value, bufferLength, outputLength); + break; + case SQL_DESC_UNNAMED: + GetAttribute(record.m_unnamed, value, bufferLength, outputLength); + break; + case SQL_DESC_UNSIGNED: + GetAttribute(record.m_unsigned, value, bufferLength, outputLength); + break; + case SQL_DESC_UPDATABLE: + GetAttribute(record.m_updatable, value, bufferLength, outputLength); + break; + default: + throw DriverException("Invalid descriptor field", "HY091"); + } +} + +SQLSMALLINT ODBCDescriptor::getAllocType() const { + return m_owningConnection != nullptr ? SQL_DESC_ALLOC_USER : SQL_DESC_ALLOC_AUTO; +} + +bool ODBCDescriptor::IsAppDescriptor() const { + return m_isAppDescriptor; +} + +bool ODBCDescriptor::HaveBindingsChanged() const { + return m_hasBindingsChanged; +} + +void ODBCDescriptor::RegisterToStatement(ODBCStatement* statement, bool isApd) { + if (isApd) { + m_registeredOnStatementsAsApd.push_back(statement); + } else { + m_registeredOnStatementsAsArd.push_back(statement); + } +} + +void ODBCDescriptor::DetachFromStatement(ODBCStatement* statement, bool isApd) { + auto& vectorToUpdate = isApd ? m_registeredOnStatementsAsApd : m_registeredOnStatementsAsArd; + auto it = std::find(vectorToUpdate.begin(), vectorToUpdate.end(), statement); + if (it != vectorToUpdate.end()) { + vectorToUpdate.erase(it); + } +} + +void ODBCDescriptor::ReleaseDescriptor() { + for (ODBCStatement* stmt : m_registeredOnStatementsAsApd) { + stmt->RevertAppDescriptor(true); + } + + for (ODBCStatement* stmt : m_registeredOnStatementsAsArd) { + stmt->RevertAppDescriptor(false); + } + + if (m_owningConnection) { + m_owningConnection->dropDescriptor(this); + } +} + +void ODBCDescriptor::PopulateFromResultSetMetadata(ResultSetMetadata* rsmd) { + m_records.assign(rsmd->GetColumnCount(), DescriptorRecord()); + m_highestOneBasedBoundRecord = m_records.size() + 1; + + for (size_t i = 0; i < m_records.size(); ++i) { + size_t oneBasedIndex = i + 1; + m_records[i].m_baseColumnName = rsmd->GetBaseColumnName(oneBasedIndex); + m_records[i].m_baseTableName = rsmd->GetBaseTableName(oneBasedIndex); + m_records[i].m_catalogName = rsmd->GetCatalogName(oneBasedIndex); + m_records[i].m_label = rsmd->GetColumnLabel(oneBasedIndex); + m_records[i].m_literalPrefix = rsmd->GetLiteralPrefix(oneBasedIndex); + m_records[i].m_literalSuffix = rsmd->GetLiteralSuffix(oneBasedIndex); + m_records[i].m_localTypeName = rsmd->GetLocalTypeName(oneBasedIndex); + m_records[i].m_name = rsmd->GetName(oneBasedIndex); + m_records[i].m_schemaName = rsmd->GetSchemaName(oneBasedIndex); + m_records[i].m_tableName = rsmd->GetTableName(oneBasedIndex); + m_records[i].m_typeName = rsmd->GetTypeName(oneBasedIndex); + m_records[i].m_dataPtr = nullptr; + m_records[i].m_indicatorPtr = nullptr; + m_records[i].m_displaySize = rsmd->GetColumnDisplaySize(oneBasedIndex); + m_records[i].m_octetLength = rsmd->GetOctetLength(oneBasedIndex); + m_records[i].m_length = rsmd->GetLength(oneBasedIndex); + m_records[i].m_autoUniqueValue = rsmd->IsAutoUnique(oneBasedIndex) ? SQL_TRUE : SQL_FALSE; + m_records[i].m_caseSensitive = rsmd->IsCaseSensitive(oneBasedIndex)? SQL_TRUE : SQL_FALSE; + m_records[i].m_datetimeIntervalPrecision; // TODO - update when rsmd adds this + m_records[i].m_numPrecRadix = rsmd->GetNumPrecRadix(oneBasedIndex); + m_records[i].m_conciseType = GetSqlTypeForODBCVersion(rsmd->GetDataType(oneBasedIndex), m_is2xConnection); // TODO: Check if this needs to be different than datatype. + m_records[i].m_datetimeIntervalCode; // TODO + m_records[i].m_fixedPrecScale = rsmd->IsFixedPrecScale(oneBasedIndex) ? SQL_TRUE : SQL_FALSE; + m_records[i].m_nullable = rsmd->IsNullable(oneBasedIndex); + m_records[i].m_paramType = SQL_PARAM_INPUT; + m_records[i].m_precision = rsmd->GetPrecision(oneBasedIndex); + m_records[i].m_rowVer = SQL_FALSE; + m_records[i].m_scale = rsmd->GetScale(oneBasedIndex); + m_records[i].m_searchable = rsmd->IsSearchable(oneBasedIndex); + m_records[i].m_type = GetSqlTypeForODBCVersion(rsmd->GetDataType(oneBasedIndex), m_is2xConnection); + m_records[i].m_unnamed = m_records[i].m_name.empty() ? SQL_TRUE : SQL_FALSE; + m_records[i].m_unsigned = rsmd->IsUnsigned(oneBasedIndex) ? SQL_TRUE : SQL_FALSE; + m_records[i].m_updatable = rsmd->GetUpdatable(oneBasedIndex); + } +} + +const std::vector& ODBCDescriptor::GetRecords() const { + return m_records; +} + +std::vector& ODBCDescriptor::GetRecords() { + return m_records; +} + +void ODBCDescriptor::BindCol(SQLSMALLINT recordNumber, SQLSMALLINT cType, SQLPOINTER dataPtr, SQLLEN bufferLength, SQLLEN* indicatorPtr) { + assert(m_isAppDescriptor); + assert(m_isWritable); + + // The set of records auto-expands to the supplied record number. + if (m_records.size() < recordNumber) { + m_records.resize(recordNumber); + } + + SQLSMALLINT zeroBasedRecordIndex = recordNumber - 1; + DescriptorRecord& record = m_records[zeroBasedRecordIndex]; + + record.m_type = cType; + record.m_indicatorPtr = indicatorPtr; + record.m_length = bufferLength; + SetDataPtrOnRecord(dataPtr, recordNumber); +} + +void ODBCDescriptor::SetDataPtrOnRecord(SQLPOINTER dataPtr, SQLSMALLINT recordNumber) { + assert(recordNumber <= m_records.size()); + DescriptorRecord& record = m_records[recordNumber-1]; + if (dataPtr) { + record.CheckConsistency(); + record.m_isBound = true; + } else { + record.m_isBound = false; + } + record.m_dataPtr = dataPtr; + + // Bookkeeping on the highest bound record (used for returning SQL_DESC_COUNT) + if (m_highestOneBasedBoundRecord < recordNumber && dataPtr) { + m_highestOneBasedBoundRecord = recordNumber; + } else if (m_highestOneBasedBoundRecord == recordNumber && !dataPtr) { + m_highestOneBasedBoundRecord = CalculateHighestBoundRecord(m_records); + } + m_hasBindingsChanged = true; +} + +void DescriptorRecord::CheckConsistency() { + // TODO. +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCEnvironment.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCEnvironment.cc new file mode 100644 index 0000000000000..c5709c97b6c05 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCEnvironment.cc @@ -0,0 +1,80 @@ +// 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 + +using namespace ODBC; +using namespace driver::odbcabstraction; + +// Public ========================================================================================= +ODBCEnvironment::ODBCEnvironment(std::shared_ptr driver) : + m_driver(std::move(driver)), + m_diagnostics(new Diagnostics(m_driver->GetDiagnostics().GetVendor(), + m_driver->GetDiagnostics().GetDataSourceComponent(), + V_2)), + m_version(SQL_OV_ODBC2), + m_connectionPooling(SQL_CP_OFF) { +} + +Diagnostics &ODBCEnvironment::GetDiagnostics_Impl() { + return *m_diagnostics; +} + +SQLINTEGER ODBCEnvironment::getODBCVersion() const { + return m_version; +} + +void ODBCEnvironment::setODBCVersion(SQLINTEGER version) { + if (version != m_version) { + m_version = version; + m_diagnostics.reset( + new Diagnostics(m_diagnostics->GetVendor(), + m_diagnostics->GetDataSourceComponent(), + version == SQL_OV_ODBC2 ? V_2 : V_3)); + } +} + +SQLINTEGER ODBCEnvironment::getConnectionPooling() const { + return m_connectionPooling; +} + +void ODBCEnvironment::setConnectionPooling(SQLINTEGER connectionPooling) { + m_connectionPooling = connectionPooling; +} + +std::shared_ptr ODBCEnvironment::CreateConnection() { + std::shared_ptr spiConnection = m_driver->CreateConnection(m_version == SQL_OV_ODBC2 ? V_2 : V_3); + std::shared_ptr newConn = std::make_shared(*this, spiConnection); + m_connections.push_back(newConn); + return newConn; +} + +void ODBCEnvironment::DropConnection(ODBCConnection* conn) { + auto it = std::find_if(m_connections.begin(), m_connections.end(), + [&conn] (const std::shared_ptr& connection) { return connection.get() == conn; }); + if (m_connections.end() != it) { + m_connections.erase(it); + } +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc new file mode 100644 index 0000000000000..7b5cafc5dc650 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc @@ -0,0 +1,734 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include + +using namespace ODBC; +using namespace driver::odbcabstraction; + +namespace { + void DescriptorToHandle(SQLPOINTER output, ODBCDescriptor* descriptor, SQLINTEGER* lenPtr) { + if (output) { + SQLHANDLE* outputHandle = static_cast(output); + *outputHandle = reinterpret_cast(descriptor); + } + if (lenPtr) { + *lenPtr = sizeof(SQLHANDLE); + } + } + + size_t GetLength(const DescriptorRecord& record) { + switch (record.m_type) { + case SQL_C_CHAR: + case SQL_C_WCHAR: + case SQL_C_BINARY: + return record.m_length; + + case SQL_C_BIT: + case SQL_C_TINYINT: + case SQL_C_STINYINT: + case SQL_C_UTINYINT: + return sizeof(SQLSCHAR); + + case SQL_C_SHORT: + case SQL_C_SSHORT: + case SQL_C_USHORT: + return sizeof(SQLSMALLINT); + + case SQL_C_LONG: + case SQL_C_SLONG: + case SQL_C_ULONG: + case SQL_C_FLOAT: + return sizeof(SQLINTEGER); + + case SQL_C_SBIGINT: + case SQL_C_UBIGINT: + case SQL_C_DOUBLE: + return sizeof(SQLBIGINT); + + case SQL_C_NUMERIC: + return sizeof(SQL_NUMERIC_STRUCT); + + case SQL_C_DATE: + case SQL_C_TYPE_DATE: + return sizeof(SQL_DATE_STRUCT); + + case SQL_C_TIME: + case SQL_C_TYPE_TIME: + return sizeof(SQL_TIME_STRUCT); + + case SQL_C_TIMESTAMP: + case SQL_C_TYPE_TIMESTAMP: + return sizeof(SQL_TIMESTAMP_STRUCT); + + case SQL_C_INTERVAL_DAY: + case SQL_C_INTERVAL_DAY_TO_HOUR: + case SQL_C_INTERVAL_DAY_TO_MINUTE: + case SQL_C_INTERVAL_DAY_TO_SECOND: + case SQL_C_INTERVAL_HOUR: + case SQL_C_INTERVAL_HOUR_TO_MINUTE: + case SQL_C_INTERVAL_HOUR_TO_SECOND: + case SQL_C_INTERVAL_MINUTE: + case SQL_C_INTERVAL_MINUTE_TO_SECOND: + case SQL_C_INTERVAL_SECOND: + case SQL_C_INTERVAL_YEAR: + case SQL_C_INTERVAL_YEAR_TO_MONTH: + case SQL_C_INTERVAL_MONTH: + return sizeof(SQL_INTERVAL_STRUCT); + default: + return record.m_length; + } + } + + SQLSMALLINT getCTypeForSQLType(const DescriptorRecord& record) { + switch (record.m_conciseType) { + case SQL_CHAR: + case SQL_VARCHAR: + case SQL_LONGVARCHAR: + return SQL_C_CHAR; + + case SQL_WCHAR: + case SQL_WVARCHAR: + case SQL_WLONGVARCHAR: + return SQL_C_WCHAR; + + case SQL_BINARY: + case SQL_VARBINARY: + case SQL_LONGVARBINARY: + return SQL_C_BINARY; + + case SQL_TINYINT: + return record.m_unsigned ? SQL_C_UTINYINT : SQL_C_STINYINT; + + case SQL_SMALLINT: + return record.m_unsigned ? SQL_C_USHORT : SQL_C_SSHORT; + + case SQL_INTEGER: + return record.m_unsigned ? SQL_C_ULONG : SQL_C_SLONG; + + case SQL_BIGINT: + return record.m_unsigned ? SQL_C_UBIGINT : SQL_C_SBIGINT; + + case SQL_REAL: + return SQL_C_FLOAT; + + case SQL_FLOAT: + case SQL_DOUBLE: + return SQL_C_DOUBLE; + + case SQL_DATE: + case SQL_TYPE_DATE: + return SQL_C_TYPE_DATE; + + case SQL_TIME: + case SQL_TYPE_TIME: + return SQL_C_TYPE_TIME; + + case SQL_TIMESTAMP: + case SQL_TYPE_TIMESTAMP: + return SQL_C_TYPE_TIMESTAMP; + + case SQL_C_INTERVAL_DAY: + return SQL_INTERVAL_DAY; + case SQL_C_INTERVAL_DAY_TO_HOUR: + return SQL_INTERVAL_DAY_TO_HOUR; + case SQL_C_INTERVAL_DAY_TO_MINUTE: + return SQL_INTERVAL_DAY_TO_MINUTE; + case SQL_C_INTERVAL_DAY_TO_SECOND: + return SQL_INTERVAL_DAY_TO_SECOND; + case SQL_C_INTERVAL_HOUR: + return SQL_INTERVAL_HOUR; + case SQL_C_INTERVAL_HOUR_TO_MINUTE: + return SQL_INTERVAL_HOUR_TO_MINUTE; + case SQL_C_INTERVAL_HOUR_TO_SECOND: + return SQL_INTERVAL_HOUR_TO_SECOND; + case SQL_C_INTERVAL_MINUTE: + return SQL_INTERVAL_MINUTE; + case SQL_C_INTERVAL_MINUTE_TO_SECOND: + return SQL_INTERVAL_MINUTE_TO_SECOND; + case SQL_C_INTERVAL_SECOND: + return SQL_INTERVAL_SECOND; + case SQL_C_INTERVAL_YEAR: + return SQL_INTERVAL_YEAR; + case SQL_C_INTERVAL_YEAR_TO_MONTH: + return SQL_INTERVAL_YEAR_TO_MONTH; + case SQL_C_INTERVAL_MONTH: + return SQL_INTERVAL_MONTH; + + default: + throw DriverException("Unknown SQL type: " + std::to_string(record.m_conciseType), "HY003"); + } + } + + void CopyAttribute(Statement& source, Statement& target, Statement::StatementAttributeId attributeId) { + auto optionalValue = source.GetAttribute(attributeId); + if (optionalValue) { + target.SetAttribute(attributeId, *optionalValue); + } + } +} + +// Public ========================================================================================= +ODBCStatement::ODBCStatement(ODBCConnection& connection, + std::shared_ptr spiStatement) : + m_connection(connection), + m_spiStatement(std::move(spiStatement)), + m_builtInArd(std::make_shared(m_spiStatement->GetDiagnostics(), nullptr, this, true, true, connection.IsOdbc2Connection())), + m_builtInApd(std::make_shared(m_spiStatement->GetDiagnostics(), nullptr, this, true, true, connection.IsOdbc2Connection())), + m_ipd(std::make_shared(m_spiStatement->GetDiagnostics(), nullptr, this, false, true, connection.IsOdbc2Connection())), + m_ird(std::make_shared(m_spiStatement->GetDiagnostics(), nullptr, this, false, false, connection.IsOdbc2Connection())), + m_currentArd(m_builtInApd.get()), + m_currentApd(m_builtInApd.get()), + m_rowNumber(0), + m_maxRows(0), + m_rowsetSize(1), + m_isPrepared(false), + m_hasReachedEndOfResult(false) { +} + +Diagnostics &ODBCStatement::GetDiagnostics_Impl() { + return m_spiStatement->GetDiagnostics(); +} + +ODBCConnection &ODBCStatement::GetConnection() { + return m_connection; +} + +void ODBCStatement::CopyAttributesFromConnection(ODBCConnection& connection) { + ODBCStatement& trackingStatement = connection.GetTrackingStatement(); + + // Get abstraction attributes and copy to this m_spiStatement. + // Possible ODBC attributes are below, but many of these are not supported by warpdrive + // or ODBCAbstaction: + // SQL_ATTR_ASYNC_ENABLE: + // SQL_ATTR_METADATA_ID: + // SQL_ATTR_CONCURRENCY: + // SQL_ATTR_CURSOR_TYPE: + // SQL_ATTR_KEYSET_SIZE: + // SQL_ATTR_MAX_LENGTH: + // SQL_ATTR_MAX_ROWS: + // SQL_ATTR_NOSCAN: + // SQL_ATTR_QUERY_TIMEOUT: + // SQL_ATTR_RETRIEVE_DATA: + // SQL_ATTR_SIMULATE_CURSOR: + // SQL_ATTR_USE_BOOKMARKS: + CopyAttribute(*trackingStatement.m_spiStatement, *m_spiStatement, Statement::METADATA_ID); + CopyAttribute(*trackingStatement.m_spiStatement, *m_spiStatement, Statement::MAX_LENGTH); + CopyAttribute(*trackingStatement.m_spiStatement, *m_spiStatement, Statement::NOSCAN); + CopyAttribute(*trackingStatement.m_spiStatement, *m_spiStatement, Statement::QUERY_TIMEOUT); + + // SQL_ATTR_ROW_BIND_TYPE: + m_currentArd->SetHeaderField(SQL_DESC_BIND_TYPE, + reinterpret_cast(static_cast(trackingStatement.m_currentArd->GetBoundStructOffset())), 0); +} + +bool ODBCStatement::isPrepared() const { + return m_isPrepared; +} + +void ODBCStatement::Prepare(const std::string& query) { + boost::optional > metadata = m_spiStatement->Prepare(query); + + if (metadata) { + m_ird->PopulateFromResultSetMetadata(metadata->get()); + } + m_isPrepared = true; +} + +void ODBCStatement::ExecutePrepared() { + if (!m_isPrepared) { + throw DriverException("Function sequence error", "HY010"); + } + + if (m_spiStatement->ExecutePrepared()) { + m_currenResult = m_spiStatement->GetResultSet(); + m_ird->PopulateFromResultSetMetadata(m_spiStatement->GetResultSet()->GetMetadata().get()); + m_hasReachedEndOfResult = false; + } +} + +void ODBCStatement::ExecuteDirect(const std::string& query) { + if (m_spiStatement->Execute(query)) { + m_currenResult = m_spiStatement->GetResultSet(); + m_ird->PopulateFromResultSetMetadata(m_currenResult->GetMetadata().get()); + m_hasReachedEndOfResult = false; + } + + // Direct execution wipes out the prepared state. + m_isPrepared = false; +} + +bool ODBCStatement::Fetch(size_t rows) { + if (m_hasReachedEndOfResult) { + m_ird->SetRowsProcessed(0); + return false; + } + + if (m_maxRows) { + rows = std::min(rows, m_maxRows - m_rowNumber); + } + + if (m_currentArd->HaveBindingsChanged()) { + // TODO: Deal handle when offset != bufferlength. + + // Wipe out all bindings in the ResultSet. + // Note that the number of ARD records can both be more or less + // than the number of columns. + SQLULEN bindOffset = m_currentArd->GetBindOffset(); + for (size_t i = 0; i < m_ird->GetRecords().size(); i++) { + if (i < m_currentArd->GetRecords().size() && m_currentArd->GetRecords()[i].m_isBound) { + const DescriptorRecord& ardRecord = m_currentArd->GetRecords()[i]; + m_currenResult->BindColumn(i+1, ardRecord.m_type, ardRecord.m_precision, + ardRecord.m_scale, reinterpret_cast(ardRecord.m_dataPtr) + bindOffset, + GetLength(ardRecord), + reinterpret_cast( + reinterpret_cast(ardRecord.m_indicatorPtr) + bindOffset)); + } else { + m_currenResult->BindColumn(i+1, CDataType_CHAR /* arbitrary type, not used */, 0, 0, nullptr, 0, nullptr); + } + } + m_currentArd->NotifyBindingsHavePropagated(); + } + + size_t rowsFetched = m_currenResult->Move(rows); + m_ird->SetRowsProcessed(static_cast(rowsFetched)); + + m_rowNumber += rowsFetched; + m_hasReachedEndOfResult = rowsFetched != rows; + return rowsFetched != 0; +} + +void ODBCStatement::GetStmtAttr(SQLINTEGER statementAttribute, + SQLPOINTER output, SQLINTEGER bufferSize, + SQLINTEGER *strLenPtr, bool isUnicode) { + using driver::odbcabstraction::Statement; + boost::optional spiAttribute; + switch (statementAttribute) { + // Descriptor accessor attributes + case SQL_ATTR_APP_PARAM_DESC: + DescriptorToHandle(output, m_currentApd, strLenPtr); + return; + case SQL_ATTR_APP_ROW_DESC: + DescriptorToHandle(output, m_currentArd, strLenPtr); + return; + case SQL_ATTR_IMP_PARAM_DESC: + DescriptorToHandle(output, m_ipd.get(), strLenPtr); + return; + case SQL_ATTR_IMP_ROW_DESC: + DescriptorToHandle(output, m_ird.get(), strLenPtr); + return; + + // Attributes that are descriptor fields + case SQL_ATTR_PARAM_BIND_OFFSET_PTR: + m_currentApd->GetHeaderField(SQL_DESC_BIND_OFFSET_PTR, output, bufferSize, strLenPtr); + return; + case SQL_ATTR_PARAM_BIND_TYPE: + m_currentApd->GetHeaderField(SQL_DESC_BIND_TYPE, output, bufferSize, strLenPtr); + return; + case SQL_ATTR_PARAM_OPERATION_PTR: + m_currentApd->GetHeaderField(SQL_DESC_ARRAY_STATUS_PTR, output, bufferSize, strLenPtr); + return; + case SQL_ATTR_PARAM_STATUS_PTR: + m_ipd->GetHeaderField(SQL_DESC_ARRAY_STATUS_PTR, output, bufferSize, strLenPtr); + return; + case SQL_ATTR_PARAMS_PROCESSED_PTR: + m_ipd->GetHeaderField(SQL_DESC_ROWS_PROCESSED_PTR, output, bufferSize, strLenPtr); + return; + case SQL_ATTR_PARAMSET_SIZE: + m_currentApd->GetHeaderField(SQL_DESC_ARRAY_SIZE, output, bufferSize, strLenPtr); + return; + case SQL_ATTR_ROW_ARRAY_SIZE: + m_currentArd->GetHeaderField(SQL_DESC_ARRAY_SIZE, output, bufferSize, strLenPtr); + return; + case SQL_ATTR_ROW_BIND_OFFSET_PTR: + m_currentArd->GetHeaderField(SQL_DESC_BIND_OFFSET_PTR, output, bufferSize, strLenPtr); + return; + case SQL_ATTR_ROW_BIND_TYPE: + m_currentArd->GetHeaderField(SQL_DESC_BIND_TYPE, output, bufferSize, strLenPtr); + return; + case SQL_ATTR_ROW_OPERATION_PTR: + m_currentArd->GetHeaderField(SQL_DESC_ARRAY_STATUS_PTR, output, bufferSize, strLenPtr); + return; + case SQL_ATTR_ROW_STATUS_PTR: + m_ird->GetHeaderField(SQL_DESC_ARRAY_STATUS_PTR, output, bufferSize, strLenPtr); + return; + case SQL_ATTR_ROWS_FETCHED_PTR: + m_ird->GetHeaderField(SQL_DESC_ROWS_PROCESSED_PTR, output, bufferSize, strLenPtr); + return; + + case SQL_ATTR_ASYNC_ENABLE: + GetAttribute(static_cast(SQL_ASYNC_ENABLE_OFF), output, bufferSize, strLenPtr); + return; + +#ifdef SQL_ATTR_ASYNC_STMT_EVENT + case SQL_ATTR_ASYNC_STMT_EVENT: + throw DriverException("Unsupported attribute", "HYC00"); +#endif +#ifdef SQL_ATTR_ASYNC_STMT_PCALLBACK + case SQL_ATTR_ASYNC_STMT_PCALLBACK: + throw DriverException("Unsupported attribute", "HYC00"); +#endif +#ifdef SQL_ATTR_ASYNC_STMT_PCONTEXT + case SQL_ATTR_ASYNC_STMT_PCONTEXT: + throw DriverException("Unsupported attribute", "HYC00"); +#endif + case SQL_ATTR_CURSOR_SCROLLABLE: + GetAttribute(static_cast(SQL_NONSCROLLABLE), output, bufferSize, strLenPtr); + return; + + case SQL_ATTR_CURSOR_SENSITIVITY: + GetAttribute(static_cast(SQL_UNSPECIFIED), output, bufferSize, strLenPtr); + return; + + case SQL_ATTR_CURSOR_TYPE: + GetAttribute(static_cast(SQL_CURSOR_FORWARD_ONLY), output, bufferSize, strLenPtr); + return; + + case SQL_ATTR_ENABLE_AUTO_IPD: + GetAttribute(static_cast(SQL_FALSE), output, bufferSize, strLenPtr); + return; + + case SQL_ATTR_FETCH_BOOKMARK_PTR: + GetAttribute(static_cast(NULL), output, bufferSize, strLenPtr); + return; + + case SQL_ATTR_KEYSET_SIZE: + GetAttribute(static_cast(0), output, bufferSize, strLenPtr); + return; + + case SQL_ATTR_ROW_NUMBER: + GetAttribute(static_cast(m_rowNumber), output, bufferSize, strLenPtr); + return; + case SQL_ATTR_SIMULATE_CURSOR: + GetAttribute(static_cast(SQL_SC_UNIQUE), output, bufferSize, strLenPtr); + return; + case SQL_ATTR_USE_BOOKMARKS: + GetAttribute(static_cast(SQL_UB_OFF), output, bufferSize, strLenPtr); + return; + case SQL_ATTR_CONCURRENCY: + GetAttribute(static_cast(SQL_CONCUR_READ_ONLY), output, bufferSize, strLenPtr); + return; + case SQL_ATTR_MAX_ROWS: + GetAttribute(static_cast(m_maxRows), output, bufferSize, strLenPtr); + return; + case SQL_ATTR_RETRIEVE_DATA: + GetAttribute(static_cast(SQL_RD_ON), output, bufferSize, strLenPtr); + return; + case SQL_ROWSET_SIZE: + GetAttribute(static_cast(m_rowsetSize), output, bufferSize, strLenPtr); + return; + + // Driver-level statement attributes. These are all SQLULEN attributes. + case SQL_ATTR_MAX_LENGTH: + spiAttribute = m_spiStatement->GetAttribute(Statement::MAX_LENGTH); + break; + case SQL_ATTR_METADATA_ID: + spiAttribute = m_spiStatement->GetAttribute(Statement::METADATA_ID); + break; + case SQL_ATTR_NOSCAN: + spiAttribute = m_spiStatement->GetAttribute(Statement::NOSCAN); + break; + case SQL_ATTR_QUERY_TIMEOUT: + spiAttribute = m_spiStatement->GetAttribute(Statement::QUERY_TIMEOUT); + break; + default: + throw DriverException("Invalid statement attribute: " + std::to_string(statementAttribute), "HY092"); + } + + if (spiAttribute) { + GetAttribute(static_cast(boost::get(*spiAttribute)), + output, bufferSize, strLenPtr); + return; + } + + throw DriverException("Invalid statement attribute: " + std::to_string(statementAttribute), "HY092"); +} + +void ODBCStatement::SetStmtAttr(SQLINTEGER statementAttribute, SQLPOINTER value, + SQLINTEGER bufferSize, bool isUnicode) { + size_t attributeToWrite = 0; + bool successfully_written = false; + + switch (statementAttribute) { + case SQL_ATTR_APP_PARAM_DESC: { + ODBCDescriptor* desc = static_cast(value); + if (m_currentApd != desc) { + if (m_currentApd != m_builtInApd.get()) { + m_currentApd->DetachFromStatement(this, true); + } + m_currentApd = desc; + if (m_currentApd != m_builtInApd.get()) { + desc->RegisterToStatement(this, true); + } + } + return; + } + case SQL_ATTR_APP_ROW_DESC: { + ODBCDescriptor* desc = static_cast(value); + if (m_currentArd != desc) { + if (m_currentArd != m_builtInArd.get()) { + m_currentArd->DetachFromStatement(this, false); + } + m_currentArd = desc; + if (m_currentArd != m_builtInArd.get()) { + desc->RegisterToStatement(this, false); + } + } + return; + } + case SQL_ATTR_IMP_PARAM_DESC: + throw DriverException("Cannot assign implementation descriptor.", "HY017"); + case SQL_ATTR_IMP_ROW_DESC: + throw DriverException("Cannot assign implementation descriptor.", "HY017"); + // Attributes that are descriptor fields + case SQL_ATTR_PARAM_BIND_OFFSET_PTR: + m_currentApd->SetHeaderField(SQL_DESC_BIND_OFFSET_PTR, value, bufferSize); + return; + case SQL_ATTR_PARAM_BIND_TYPE: + m_currentApd->SetHeaderField(SQL_DESC_BIND_TYPE, value, bufferSize); + return; + case SQL_ATTR_PARAM_OPERATION_PTR: + m_currentApd->SetHeaderField(SQL_DESC_ARRAY_STATUS_PTR, value, bufferSize); + return; + case SQL_ATTR_PARAM_STATUS_PTR: + m_ipd->SetHeaderField(SQL_DESC_ARRAY_STATUS_PTR, value, bufferSize); + return; + case SQL_ATTR_PARAMS_PROCESSED_PTR: + m_ipd->SetHeaderField(SQL_DESC_ROWS_PROCESSED_PTR, value, bufferSize); + return; + case SQL_ATTR_PARAMSET_SIZE: + m_currentApd->SetHeaderField(SQL_DESC_ARRAY_SIZE, value, bufferSize); + return; + case SQL_ATTR_ROW_ARRAY_SIZE: + m_currentArd->SetHeaderField(SQL_DESC_ARRAY_SIZE, value, bufferSize); + return; + case SQL_ATTR_ROW_BIND_OFFSET_PTR: + m_currentArd->SetHeaderField(SQL_DESC_BIND_OFFSET_PTR, value, bufferSize); + return; + case SQL_ATTR_ROW_BIND_TYPE: + m_currentArd->SetHeaderField(SQL_DESC_BIND_TYPE, value, bufferSize); + return; + case SQL_ATTR_ROW_OPERATION_PTR: + m_currentArd->SetHeaderField(SQL_DESC_ARRAY_STATUS_PTR, value, bufferSize); + return; + case SQL_ATTR_ROW_STATUS_PTR: + m_ird->SetHeaderField(SQL_DESC_ARRAY_STATUS_PTR, value, bufferSize); + return; + case SQL_ATTR_ROWS_FETCHED_PTR: + m_ird->SetHeaderField(SQL_DESC_ROWS_PROCESSED_PTR, value, bufferSize); + return; + + case SQL_ATTR_ASYNC_ENABLE: +#ifdef SQL_ATTR_ASYNC_STMT_EVENT + case SQL_ATTR_ASYNC_STMT_EVENT: + throw DriverException("Unsupported attribute", "HYC00"); +#endif +#ifdef SQL_ATTR_ASYNC_STMT_PCALLBACK + case SQL_ATTR_ASYNC_STMT_PCALLBACK: + throw DriverException("Unsupported attribute", "HYC00"); +#endif +#ifdef SQL_ATTR_ASYNC_STMT_PCONTEXT + case SQL_ATTR_ASYNC_STMT_PCONTEXT: + throw DriverException("Unsupported attribute", "HYC00"); +#endif + case SQL_ATTR_CONCURRENCY: + CheckIfAttributeIsSetToOnlyValidValue(value, static_cast(SQL_CONCUR_READ_ONLY)); + return; + case SQL_ATTR_CURSOR_SCROLLABLE: + CheckIfAttributeIsSetToOnlyValidValue(value, static_cast(SQL_NONSCROLLABLE)); + return; + case SQL_ATTR_CURSOR_SENSITIVITY: + CheckIfAttributeIsSetToOnlyValidValue(value, static_cast(SQL_UNSPECIFIED)); + return; + case SQL_ATTR_CURSOR_TYPE: + CheckIfAttributeIsSetToOnlyValidValue(value, static_cast(SQL_CURSOR_FORWARD_ONLY)); + return; + case SQL_ATTR_ENABLE_AUTO_IPD: + CheckIfAttributeIsSetToOnlyValidValue(value, static_cast(SQL_FALSE)); + return; + case SQL_ATTR_FETCH_BOOKMARK_PTR: + if (value != NULL) { + throw DriverException("Optional feature not implemented", "HYC00"); + } + return; + case SQL_ATTR_KEYSET_SIZE: + CheckIfAttributeIsSetToOnlyValidValue(value, static_cast(0)); + return; + case SQL_ATTR_ROW_NUMBER: + throw DriverException("Cannot set read-only attribute", "HY092"); + case SQL_ATTR_SIMULATE_CURSOR: + CheckIfAttributeIsSetToOnlyValidValue(value, static_cast(SQL_SC_UNIQUE)); + return; + case SQL_ATTR_USE_BOOKMARKS: + CheckIfAttributeIsSetToOnlyValidValue(value, static_cast(SQL_UB_OFF)); + return; + case SQL_ATTR_RETRIEVE_DATA: + CheckIfAttributeIsSetToOnlyValidValue(value, static_cast(SQL_TRUE)); + return; + case SQL_ROWSET_SIZE: + SetAttribute(value, m_rowsetSize); + return; + + case SQL_ATTR_MAX_ROWS: + throw DriverException("Cannot set read-only attribute", "HY092"); + + // Driver-leve statement attributes. These are all size_t attributes + case SQL_ATTR_MAX_LENGTH: + SetAttribute(value, attributeToWrite); + successfully_written = m_spiStatement->SetAttribute(Statement::MAX_LENGTH, attributeToWrite); + break; + case SQL_ATTR_METADATA_ID: + SetAttribute(value, attributeToWrite); + successfully_written = m_spiStatement->SetAttribute(Statement::METADATA_ID, attributeToWrite); + break; + case SQL_ATTR_NOSCAN: + SetAttribute(value, attributeToWrite); + successfully_written = m_spiStatement->SetAttribute(Statement::NOSCAN, attributeToWrite); + break; + case SQL_ATTR_QUERY_TIMEOUT: + SetAttribute(value, attributeToWrite); + successfully_written = m_spiStatement->SetAttribute(Statement::QUERY_TIMEOUT, attributeToWrite); + break; + default: + throw DriverException("Invalid attribute: " + std::to_string(attributeToWrite), "HY092"); + } + if (!successfully_written) { + GetDiagnostics().AddWarning("Optional value changed.", "01S02", ODBCErrorCodes_GENERAL_WARNING); + } +} + +void ODBCStatement::RevertAppDescriptor(bool isApd) { + if (isApd) { + m_currentApd = m_builtInApd.get(); + } else { + m_currentArd = m_builtInArd.get(); + } +} + +void ODBCStatement::closeCursor(bool suppressErrors) { + if (!suppressErrors && !m_currenResult) { + throw DriverException("Invalid cursor state", "28000"); + } + + if (m_currenResult) { + m_currenResult->Close(); + m_currenResult = nullptr; + } +} + +bool ODBCStatement::GetData(SQLSMALLINT recordNumber, SQLSMALLINT cType, SQLPOINTER dataPtr, SQLLEN bufferLength, SQLLEN* indicatorPtr) { + if (recordNumber == 0) { + throw DriverException("Bookmarks are not supported", "07009"); + } else if (recordNumber > m_ird->GetRecords().size()) { + throw DriverException("Invalid column index: " + std::to_string(recordNumber), "07009"); + } + + SQLSMALLINT evaluatedCType = cType; + + // TODO: Get proper default precision and scale from abstraction. + int precision = 0; + int scale = 0; + + if (cType == SQL_ARD_TYPE) { + // DM should validate the ARD size. + assert(m_currentArd->GetRecords().size() <= recordNumber); + const DescriptorRecord& record = m_currentArd->GetRecords()[recordNumber-1]; + evaluatedCType = record.m_conciseType; + precision = record.m_precision; + scale = record.m_scale; + } + + // Note: this is intentionally not an else if, since the type can be SQL_C_DEFAULT in the ARD. + if (evaluatedCType == SQL_C_DEFAULT) { + const DescriptorRecord& ardRecord = m_currentArd->GetRecords()[recordNumber-1]; + precision = ardRecord.m_precision; + scale = ardRecord.m_scale; + + const DescriptorRecord& irdRecord = m_ird->GetRecords()[recordNumber-1]; + evaluatedCType = getCTypeForSQLType(irdRecord); + } + + return m_currenResult->GetData(recordNumber, evaluatedCType, precision, + scale, dataPtr, bufferLength, indicatorPtr); +} + +void ODBCStatement::releaseStatement() { + closeCursor(true); + m_connection.dropStatement(this); +} + +void ODBCStatement::GetTables(const std::string* catalog, const std::string* schema, const std::string* table, const std::string* tableType) { + closeCursor(true); + if (m_connection.IsOdbc2Connection()) { + m_currenResult = m_spiStatement->GetTables_V2(catalog, schema, table, tableType); + } else { + m_currenResult = m_spiStatement->GetTables_V3(catalog, schema, table, tableType); + } + m_ird->PopulateFromResultSetMetadata(m_currenResult->GetMetadata().get()); + m_hasReachedEndOfResult = false; + + // Direct execution wipes out the prepared state. + m_isPrepared = false; +} + +void ODBCStatement::GetColumns(const std::string* catalog, const std::string* schema, const std::string* table, const std::string* column) { + closeCursor(true); + if (m_connection.IsOdbc2Connection()) { + m_currenResult = m_spiStatement->GetColumns_V2(catalog, schema, table, column); + } else { + m_currenResult = m_spiStatement->GetColumns_V3(catalog, schema, table, column); + } + m_ird->PopulateFromResultSetMetadata(m_currenResult->GetMetadata().get()); + m_hasReachedEndOfResult = false; + + // Direct execution wipes out the prepared state. + m_isPrepared = false; +} + +void ODBCStatement::GetTypeInfo(SQLSMALLINT dataType) { + closeCursor(true); + if (m_connection.IsOdbc2Connection()) { + m_currenResult = m_spiStatement->GetTypeInfo_V2(dataType); + } else { + m_currenResult = m_spiStatement->GetTypeInfo_V3(dataType); + } + m_ird->PopulateFromResultSetMetadata(m_currenResult->GetMetadata().get()); + m_hasReachedEndOfResult = false; + + // Direct execution wipes out the prepared state. + m_isPrepared = false; +} + +void ODBCStatement::Cancel() { + m_spiStatement->Cancel(); +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc index 0e9d864c54e5f..aea9fd3b04667 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc @@ -22,7 +22,7 @@ namespace driver { namespace odbcabstraction { -bool AsBool(const std::string& value, const bool default_value) { +bool AsBool(const std::string& value, bool default_value) { if (boost::iequals(value, "true") || boost::iequals(value, "1")) { return true; } else if (boost::iequals(value, "false") || boost::iequals(value, "0")) { @@ -32,8 +32,8 @@ bool AsBool(const std::string& value, const bool default_value) { } } -bool AsBool( const bool default_value, const Connection::ConnPropertyMap& connPropertyMap, - const std::string& property_name) { +bool AsBool(bool default_value, const Connection::ConnPropertyMap& connPropertyMap, + const std::string& property_name) { auto extracted_property = connPropertyMap.find( property_name); From cb5b48aa478e7700dcacf6f22bd44ffca1ae482e Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 6 Jun 2022 14:27:38 -0700 Subject: [PATCH 117/183] Fix SQLGetData not switching arrays when iterating chunks SQLGetData was re-using the same array from the first chunk in a FlightStream, rather than rebuilding its accessor with the next array in the chunk. This would cause data to repeat itself over and over, and also crash when iterating over multi-chunk data because the size of all chunks isn't the same (so there'd be an array out of bounds error). Change-Id: I2413fae26f64caa41ac122861aa5fe810a94d5cd --- .../flight_sql/flight_sql_result_set_column.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index 1f89799479d7f..f0e913b38c877 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -67,6 +67,7 @@ FlightSqlResultSetColumn::GetAccessorForTargetType(CDataType target_type) { } cached_accessor_ = CreateAccessor(target_type); + cached_original_array_ = original_array.get(); return cached_accessor_.get(); } @@ -100,9 +101,10 @@ void FlightSqlResultSetColumn::ResetBinding() { } void FlightSqlResultSetColumn::ResetAccessor() { - if (is_bound) { - cached_accessor_.reset(); - } + // An improvement would be to have ResetAccessor take in a newly acquired array. + // Then the accessor itself should switch to the new array and reset internal + // state, rather than deleting the accessor. + cached_accessor_.reset(); } } // namespace flight_sql From b3e26d6bc268958478b06080dcefa49cad5dba93 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 7 Jun 2022 11:01:41 -0300 Subject: [PATCH 118/183] Fix: FlightSqlResultSet#Move() overriding previous batches on bound columns When a single Move() call reads from multiple RecordBatches, the first batch results are overwritten by the second one, this fixes this issue by shifting the buffer start position between batches. Change-Id: I726e22553723bae79c08ce29e7e72438cbb15a26 --- .../flight_sql/accessors/binary_array_accessor.cc | 5 +++++ .../flight_sql/accessors/binary_array_accessor.h | 2 ++ .../flight_sql/accessors/boolean_array_accessor.cc | 7 ++++++- .../flight_sql/accessors/boolean_array_accessor.h | 2 ++ .../flight_sql/accessors/date_array_accessor.cc | 7 ++++++- .../flight_sql/accessors/date_array_accessor.h | 2 ++ .../flight_sql/accessors/decimal_array_accessor.cc | 7 ++++++- .../flight_sql/accessors/decimal_array_accessor.h | 2 ++ .../accessors/primitive_array_accessor.cc | 5 +++++ .../flight_sql/accessors/primitive_array_accessor.h | 2 ++ .../flight_sql/accessors/string_array_accessor.cc | 5 +++++ .../flight_sql/accessors/string_array_accessor.h | 2 ++ .../flight_sql/accessors/time_array_accessor.cc | 7 ++++++- .../flight_sql/accessors/time_array_accessor.h | 2 ++ .../accessors/timestamp_array_accessor.cc | 7 ++++++- .../flight_sql/accessors/timestamp_array_accessor.h | 2 ++ .../flightsql-odbc/flight_sql/accessors/types.h | 6 ++++++ .../flight_sql/flight_sql_result_set.cc | 13 ++++++++----- 18 files changed, 75 insertions(+), 10 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc index 7f6bf0ad4d739..0e7180c769cb0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc @@ -74,6 +74,11 @@ void BinaryArrayFlightSqlAccessor::MoveSingleCell_impl( MoveSingleCellToBinaryBuffer(binding, array, i, value_offset, update_value_offset, diagnostics); } +template +size_t BinaryArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { + return binding->buffer_length; +} + template class BinaryArrayFlightSqlAccessor; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h index 1d322874de1fe..f678fa2a98fbb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h @@ -36,6 +36,8 @@ class BinaryArrayFlightSqlAccessor void MoveSingleCell_impl(ColumnBinding *binding, BinaryArray *array, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); + + size_t GetCellLength_impl(ColumnBinding *binding) const; }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc index 7b7e17f35afbb..264f2df54774e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc @@ -40,10 +40,15 @@ void BooleanArrayFlightSqlAccessor::MoveSingleCell_impl( buffer[i] = value ? 1 : 0; if (binding->strlen_buffer) { - binding->strlen_buffer[i] = static_cast(sizeof(unsigned char)); + binding->strlen_buffer[i] = static_cast(GetCellLength_impl(binding)); } } +template +size_t BooleanArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { + return sizeof(unsigned char); +} + template class BooleanArrayFlightSqlAccessor; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h index 3f174873fd720..e79a5461a4404 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h @@ -37,6 +37,8 @@ class BooleanArrayFlightSqlAccessor void MoveSingleCell_impl(ColumnBinding *binding, BooleanArray *array, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); + + size_t GetCellLength_impl(ColumnBinding *binding) const; }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc index 6ce5473264be4..2b6874b70c48d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc @@ -71,10 +71,15 @@ void DateArrayFlightSqlAccessor::MoveSingleCell_impl( buffer[cell_counter].day = date.tm_mday; if (binding->strlen_buffer) { - binding->strlen_buffer[cell_counter] = static_cast(sizeof(DATE_STRUCT)); + binding->strlen_buffer[cell_counter] = static_cast(GetCellLength_impl(binding)); } } +template +size_t DateArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { + return sizeof(DATE_STRUCT); +} + template class DateArrayFlightSqlAccessor; template class DateArrayFlightSqlAccessor::MoveSing } if (binding->strlen_buffer) { - binding->strlen_buffer[i] = static_cast(sizeof(NUMERIC_STRUCT)); + binding->strlen_buffer[i] = static_cast(GetCellLength_impl(binding)); } } +template +size_t DecimalArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { + return sizeof(NUMERIC_STRUCT); +} + template class DecimalArrayFlightSqlAccessor; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h index 880f6ece599a5..6a2a26d9bfe4e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h @@ -40,6 +40,8 @@ class DecimalArrayFlightSqlAccessor int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); + size_t GetCellLength_impl(ColumnBinding *binding) const; + private: std::shared_ptr data_type_; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc index fae785a109376..5cb90761e8b89 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc @@ -38,6 +38,11 @@ PrimitiveArrayFlightSqlAccessor::GetColumnarData_impl( return CopyFromArrayValuesToBinding(sliced_array, binding); } +template +size_t PrimitiveArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { + return sizeof(typename ARROW_ARRAY::TypeClass::c_type); +} + template class PrimitiveArrayFlightSqlAccessor< Int64Array, odbcabstraction::CDataType_SBIGINT>; template class PrimitiveArrayFlightSqlAccessor< diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h index d31c26c7c61de..777853f4bef0e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h @@ -41,6 +41,8 @@ class PrimitiveArrayFlightSqlAccessor size_t GetColumnarData_impl(const std::shared_ptr &sliced_array, ColumnBinding *binding, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); + + size_t GetCellLength_impl(ColumnBinding *binding) const; }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc index ac5b081b8a50b..aba0e603f6114 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -107,6 +107,11 @@ void StringArrayFlightSqlAccessor::MoveSingleCell_impl( value_offset, update_value_offset, diagnostics); } +template +size_t StringArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { + return binding->buffer_length; +} + template class StringArrayFlightSqlAccessor; template class StringArrayFlightSqlAccessor; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h index ebf8eca79e088..80e094bc61fe3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h @@ -40,6 +40,8 @@ class StringArrayFlightSqlAccessor int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); + size_t GetCellLength_impl(ColumnBinding *binding) const; + private: CharToWStrConverter converter_; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc index 4065811419daf..05022d23454af 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc @@ -68,10 +68,15 @@ void TimeArrayFlightSqlAccessor::MoveSingleCell_impl( buffer[cell_counter].second = time.tm_sec; if (binding->strlen_buffer) { - binding->strlen_buffer[cell_counter] = static_cast(sizeof(TIME_STRUCT)); + binding->strlen_buffer[cell_counter] = static_cast(GetCellLength_impl(binding)); } } +template +size_t TimeArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { + return sizeof(TIME_STRUCT); +} + template class TimeArrayFlightSqlAccessor; template class TimeArrayFlightSqlAccessor::MoveSingleCell_impl(ColumnBinding buffer[cell_counter].fraction = value % divisor; if (binding->strlen_buffer) { - binding->strlen_buffer[cell_counter] = static_cast(sizeof(TIMESTAMP_STRUCT)); + binding->strlen_buffer[cell_counter] = static_cast(GetCellLength_impl(binding)); } } +template +size_t TimestampArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { + return sizeof(TIMESTAMP_STRUCT); +} + template class TimestampArrayFlightSqlAccessor; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h index 58ff94e39d60f..bc6df05bc13f6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h @@ -39,6 +39,8 @@ class TimestampArrayFlightSqlAccessor int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); + size_t GetCellLength_impl(ColumnBinding *binding) const; + private: std::shared_ptr timestamp_type_; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h index 708f5768be96b..f7fb60c3f4b79 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h @@ -65,6 +65,8 @@ class Accessor { virtual size_t GetColumnarData(ColumnBinding *binding, int64_t starting_row, size_t cells, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) = 0; + + virtual size_t GetCellLength(ColumnBinding *binding) const = 0; }; template @@ -85,6 +87,10 @@ class FlightSqlAccessor : public Accessor { value_offset, update_value_offset, diagnostics); } + size_t GetCellLength(ColumnBinding *binding) const override { + return static_cast(this)->GetCellLength_impl(binding); + } + private: ARROW_ARRAY *array_; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index 1826b006307cd..ae7ab576cc22f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -105,16 +105,19 @@ size_t FlightSqlResultSet::Move(size_t rows) { continue; } - for (auto it = columns_.begin(); it != columns_.end(); ++it) { - auto &column = *it; - + for (auto & column : columns_) { // There can be unbound columns. if (!column.is_bound) continue; int64_t value_offset = 0; - size_t accessor_rows = column.GetAccessorForBinding()->GetColumnarData( - &column.binding, current_row_, rows_to_fetch, value_offset, false, diagnostics_); + + auto *accessor = column.GetAccessorForBinding(); + ColumnBinding shifted_binding = column.binding; + shifted_binding.buffer = static_cast(shifted_binding.buffer) + accessor->GetCellLength(&shifted_binding) * fetched_rows; + + size_t accessor_rows = accessor->GetColumnarData( + &shifted_binding, current_row_, rows_to_fetch, value_offset, false, diagnostics_); if (rows_to_fetch != accessor_rows) { throw DriverException( From 24dd38698d00fbe800e374722ee3ce1de111837f Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Wed, 8 Jun 2022 14:19:42 -0300 Subject: [PATCH 119/183] Change default Arrow ref to specific master commit Change-Id: I703d3b0e79a892575c24c3b4ab3af43f79029803 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 7d659af797f39..9737be1463afe 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -126,7 +126,7 @@ else() endif() set(ARROW_GIT_REPOSITORY "https://github.com/apache/arrow.git" CACHE STRING "Arrow repository path or URL") -set(ARROW_GIT_TAG "master" CACHE STRING "Tag for the Arrow repository") +set(ARROW_GIT_TAG "b050bd0d31db6412256cec3362c0d57c9732e1f2" CACHE STRING "Tag for the Arrow repository") message("Using Arrow from ${ARROW_GIT_REPOSITORY} on tag ${ARROW_GIT_TAG}") ExternalProject_Add(ApacheArrow From 81fb96a851311e432370c465c2f0748590bd31d6 Mon Sep 17 00:00:00 2001 From: James Duong Date: Tue, 7 Jun 2022 15:13:47 -0700 Subject: [PATCH 120/183] Fix format for SQL_DBMS_VER Change SQL_DBMS_VER to use the format ##.##.#### to match the ODBC spec. Interpret FLIGHT_SQL_SERVER_VERSION when it has missing or invalid values in the version number to match the format above. (Fill out dummy values when we see an illegal sequence then paste the illegal sequence at the end). Change-Id: I93a4d7c6d6db7de9c013705b55c586138559f55c --- .../flight_sql_statement_get_tables.cc | 5 -- .../flight_sql/get_info_cache.cc | 3 +- .../flightsql-odbc/flight_sql/utils.cc | 82 +++++++++++++++++++ .../flightsql-odbc/flight_sql/utils.h | 2 + .../flightsql-odbc/flight_sql/utils_test.cc | 10 +++ .../flightsql-odbc/vcpkg.json | 4 +- 6 files changed, 98 insertions(+), 8 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc index d29a20342ebee..fde43badb215b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc @@ -23,9 +23,6 @@ #include "record_batch_transformer.h" #include "utils.h" -#include -#include - namespace driver { namespace flight_sql { @@ -34,8 +31,6 @@ using arrow::flight::FlightClientOptions; using arrow::flight::FlightInfo; using arrow::flight::sql::FlightSqlClient; -typedef boost::tokenizer> Tokenizer; - void ParseTableTypes(const std::string &table_type, std::vector &table_types) { bool encountered = false; // for checking if there is a single quote diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc index b188723d27af9..74343f0a71baa 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc @@ -323,7 +323,8 @@ bool GetInfoCache::LoadInfoFromServer() { break; } case SqlInfoOptions::FLIGHT_SQL_SERVER_VERSION: { - info_[SQL_DBMS_VER] = std::string(reinterpret_cast(scalar->value.get())->view()); + info_[SQL_DBMS_VER] = ConvertToDBMSVer( + std::string(reinterpret_cast(scalar->value.get())->view())); break; } case SqlInfoOptions::FLIGHT_SQL_SERVER_ARROW_VERSION: { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 8fe5131226693..6a3062500c52e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -21,7 +21,9 @@ #include #include #include +#include #include +#include #include "json_converter.h" namespace driver { @@ -754,5 +756,85 @@ ArrayConvertTask GetConverter(arrow::Type::type original_type_id, }; } } +std::string ConvertToDBMSVer(const std::string &str) { + boost::char_separator separator("."); + boost::tokenizer< boost::char_separator > tokenizer(str, separator); + std::string result; + // The permitted ODBC format is ##.##.#### + // If any of the first 3 tokens are not numbers or are greater than the permitted digits, + // assume we hit the custom-server-information early and assume the remaining version digits are zero. + size_t position = 0; + bool is_showing_custom_data = false; + auto pad_remaining_tokens = [&](size_t pos) -> std::string { + std::string padded_str; + if (pos == 0) { + padded_str += "00"; + } + if (pos <= 1) { + padded_str += ".00"; + } + if (pos <= 2) { + padded_str += ".0000"; + } + return padded_str; + }; + + for(auto token : tokenizer) + { + if (token.empty()) { + continue; + } + + if (!is_showing_custom_data && position < 3) { + std::string suffix; + try { + size_t next_pos = 0; + int version = stoi(token, &next_pos); + if (next_pos != token.size()) { + suffix = &token[0]; + } + if (version < 0 || + (position < 2 && (version > 99)) || + (position == 2 && version > 9999)) { + is_showing_custom_data = true; + } else { + std::stringstream strstream; + if (position == 2) { + strstream << std::setfill('0') << std::setw(4); + } else { + strstream << std::setfill('0') << std::setw(2); + } + strstream << version; + + if (position != 0) { + result += "."; + } + result += strstream.str(); + if (next_pos != token.size()) { + suffix = &token[next_pos]; + result += pad_remaining_tokens(++position) + suffix; + position = 4; // Prevent additional padding. + is_showing_custom_data = true; + continue; + } + ++position; + continue; + } + } catch (std::logic_error&) { + is_showing_custom_data = true; + } + + result += pad_remaining_tokens(position) + suffix; + ++position; + } + + result += "." + token; + ++position; + } + + result += pad_remaining_tokens(position); + return result; +} + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index 844d5fc5c5305..39b47bb1b6365 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -111,5 +111,7 @@ std::shared_ptr CheckConversion(const arrow::Result ArrayConvertTask GetConverter(arrow::Type::type original_type_id, odbcabstraction::CDataType target_type); +std::string ConvertToDBMSVer(const std::string& str); + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc index f759827f0c764..1372ddf3366cc 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc @@ -60,5 +60,15 @@ TEST(Utils, ConvertSqlPatternToRegexString) { ASSERT_EQ(std::string("X_Y"), ConvertSqlPatternToRegexString("X\\_Y")); } +TEST(Utils, ConvertToDBMSVer) { + ASSERT_EQ(std::string("01.02.0003"), ConvertToDBMSVer("1.2.3")); + ASSERT_EQ(std::string("01.02.0003.0"), ConvertToDBMSVer("1.2.3.0")); + ASSERT_EQ(std::string("01.02.0000"), ConvertToDBMSVer("1.2")); + ASSERT_EQ(std::string("01.00.0000"), ConvertToDBMSVer("1")); + ASSERT_EQ(std::string("01.02.0000-foo"), ConvertToDBMSVer("1.2-foo")); + ASSERT_EQ(std::string("01.00.0000-foo"), ConvertToDBMSVer("1-foo")); + ASSERT_EQ(std::string("10.11.0001-foo"), ConvertToDBMSVer("10.11.1-foo")); +} + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json index 959c675cceee2..596bd5f0e86d9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json @@ -5,12 +5,12 @@ "abseil", "benchmark", "boost-beast", + "boost-crc", "boost-filesystem", "boost-multiprecision", + "boost-optional", "boost-process", "boost-system", - "boost-crc", - "boost-optional", "boost-variant", "boost-xpressive", "brotli", From e6ea62a82ee553147400b695152672f73c7624da Mon Sep 17 00:00:00 2001 From: James Duong Date: Wed, 8 Jun 2022 10:31:19 -0700 Subject: [PATCH 121/183] Make the IRD accessor non-const Make the accessor for the IRD from the ODBCStatement non-const. SQLExtendedFetch temporarily sets IRD fields, so this change is in support of this. Change-Id: I2af9f50946abdae7717f8c1852376afda3adef6b --- .../include/odbcabstraction/odbc_impl/ODBCStatement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h index ac57d0fda22cf..9c1933320656b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h @@ -73,7 +73,7 @@ class ODBCStatement : public ODBCHandle { void RevertAppDescriptor(bool isApd); - inline const ODBCDescriptor* GetIRD() const { + inline ODBCDescriptor* GetIRD() { return m_ird.get(); } From adee0b5b53b2484dfda8d6f5ac62dac472ffa3d9 Mon Sep 17 00:00:00 2001 From: James Duong Date: Wed, 8 Jun 2022 13:32:26 -0700 Subject: [PATCH 122/183] Adapt Flight SQL driver for the OLE DB to ODBC bridge - Allow "User ID" to be another alias for Username. - Ignore generic connection properties that contain spaces with a warning because OLE DB generates these by default (such as "Persist Security Info") Change-Id: I095670765ed83372e6b7a30e399453ad43743a64 --- .../flight_sql/flight_sql_auth_method.cc | 7 +++++ .../flight_sql/flight_sql_connection.cc | 20 +++++++++++-- .../flight_sql/flight_sql_connection.h | 1 + .../flight_sql/flight_sql_connection_test.cc | 29 +++++++++++++++++++ .../flight_sql/ui/dsn_configuration_window.cc | 4 +-- 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 90d556b2c8de1..b9b63b614ee93 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -136,6 +136,13 @@ std::unique_ptr FlightSqlAuthMethod::FromProperties( // Check if should use user-password authentication auto it_user = properties.find(FlightSqlConnection::USER); + if (it_user == properties.end()) { + // The Microsoft OLE DB to ODBC bridge provider (MSDASQL) will write + // "User ID" and "Password" properties instead of mapping + // to ODBC compliant UID/PWD keys. + it_user = properties.find(FlightSqlConnection::USER_ID); + } + auto it_password = properties.find(FlightSqlConnection::PASSWORD); auto it_token = properties.find(FlightSqlConnection::TOKEN); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 809fffc3ed300..295e24320bd12 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -60,6 +60,7 @@ const std::string FlightSqlConnection::DRIVER = "driver"; const std::string FlightSqlConnection::HOST = "host"; const std::string FlightSqlConnection::PORT = "port"; const std::string FlightSqlConnection::USER = "user"; +const std::string FlightSqlConnection::USER_ID = "user id"; const std::string FlightSqlConnection::UID = "uid"; const std::string FlightSqlConnection::PASSWORD = "password"; const std::string FlightSqlConnection::PWD = "pwd"; @@ -70,8 +71,8 @@ const std::string FlightSqlConnection::TRUSTED_CERTS = "trustedCerts"; const std::string FlightSqlConnection::USE_SYSTEM_TRUST_STORE = "useSystemTrustStore"; const std::vector FlightSqlConnection::ALL_KEYS = { - FlightSqlConnection::DSN, FlightSqlConnection::DRIVER, FlightSqlConnection::HOST, FlightSqlConnection::PORT, - FlightSqlConnection::TOKEN, FlightSqlConnection::UID, FlightSqlConnection::PWD, FlightSqlConnection::USE_ENCRYPTION, + FlightSqlConnection::DSN, FlightSqlConnection::DRIVER, FlightSqlConnection::HOST, FlightSqlConnection::PORT, + FlightSqlConnection::TOKEN, FlightSqlConnection::UID, FlightSqlConnection::USER_ID, FlightSqlConnection::PWD, FlightSqlConnection::USE_ENCRYPTION, FlightSqlConnection::TRUSTED_CERTS, FlightSqlConnection::USE_SYSTEM_TRUST_STORE, FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION }; namespace { @@ -116,6 +117,7 @@ const std::set BUILT_IN_PROP FlightSqlConnection::HOST, FlightSqlConnection::PORT, FlightSqlConnection::USER, + FlightSqlConnection::USER_ID, FlightSqlConnection::UID, FlightSqlConnection::PASSWORD, FlightSqlConnection::PWD, @@ -130,7 +132,7 @@ Connection::ConnPropertyMap::const_iterator TrackMissingRequiredProperty(const std::string &property, const Connection::ConnPropertyMap &properties, std::vector &missing_attr) { - Connection::ConnPropertyMap::const_iterator prop_iter = + auto prop_iter = properties.find(property); if (properties.end() == prop_iter) { missing_attr.push_back(property); @@ -209,7 +211,19 @@ FlightSqlConnection::PopulateCallOptions(const ConnPropertyMap &props) { continue; } + if (prop.first.find(' ') != std::string::npos) { + // Connection properties containing spaces will crash gRPC, but some tools + // such as the OLE DB to ODBC bridge generate unused properties containing spaces. + diagnostics_.AddWarning( + std::string("Ignoring connection option " + prop.first) + + ". Server-specific options must be valid HTTP header names and " + + "cannot contain spaces.", + "01000", odbcabstraction::ODBCErrorCodes_GENERAL_WARNING); + continue; + } + // Note: header names must be lower case for gRPC. + // gRPC will crash if they are not lower-case. std::string key_lc = boost::algorithm::to_lower_copy(prop.first); call_options_.headers.emplace_back(std::make_pair(key_lc, prop.second)); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 844747178503d..e2344868dac86 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -57,6 +57,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { static const std::string PORT; static const std::string USER; static const std::string UID; + static const std::string USER_ID; static const std::string PASSWORD; static const std::string PWD; static const std::string TOKEN; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index e16b97150c67d..9f8ba4ca22155 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -137,5 +137,34 @@ TEST(PopulateCallOptionsTest, ConnectionTimeout) { connection.PopulateCallOptions(Connection::ConnPropertyMap()).timeout); } +TEST(PopulateCallOptionsTest, GenericOption) { + FlightSqlConnection connection(odbcabstraction::V_3); + connection.SetClosed(false); + + Connection::ConnPropertyMap properties; + properties["Foo"] = "Bar"; + auto options = connection.PopulateCallOptions(properties); + auto headers = options.headers; + ASSERT_EQ(1, headers.size()); + + // Header name must be lower-case because gRPC will crash if it is not lower-case. + ASSERT_EQ("foo", headers[0].first); + + // Header value should preserve case. + ASSERT_EQ("Bar", headers[0].second); +} + +TEST(PopulateCallOptionsTest, GenericOptionWithSpaces) { + FlightSqlConnection connection(odbcabstraction::V_3); + connection.SetClosed(false); + + Connection::ConnPropertyMap properties; + properties["Persist Security Info"] = "False"; + auto options = connection.PopulateCallOptions(properties); + auto headers = options.headers; + // Header names with spaces must be omitted or gRPC will crash. + ASSERT_TRUE(headers.empty()); +} + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc index 379cbe9486ccc..d716ee15e834d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc @@ -208,11 +208,11 @@ int DsnConfigurationWindow::CreateEncryptionSettingsGroup(int posX, int posY, in const char* val = config.Get(FlightSqlConnection::USE_ENCRYPTION).c_str(); - const bool enableEncrption = !boost::iequals(val, "false"); + const bool enableEncryption = !boost::iequals(val, "false"); labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Use Encryption:", ChildId::ENABLE_ENCRYPTION_LABEL)); enableEncryptionCheckBox = CreateCheckBox(editPosX, rowPos - 2, editSizeX, ROW_HEIGHT, "", - ChildId::ENABLE_ENCRYPTION_CHECKBOX, enableEncrption); + ChildId::ENABLE_ENCRYPTION_CHECKBOX, enableEncryption); rowPos += INTERVAL + ROW_HEIGHT; From 1da92ee7e7742f391bd486d615aad915d72502f5 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 7 Jun 2022 16:47:53 -0300 Subject: [PATCH 123/183] Add LICENSE and NOTICE files and ensure copyright headers are correct This ensures all files have copyright headers. Also includes a LICENSE and NOTICE file. Change-Id: Id894bc142b766e6560b6687f5e0fd34664ff4be2 --- .../flightsql-odbc/CMakeLists.txt | 16 +- .../flightsql-odbc/LICENSE | 201 ++++++++++++++++++ .../flightsql-odbc/NOTICE | 31 +++ .../flightsql-odbc/build_win32.bat | 5 + .../flightsql-odbc/build_win64.bat | 5 + .../flightsql-odbc/flight_sql/CMakeLists.txt | 16 +- .../accessors/binary_array_accessor.cc | 21 +- .../accessors/binary_array_accessor.h | 21 +- .../accessors/binary_array_accessor_test.cc | 21 +- .../accessors/boolean_array_accessor.cc | 21 +- .../accessors/boolean_array_accessor.h | 21 +- .../accessors/boolean_array_accessor_test.cc | 21 +- .../flight_sql/accessors/common.h | 21 +- .../accessors/date_array_accessor.cc | 21 +- .../accessors/date_array_accessor.h | 21 +- .../accessors/date_array_accessor_test.cc | 21 +- .../accessors/decimal_array_accessor.cc | 21 +- .../accessors/decimal_array_accessor.h | 21 +- .../accessors/decimal_array_accessor_test.cc | 21 +- .../flight_sql/accessors/main.h | 21 +- .../accessors/primitive_array_accessor.cc | 21 +- .../accessors/primitive_array_accessor.h | 21 +- .../primitive_array_accessor_test.cc | 21 +- .../accessors/string_array_accessor.cc | 21 +- .../accessors/string_array_accessor.h | 21 +- .../accessors/string_array_accessor_test.cc | 21 +- .../accessors/time_array_accessor.cc | 21 +- .../accessors/time_array_accessor.h | 21 +- .../accessors/time_array_accessor_test.cc | 21 +- .../accessors/timestamp_array_accessor.cc | 21 +- .../accessors/timestamp_array_accessor.h | 21 +- .../timestamp_array_accessor_test.cc | 21 +- .../flight_sql/accessors/types.h | 21 +- .../flight_sql/config/configuration.cc | 15 +- .../config/connection_string_parser.cc | 15 +- .../flight_sql/flight_sql_auth_method.cc | 21 +- .../flight_sql/flight_sql_auth_method.h | 21 +- .../flight_sql/flight_sql_connection.cc | 21 +- .../flight_sql/flight_sql_connection.h | 21 +- .../flight_sql/flight_sql_connection_test.cc | 21 +- .../flight_sql/flight_sql_driver.cc | 21 +- .../flight_sql_get_tables_reader.cc | 21 +- .../flight_sql/flight_sql_get_tables_reader.h | 21 +- .../flight_sql_get_type_info_reader.cc | 21 +- .../flight_sql_get_type_info_reader.h | 21 +- .../flight_sql/flight_sql_result_set.cc | 21 +- .../flight_sql/flight_sql_result_set.h | 21 +- .../flight_sql_result_set_accessors.cc | 21 +- .../flight_sql_result_set_accessors.h | 21 +- .../flight_sql_result_set_column.cc | 21 +- .../flight_sql/flight_sql_result_set_column.h | 21 +- .../flight_sql_result_set_metadata.cc | 21 +- .../flight_sql_result_set_metadata.h | 21 +- .../flight_sql/flight_sql_ssl_config.cc | 21 +- .../flight_sql/flight_sql_ssl_config.h | 21 +- .../flight_sql/flight_sql_statement.cc | 21 +- .../flight_sql/flight_sql_statement.h | 21 +- .../flight_sql_statement_get_columns.cc | 21 +- .../flight_sql_statement_get_columns.h | 21 +- .../flight_sql_statement_get_tables.cc | 21 +- .../flight_sql_statement_get_tables.h | 21 +- .../flight_sql_statement_get_type_info.cc | 21 +- .../flight_sql_statement_get_type_info.h | 21 +- .../flight_sql_stream_chunk_iterator.cc | 21 +- .../flight_sql_stream_chunk_iterator.h | 21 +- .../flight_sql/get_info_cache.cc | 21 +- .../flight_sql/get_info_cache.h | 21 +- .../include/flight_sql/config/configuration.h | 15 +- .../config/connection_string_parser.h | 15 +- .../include/flight_sql/flight_sql_driver.h | 21 +- .../flight_sql/ui/add_property_window.h | 15 +- .../include/flight_sql/ui/custom_window.h | 15 +- .../flight_sql/ui/dsn_configuration_window.h | 15 +- .../flight_sql/include/flight_sql/ui/window.h | 15 +- .../flight_sql/json_converter.cc | 21 +- .../flight_sql/json_converter.h | 21 +- .../flight_sql/json_converter_test.cc | 21 +- .../flightsql-odbc/flight_sql/main.cc | 21 +- .../flight_sql/parse_table_types_test.cc | 21 +- .../flight_sql/record_batch_transformer.cc | 21 +- .../flight_sql/record_batch_transformer.h | 21 +- .../record_batch_transformer_test.cc | 21 +- .../flight_sql/scalar_function_reporter.cc | 21 +- .../flight_sql/scalar_function_reporter.h | 21 +- .../flightsql-odbc/flight_sql/system_dsn.cc | 15 +- .../flight_sql/system_trust_store.cc | 21 +- .../flight_sql/system_trust_store.h | 21 +- .../flight_sql/ui/add_property_window.cc | 15 +- .../flight_sql/ui/custom_window.cc | 15 +- .../flight_sql/ui/dsn_configuration_window.cc | 15 +- .../flightsql-odbc/flight_sql/ui/window.cc | 15 +- .../flightsql-odbc/flight_sql/utils.cc | 21 +- .../flightsql-odbc/flight_sql/utils.h | 21 +- .../flightsql-odbc/flight_sql/utils_test.cc | 21 +- .../odbcabstraction/CMakeLists.txt | 16 +- .../odbcabstraction/calendar_utils.cc | 21 +- .../odbcabstraction/diagnostics.cc | 21 +- .../odbcabstraction/exceptions.cc | 21 +- .../include/odbcabstraction/calendar_utils.h | 21 +- .../include/odbcabstraction/diagnostics.h | 21 +- .../include/odbcabstraction/error_codes.h | 21 +- .../include/odbcabstraction/exceptions.h | 21 +- .../odbc_impl/AttributeUtils.h | 21 +- .../odbcabstraction/odbc_impl/EncodingUtils.h | 21 +- .../odbc_impl/ODBCConnection.h | 21 +- .../odbc_impl/ODBCDescriptor.h | 21 +- .../odbc_impl/ODBCEnvironment.h | 21 +- .../odbcabstraction/odbc_impl/ODBCHandle.h | 21 +- .../odbcabstraction/odbc_impl/ODBCStatement.h | 21 +- .../odbcabstraction/odbc_impl/TypeUtilities.h | 21 +- .../include/odbcabstraction/platform.h | 21 +- .../include/odbcabstraction/spi/connection.h | 21 +- .../include/odbcabstraction/spi/driver.h | 21 +- .../include/odbcabstraction/spi/result_set.h | 21 +- .../odbcabstraction/spi/result_set_metadata.h | 21 +- .../include/odbcabstraction/spi/statement.h | 21 +- .../include/odbcabstraction/types.h | 21 +- .../include/odbcabstraction/utils.h | 21 +- .../odbc_impl/ODBCConnection.cc | 21 +- .../odbc_impl/ODBCDescriptor.cc | 21 +- .../odbc_impl/ODBCEnvironment.cc | 21 +- .../odbc_impl/ODBCStatement.cc | 21 +- .../flightsql-odbc/odbcabstraction/utils.cc | 21 +- 123 files changed, 789 insertions(+), 1859 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/LICENSE create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/NOTICE diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index 19d60fdd2e3d2..94d1891a1e1d2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -1,19 +1,7 @@ -# 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 +# Copyright (C) 2020-2022 Dremio Corporation # -# http://www.apache.org/licenses/LICENSE-2.0 +# See "LICENSE" for license information. # -# 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.11) set(CMAKE_CXX_STANDARD 11) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/LICENSE b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/LICENSE new file mode 100644 index 0000000000000..aded4d6481da4 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (C) 2020-2022 - Dremio Corporation. + + Licensed 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. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/NOTICE b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/NOTICE new file mode 100644 index 0000000000000..7c5e65c71f250 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/NOTICE @@ -0,0 +1,31 @@ + Dremio +Copyright © 2020-2022 Dremio Corporation + +This software depends on external packages and source code. +The applicable license information is listed below. + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/) + +Licensed 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. + +---- + +This product includes software developed at +https://rapidjson.org/ + +Tencent is pleased to support the open source community by making RapidJSON available. + +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. + +If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. +If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license. +A copy of the MIT License is included in this file. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win32.bat b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win32.bat index 902eaeff4d874..c7a476d739a29 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win32.bat +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win32.bat @@ -1,3 +1,8 @@ +@rem +@rem Copyright (C) 2020-2022 Dremio Corporation +@rem +@rem See "LICENSE" for license information. +@rem @rem @rem Copyright 2015 the original author or authors. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win64.bat b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win64.bat index 29a0fe01f04f1..ef0d9cc0882ed 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win64.bat +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/build_win64.bat @@ -1,3 +1,8 @@ +@rem +@rem Copyright (C) 2020-2022 Dremio Corporation +@rem +@rem See "LICENSE" for license information. +@rem @rem @rem Copyright 2015 the original author or authors. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 9737be1463afe..584c9c95943e8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -1,19 +1,7 @@ -# 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 +# Copyright (C) 2020-2022 Dremio Corporation # -# http://www.apache.org/licenses/LICENSE-2.0 +# See "LICENSE" for license information. # -# 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.11) set(CMAKE_CXX_STANDARD 11) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc index 0e7180c769cb0..9d5985e261683 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "binary_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h index f678fa2a98fbb..9bbc5e53aa910 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc index b707c77322252..c1fafb4de2f07 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "arrow/testing/gtest_util.h" #include "arrow/testing/builder.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc index 264f2df54774e..534e8e2ffb16a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "boolean_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h index e79a5461a4404..9a7ef0a793b8f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc index 5b9e282c74dd5..bce7e4411547e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "arrow/testing/builder.h" #include "boolean_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h index ab7e33a83bd79..c1f1aa6d809c0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc index 2b6874b70c48d..30bbdde4180bf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "date_array_accessor.h" #include "time.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h index 6dd8240d85d04..764a6754a9558 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc index bacb993b09ad2..01a247e34e751 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "arrow/testing/builder.h" #include "boolean_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc index 4bd9f0954bf9a..79058df48e0c8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "decimal_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h index 6a2a26d9bfe4e..5cf787e88cb89 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc index 9b0f2cbf65acf..19bdccb62f36b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "arrow/util/decimal.h" #include "arrow/builder.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h index 14a49033278b3..0a606e195f3a5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/main.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc index 5cb90761e8b89..11a66aacf63be 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "primitive_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h index 777853f4bef0e..ccc530903d834 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc index e6270bddbfdc4..6ee4555dfbffd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "arrow/testing/builder.h" #include "primitive_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc index aba0e603f6114..6162ff84a5128 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "string_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h index 80e094bc61fe3..9cde63e3fe47e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc index 868215fd53707..d22547993e27a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "arrow/testing/builder.h" #include "string_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc index 05022d23454af..c9a3cd909026b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "time_array_accessor.h" #include "odbcabstraction/calendar_utils.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h index 652f148acc3a0..d9eb51c2e519d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc index b1b2c52f1912c..33a1bf6978bf2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "arrow/testing/builder.h" #include "time_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc index 082166af5e830..b05e836291d4a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "timestamp_array_accessor.h" #include "odbcabstraction/calendar_utils.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h index bc6df05bc13f6..2089260dfff24 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc index 95370a3e2a354..eff18a7e46ed1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "arrow/testing/builder.h" #include "timestamp_array_accessor.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h index f7fb60c3f4b79..cff8bebf50bc2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/configuration.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/configuration.cc index 4c876f125c1c2..e597d856cc2bc 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/configuration.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/configuration.cc @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #include "config/configuration.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/connection_string_parser.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/connection_string_parser.cc index a69e556991a88..5751728fd2234 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/connection_string_parser.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/config/connection_string_parser.cc @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #include "config/connection_string_parser.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index b9b63b614ee93..a87ec6524d0cf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_auth_method.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h index b07b3f4cea75d..db1899f472db6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 295e24320bd12..69241359c405b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_connection.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index e2344868dac86..83b7bbcc1eee4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 9f8ba4ca22155..cafc5a2b63a9c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_connection.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index c86f0e51688a0..d9f16949e243d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_connection.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc index 99d083c48d596..e6b01293e9ca9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_get_tables_reader.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.h index 1205fc1f34719..0e10c1e5ee39e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_tables_reader.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "record_batch_transformer.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.cc index f55e8f46a7ec3..6907c501a6f72 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_get_type_info_reader.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.h index 5742df1b96507..78729d763a34d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_get_type_info_reader.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "record_batch_transformer.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index ae7ab576cc22f..bac5fc2d78678 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_result_set.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index aeeefd78efee8..73c127e55b495 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index e8738968221b0..ef9b8384d9631 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "accessors/main.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h index ddc6017f9a8a1..d47e258f32a9f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index f0e913b38c877..2468d2252569a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_result_set_column.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h index 03b814fbaf9ba..be65238445bdc 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index b0fb8c0935705..6561589a479ae 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_result_set_metadata.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h index 9c74a22e48093..3349a0276b684 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.cc index 3c95b7790b9a8..08680fa3b37cf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_ssl_config.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.h index ca3bb38d4ce81..25cd788079877 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_ssl_config.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index 96a553f94bdc9..96ffd0c50a2d2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_statement.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h index 310a7ddfa7ff2..5cdf9dd670142 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc index 85bb9ee324443..56ce2868cfb91 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_statement_get_columns.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.h index bc46aaade5139..bc829af65467c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "record_batch_transformer.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc index fde43badb215b..d3bbb40159bed 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_statement_get_tables.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h index d31e416a08193..cdbdba104bb1f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc index c1231a5683761..b8b61bb779391 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_statement_get_type_info.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.h index 40137b58c0d97..1ada1bc22caa0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "record_batch_transformer.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc index c1924dc67ade1..e979f0ee6e821 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_stream_chunk_iterator.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.h index ba1c8b42cc5a3..00d00a03d0779 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc index 74343f0a71baa..fad79b0ec6a61 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "get_info_cache.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h index 8ee4a5c9ba193..96f490c80012a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/configuration.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/configuration.h index 2f9b02ec6139e..0deabd16fdd12 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/configuration.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/configuration.h @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/connection_string_parser.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/connection_string_parser.h index fa65cfb1743dd..ae32c508f76e7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/connection_string_parser.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/config/connection_string_parser.h @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h index f0ac600f2c03b..dec753970d7db 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/add_property_window.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/add_property_window.h index 1f77cee42e80b..49ee9fbd44d74 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/add_property_window.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/add_property_window.h @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/custom_window.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/custom_window.h index d0b5f46a7f797..9fdd3667c8cbb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/custom_window.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/custom_window.h @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/dsn_configuration_window.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/dsn_configuration_window.h index 3191b3aac83d0..62b4ce42af24c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/dsn_configuration_window.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/dsn_configuration_window.h @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/window.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/window.h index addb800d9e751..7c94e185364a3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/window.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/window.h @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc index 50e61c9e25d66..d2e68bfae95b7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "json_converter.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.h index 590785cefbc8d..9ef8747b9e460 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc index 74c743d69b259..40b88e8649244 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc @@ -1,19 +1,8 @@ -// 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 +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "json_converter.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 5a0ff8e095a3f..59c26ff3311ac 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/parse_table_types_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/parse_table_types_test.cc index e08c9df1da824..8f7fffd8581d1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/parse_table_types_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/parse_table_types_test.cc @@ -1,19 +1,8 @@ -// 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 +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "flight_sql_statement_get_tables.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc index 69d7087bb012c..5e52987539c1c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "record_batch_transformer.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.h index 70b5395f4aa7f..6f6385ebb338d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc index b1150c0fdff9c..821450fbca603 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/record_batch_transformer_test.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include #include "arrow/testing/builder.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.cc index 26e859e282a33..cb91103a992be 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "scalar_function_reporter.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.h index 9e31536188f4e..adc6768721a5c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/scalar_function_reporter.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_dsn.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_dsn.cc index 86b3ee419486f..209adfc807332 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_dsn.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_dsn.cc @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.cc index 8387a5897336c..8961c384e9362 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "system_trust_store.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.h index 8504806ee361e..872044d6341ae 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/system_trust_store.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/add_property_window.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/add_property_window.cc index 0fe9b789b47a2..e97af08381694 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/add_property_window.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/add_property_window.cc @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #include "ui/add_property_window.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/custom_window.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/custom_window.cc index 40f02b25f88c0..080ea042ff076 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/custom_window.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/custom_window.cc @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc index d716ee15e834d..f2807a1f5af66 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #include "ui/dsn_configuration_window.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc index b58fc0c851c54..34a723609f319 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc @@ -1,18 +1,7 @@ /* - * 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 + * Copyright (C) 2020-2022 Dremio Corporation * - * 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. + * See "LICENSE" for license information. */ #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 6a3062500c52e..986f0a7107bcc 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "utils.h" #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index 39b47bb1b6365..b0aead1d74670 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc index 1372ddf3366cc..10b9cf7d62dd8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include "utils.h" #include "arrow/testing/builder.h" diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index ef12e7d07ed0a..d53a7997d5867 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -1,19 +1,7 @@ -# 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 +# Copyright (C) 2020-2022 Dremio Corporation # -# http://www.apache.org/licenses/LICENSE-2.0 +# See "LICENSE" for license information. # -# 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. set(CMAKE_POSITION_INDEPENDENT_CODE ON) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc index 61cfadf1f5974..14ce702eb6fc6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/diagnostics.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/diagnostics.cc index 596f76f6441b4..1bbb426af2faf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/diagnostics.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/diagnostics.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc index 9f79706ca58f8..c0128188d8909 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h index ef82d884078f9..381d432ceab4f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/diagnostics.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/diagnostics.h index 001e64be4e455..08513e9ca0534 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/diagnostics.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/diagnostics.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/error_codes.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/error_codes.h index 7931a07457474..7624c225c24f7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/error_codes.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/error_codes.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h index c1f17c805cae9..41a4051be9a49 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/AttributeUtils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/AttributeUtils.h index e53d9c8b7d304..d77044e32029c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/AttributeUtils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/AttributeUtils.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h index 68d5815df2bd6..6c68f92e65161 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCConnection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCConnection.h index 08ca1790832a9..6187418bf271f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCConnection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCConnection.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h index 7bea11aa8569f..b29cec75c64b2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCEnvironment.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCEnvironment.h index a10b1d5feb9e6..3404b086b56db 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCEnvironment.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCEnvironment.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCHandle.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCHandle.h index c97c3e54d6514..b9653b54c1888 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCHandle.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCHandle.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h index 9c1933320656b..f2e9570ef761a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/TypeUtilities.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/TypeUtilities.h index 1fd44643cfe8d..101968dd1b22d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/TypeUtilities.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/TypeUtilities.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h index d479dd7f3371e..52affed1e4928 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/connection.h index ac219292828d1..4c1c4bb2323a0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/connection.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h index 82f31a8c92b72..2a324a382807b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h index 239bf88ee72b9..59e47fca50508 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set_metadata.h index fdb104247d58c..de8feaade3fbe 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set_metadata.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set_metadata.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/statement.h index 7b557ec065d6e..0d5776a824c71 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/statement.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 21db5de23e7a1..112f12d4fb1bf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h index 537b68973aaee..a9d030df8693f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #pragma once diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc index 9c1157b2fba5a..8b6f3f0139f2f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc index adf9d05cc474e..c0bcead4ce1ed 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCEnvironment.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCEnvironment.cc index c5709c97b6c05..3bafc9ddf4bcd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCEnvironment.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCEnvironment.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc index 7b5cafc5dc650..b92babe3ac313 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc index aea9fd3b04667..9bd9e55b1285c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc @@ -1,19 +1,8 @@ -// 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. +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ #include From a64449400bfb71c5b17aabc489ce0753edafaac6 Mon Sep 17 00:00:00 2001 From: "joy.cundy" Date: Fri, 10 Jun 2022 20:00:37 +0000 Subject: [PATCH 124/183] Fix Config Dialog Advanced Properties not saving correct value Change-Id: I7a9dcfc7b844ccb38de6e3b36ab00ef698c90330 --- .../flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc index 34a723609f319..1aeccacd7d63b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/window.cc @@ -278,7 +278,7 @@ std::vector > Window::ListGetAll() for (int i = 0; i < numItems; ++i) { std::vector row; for (int j = 0; j < numColumns; ++j) { - ListView_GetItemText(handle, j, i, buf, BUF_LEN); + ListView_GetItemText(handle, i, j, buf, BUF_LEN); row.emplace_back(buf); } values.push_back(row); From d3eead5e080b9391ba000ebd8f95b17bea94d376 Mon Sep 17 00:00:00 2001 From: James Duong Date: Sat, 11 Jun 2022 17:30:13 -0700 Subject: [PATCH 125/183] Fix crash when using SQLDisconnect after SQLExecute Fix a crash if the driver disconnects from Arrow while it has open executed prepared statements. This happens when using SQLPrepare, SQLExecute, SQLDisconnect, then deallocating handles and the connection. It does not happen when replacing SQLPrepare and SQLExecute with SQLExecDirect. Ensure that the driver de-allocates SPI resources in the opposite of the order it allocates them in. Change-Id: I3071133869d5f851e282597e74dea9bf533d93f2 --- .../odbcabstraction/odbc_impl/ODBCConnection.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc index 8b6f3f0139f2f..6dca30288b9dd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc @@ -606,6 +606,10 @@ void ODBCConnection::GetConnectAttr(SQLINTEGER attribute, SQLPOINTER value, void ODBCConnection::disconnect() { if (m_isConnected) { + // Ensure that all statements (and corresponding SPI statements) get cleaned + // up before terminating the SPI connection in case they need to be de-allocated in + // the reverse of the allocation order. + m_statements.clear(); m_spiConnection->Close(); m_isConnected = false; } From e4731fe41e8c694c4c539c15e9588552d8d34e6e Mon Sep 17 00:00:00 2001 From: James Duong Date: Sun, 12 Jun 2022 15:19:17 +0000 Subject: [PATCH 126/183] Add test button to config dialog - Adds a test button to the dialog. This connects and reports the server name and server version. - Fix bug where many GetInfo properties retrieved from the server weren't being reported due to incorrect caching. - Fix a bug where when a boolean property is set to 0 in the DSN, it is incorrectly assumed to be true in the configuration dialog. Made the reading of these settings in the dialog consistent with the rest of the connection process. Change-Id: I00866343890e9b5939bd97c8fce4b2280e2e6ef1 --- .../flight_sql/flight_sql_connection.cc | 2 +- .../flight_sql/get_info_cache.cc | 2 +- .../flight_sql/ui/dsn_configuration_window.h | 6 +- .../flight_sql/ui/dsn_configuration_window.cc | 75 ++++++++++++++----- 4 files changed, 64 insertions(+), 21 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 69241359c405b..9b3afd6f97fe9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -321,7 +321,7 @@ FlightSqlConnection::GetAttribute(Connection::AttributeId attribute) { Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { auto result = info_.GetInfo(info_type); - if (info_type == SQL_DBMS_NAME) { + if (info_type == SQL_DBMS_NAME || info_type == SQL_SERVER_NAME) { // Update the database component reported in error messages. // We do this lazily for performance reasons. diagnostics_.SetDataSourceComponent(boost::get(result)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc index fad79b0ec6a61..0c457176d5090 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc @@ -262,7 +262,7 @@ Connection::Info GetInfoCache::GetInfo(uint16_t info_type) { } bool GetInfoCache::LoadInfoFromServer() { - if (has_server_info_.exchange(true)) { + if (sql_client_ && !has_server_info_.exchange(true)) { std::unique_lock lock(mutex_); arrow::Result> result = sql_client_->GetSqlInfo(call_options_, {}); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/dsn_configuration_window.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/dsn_configuration_window.h index 62b4ce42af24c..e9c2f23b425f4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/dsn_configuration_window.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/ui/dsn_configuration_window.h @@ -55,6 +55,7 @@ class DsnConfigurationWindow : public CustomWindow ADD_BUTTON, DELETE_BUTTON, TAB_CONTROL, + TEST_CONNECTION_BUTTON, OK_BUTTON, CANCEL_BUTTON }; @@ -135,7 +136,7 @@ class DsnConfigurationWindow : public CustomWindow void CheckAuthType(); - void SaveParameters(); + void SaveParameters(Configuration& targetConfig); /** Window width. */ int width; @@ -160,6 +161,9 @@ class DsnConfigurationWindow : public CustomWindow std::vector > labels; + /** Test button. */ + std::unique_ptr testButton; + /** Ok button. */ std::unique_ptr okButton; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc index f2807a1f5af66..817409c1dcef1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc @@ -12,12 +12,31 @@ #include #include #include +#include +#include #include "ui/add_property_window.h" #define COMMON_TAB 0 #define ADVANCED_TAB 1 +namespace { + std::string TestConnection(const driver::flight_sql::config::Configuration& config) { + std::unique_ptr flightSqlConn( + new driver::flight_sql::FlightSqlConnection(driver::odbcabstraction::V_3)); + + std::vector missingProperties; + flightSqlConn->Connect(config.GetProperties(), missingProperties); + + // This should have been checked before enabling the Test button. + assert(missingProperties.empty()); + std::string serverName = boost::get(flightSqlConn->GetInfo(SQL_SERVER_NAME)); + std::string serverVersion = boost::get(flightSqlConn->GetInfo(SQL_DBMS_VER)); + return "Server Name: " + serverName + "\n" + + "Server Version: " + serverVersion; + } +} + namespace driver { namespace flight_sql { namespace config { @@ -79,10 +98,12 @@ void DsnConfigurationWindow::OnCreate() advancedGroupPosY += INTERVAL + CreateEncryptionSettingsGroup(MARGIN, advancedGroupPosY, groupSizeY); advancedGroupPosY += INTERVAL + CreatePropertiesGroup(MARGIN, advancedGroupPosY, groupSizeY); + int testPosX = MARGIN; int cancelPosX = width - MARGIN - BUTTON_WIDTH; int okPosX = cancelPosX - INTERVAL - BUTTON_WIDTH; int buttonPosY = std::max(commonGroupPosY, advancedGroupPosY); + testButton = CreateButton(testPosX, buttonPosY, BUTTON_WIDTH + 20, BUTTON_HEIGHT, "Test Connection", ChildId::TEST_CONNECTION_BUTTON); okButton = CreateButton(okPosX, buttonPosY, BUTTON_WIDTH, BUTTON_HEIGHT, "Ok", ChildId::OK_BUTTON); cancelButton = CreateButton(cancelPosX, buttonPosY, BUTTON_WIDTH, BUTTON_HEIGHT, "Cancel", ChildId::CANCEL_BUTTON); @@ -197,7 +218,7 @@ int DsnConfigurationWindow::CreateEncryptionSettingsGroup(int posX, int posY, in const char* val = config.Get(FlightSqlConnection::USE_ENCRYPTION).c_str(); - const bool enableEncryption = !boost::iequals(val, "false"); + const bool enableEncryption = driver::odbcabstraction::AsBool(val, true); labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Use Encryption:", ChildId::ENABLE_ENCRYPTION_LABEL)); enableEncryptionCheckBox = CreateCheckBox(editPosX, rowPos - 2, editSizeX, ROW_HEIGHT, "", @@ -216,7 +237,7 @@ int DsnConfigurationWindow::CreateEncryptionSettingsGroup(int posX, int posY, in val = config.Get(FlightSqlConnection::USE_SYSTEM_TRUST_STORE).c_str(); - const bool useSystemCertStore = !boost::iequals(val, "false"); + const bool useSystemCertStore = driver::odbcabstraction::AsBool(val, true); labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, 2 * ROW_HEIGHT, "Use System Certificate Store:", ChildId::USE_SYSTEM_CERT_STORE_LABEL)); useSystemCertStoreCheckBox = CreateCheckBox(editPosX, rowPos - 2, 20, 2 * ROW_HEIGHT, "", @@ -227,7 +248,7 @@ int DsnConfigurationWindow::CreateEncryptionSettingsGroup(int posX, int posY, in const int rightPosX = labelPosX + (sizeX - (2 * INTERVAL)) / 2; const int rightCheckPosX = rightPosX + (editPosX - labelPosX); - const bool disableCertVerification = !boost::iequals(val, "false"); + const bool disableCertVerification = driver::odbcabstraction::AsBool(val, false); labels.push_back(CreateLabel(rightPosX, rowPos, LABEL_WIDTH, 2 * ROW_HEIGHT, "Disable Certificate Verification:", ChildId::DISABLE_CERT_VERIFICATION_LABEL)); disableCertVerificationCheckBox = CreateCheckBox(rightCheckPosX, rowPos - 2, 20, 2 * ROW_HEIGHT, "", @@ -330,18 +351,19 @@ void DsnConfigurationWindow::CheckEnableOk() { enableOk = enableOk && !passwordEdit->IsTextEmpty(); } + testButton->SetEnabled(enableOk); okButton->SetEnabled(enableOk); } -void DsnConfigurationWindow::SaveParameters() +void DsnConfigurationWindow::SaveParameters(Configuration& targetConfig) { - config.Clear(); + targetConfig.Clear(); std::string text; nameEdit->GetText(text); - config.Set(FlightSqlConnection::DSN, text); + targetConfig.Set(FlightSqlConnection::DSN, text); serverEdit->GetText(text); - config.Set(FlightSqlConnection::HOST, text); + targetConfig.Set(FlightSqlConnection::HOST, text); portEdit->GetText(text); try { const int portInt = std::stoi(text); @@ -349,7 +371,7 @@ void DsnConfigurationWindow::SaveParameters() { throw odbcabstraction::DriverException("Invalid port value."); } - config.Set(FlightSqlConnection::PORT, text); + targetConfig.Set(FlightSqlConnection::PORT, text); } catch (odbcabstraction::DriverException&) { throw; @@ -361,33 +383,33 @@ void DsnConfigurationWindow::SaveParameters() if (0 == authTypeComboBox->GetSelection()) { userEdit->GetText(text); - config.Set(FlightSqlConnection::UID, text); + targetConfig.Set(FlightSqlConnection::UID, text); passwordEdit->GetText(text); - config.Set(FlightSqlConnection::PWD, text); + targetConfig.Set(FlightSqlConnection::PWD, text); } else { authTokenEdit->GetText(text); - config.Set(FlightSqlConnection::TOKEN, text); + targetConfig.Set(FlightSqlConnection::TOKEN, text); } if (enableEncryptionCheckBox->IsChecked()) { - config.Set(FlightSqlConnection::USE_ENCRYPTION, TRUE_STR); + targetConfig.Set(FlightSqlConnection::USE_ENCRYPTION, TRUE_STR); certificateEdit->GetText(text); - config.Set(FlightSqlConnection::TRUSTED_CERTS, text); - config.Set(FlightSqlConnection::USE_SYSTEM_TRUST_STORE, useSystemCertStoreCheckBox->IsChecked() ? TRUE_STR : FALSE_STR); - config.Set(FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, disableCertVerificationCheckBox->IsChecked() ? TRUE_STR : FALSE_STR); + targetConfig.Set(FlightSqlConnection::TRUSTED_CERTS, text); + targetConfig.Set(FlightSqlConnection::USE_SYSTEM_TRUST_STORE, useSystemCertStoreCheckBox->IsChecked() ? TRUE_STR : FALSE_STR); + targetConfig.Set(FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, disableCertVerificationCheckBox->IsChecked() ? TRUE_STR : FALSE_STR); } else { - config.Set(FlightSqlConnection::USE_ENCRYPTION, FALSE_STR); + targetConfig.Set(FlightSqlConnection::USE_ENCRYPTION, FALSE_STR); } // Get all the list properties. const auto properties = propertyList->ListGetAll(); for (const auto& property : properties) { - config.Set(property[0], property[1]); + targetConfig.Set(property[0], property[1]); } } @@ -425,11 +447,28 @@ bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM wParam, LPARAM lParam) { switch (LOWORD(wParam)) { + case ChildId::TEST_CONNECTION_BUTTON: + { + try + { + Configuration testConfig; + SaveParameters(testConfig); + std::string testMessage = TestConnection(testConfig); + + MessageBox(NULL, testMessage.c_str(), "Test Connection Success", MB_OK); + } + catch (odbcabstraction::DriverException& err) + { + MessageBox(NULL, err.GetMessageText().c_str(), "Error!", MB_ICONEXCLAMATION | MB_OK); + } + + break; + } case ChildId::OK_BUTTON: { try { - SaveParameters(); + SaveParameters(config); accepted = true; PostMessage(GetHandle(), WM_CLOSE, 0, 0); } From f2f0a3c1f5a7073d7cb3340656f49d40b14a07c8 Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 13 Jun 2022 16:21:00 -0700 Subject: [PATCH 127/183] SQLGetInfo fixes - Fix missing get info types. - Fix incorrect types causing boost::get errors. - Add defaults when the server fails to report types in GetSqlInfo. - Fix crashes/incorrect metadata due to incorrectly accessing values within the dense union for many types. Change-Id: Ic4f371ec80ecdbc87d08b5ab88f3adba0921b735 --- .../flight_sql/get_info_cache.cc | 463 ++++++++++++++---- .../flight_sql/get_info_cache.h | 5 +- .../odbc_impl/ODBCConnection.cc | 63 ++- 3 files changed, 406 insertions(+), 125 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc index 0c457176d5090..1e4ae1ff73161 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc @@ -128,7 +128,7 @@ uint32_t GetCvtBitForArrowConvertEntry(int32_t convert_entry) { case ARROW_CONVERT_BIT: return SQL_CVT_BIT; case ARROW_CONVERT_CHAR: - return SQL_CVT_CHAR; + return SQL_CVT_CHAR | SQL_CVT_WCHAR; case ARROW_CONVERT_DATE: return SQL_CVT_DATE; case ARROW_CONVERT_DECIMAL: @@ -144,7 +144,7 @@ uint32_t GetCvtBitForArrowConvertEntry(int32_t convert_entry) { case ARROW_CONVERT_LONGVARBINARY: return SQL_CVT_LONGVARBINARY; case ARROW_CONVERT_LONGVARCHAR: - return SQL_CVT_LONGVARCHAR; + return SQL_CVT_LONGVARCHAR | SQL_CVT_WLONGVARCHAR; case ARROW_CONVERT_NUMERIC: return SQL_CVT_NUMERIC; case ARROW_CONVERT_REAL: @@ -160,22 +160,29 @@ uint32_t GetCvtBitForArrowConvertEntry(int32_t convert_entry) { case ARROW_CONVERT_VARBINARY: return SQL_CVT_VARBINARY; case ARROW_CONVERT_VARCHAR: - return SQL_CVT_VARCHAR; + return SQL_CVT_VARCHAR | SQL_CVT_WLONGVARCHAR; } + // Note: GUID not supported by GetSqlInfo. // Return zero, which has no bits set. return 0; } inline int32_t ScalarToInt32(arrow::UnionScalar *scalar) { - return reinterpret_cast(scalar)->value; + return reinterpret_cast(scalar->value.get())->value; } inline int64_t ScalarToInt64(arrow::UnionScalar *scalar) { - return reinterpret_cast(scalar)->value; + return reinterpret_cast(scalar->value.get())->value; } inline std::string ScalarToBoolString(arrow::UnionScalar *scalar) { - return reinterpret_cast(scalar)->value ? "Y" : "N"; + return reinterpret_cast(scalar->value.get())->value ? "Y" : "N"; +} + +inline void SetDefaultIfMissing(std::unordered_map& cache, + uint16_t info_type, driver::odbcabstraction::Connection::Info default_value) { + // Note: emplace() only writes if the key isn't found. + cache.emplace(info_type, std::move(default_value)); } } // namespace @@ -191,7 +198,7 @@ GetInfoCache::GetInfoCache(FlightCallOptions &call_options, : call_options_(call_options), sql_client_(client), has_server_info_(false) { info_[SQL_DRIVER_NAME] = "Arrow Flight ODBC Driver"; - info_[SQL_DRIVER_VER] = "1.0.0"; + info_[SQL_DRIVER_VER] = "01.00.0000"; // This should be generated dynamically. info_[SQL_GETDATA_EXTENSIONS] = static_cast(SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER); @@ -201,7 +208,9 @@ GetInfoCache::GetInfoCache(FlightCallOptions &call_options, // should. info_[SQL_ACCESSIBLE_PROCEDURES] = "N"; info_[SQL_COLLATION_SEQ] = ""; + info_[SQL_ALTER_DOMAIN] = static_cast(0); info_[SQL_ALTER_TABLE] = static_cast(0); + info_[SQL_COLUMN_ALIAS] = "Y"; info_[SQL_DATETIME_LITERALS] = static_cast( SQL_DL_SQL92_DATE | SQL_DL_SQL92_TIME | SQL_DL_SQL92_TIMESTAMP); info_[SQL_CREATE_ASSERTION] = static_cast(0); @@ -225,6 +234,8 @@ GetInfoCache::GetInfoCache(FlightCallOptions &call_options, info_[SQL_DROP_CHARACTER_SET] = static_cast(0); info_[SQL_DROP_COLLATION] = static_cast(0); info_[SQL_DROP_DOMAIN] = static_cast(0); + info_[SQL_DROP_SCHEMA] = static_cast(0); + info_[SQL_DROP_TABLE] = static_cast(0); info_[SQL_DROP_TRANSLATION] = static_cast(0); info_[SQL_DROP_VIEW] = static_cast(0); info_[SQL_MAX_IDENTIFIER_LEN] = static_cast(65535); // arbitrary @@ -239,6 +250,7 @@ GetInfoCache::GetInfoCache(FlightCallOptions &call_options, info_[SQL_CATALOG_TERM] = ""; info_[SQL_CATALOG_NAME] = "N"; info_[SQL_CATALOG_NAME_SEPARATOR] = ""; + info_[SQL_CATALOG_LOCATION] = static_cast(0); } void GetInfoCache::SetProperty( @@ -345,9 +357,11 @@ bool GetInfoCache::LoadInfoFromServer() { if (catalog_term.empty()) { info_[SQL_CATALOG_NAME] = "N"; info_[SQL_CATALOG_NAME_SEPARATOR] = ""; + info_[SQL_CATALOG_LOCATION] = static_cast(0); } else { info_[SQL_CATALOG_NAME] = "Y"; info_[SQL_CATALOG_NAME_SEPARATOR] = "."; + info_[SQL_CATALOG_LOCATION] = static_cast(SQL_CL_START); } info_[SQL_CATALOG_TERM] = std::string(reinterpret_cast(scalar->value.get())->view()); @@ -370,7 +384,7 @@ bool GetInfoCache::LoadInfoFromServer() { break; case SqlInfoOptions::SQL_DDL_SCHEMA: { bool supports_schema_ddl = - reinterpret_cast(scalar)->value; + reinterpret_cast(scalar->value.get())->value; // Note: this is a bitmask and we can't describe cascade or restrict // flags. info_[SQL_DROP_SCHEMA] = static_cast(SQL_DS_DROP_SCHEMA); @@ -383,7 +397,7 @@ bool GetInfoCache::LoadInfoFromServer() { } case SqlInfoOptions::SQL_DDL_TABLE: { bool supports_table_ddl = - reinterpret_cast(scalar)->value; + reinterpret_cast(scalar->value.get())->value; // This is a bitmask and we cannot describe all clauses. info_[SQL_CREATE_TABLE] = static_cast(SQL_CT_CREATE_TABLE); @@ -400,7 +414,7 @@ bool GetInfoCache::LoadInfoFromServer() { } case SqlInfoOptions::SQL_NULL_PLUS_NULL_IS_NULL: { info_[SQL_CONCAT_NULL_BEHAVIOR] = static_cast( - reinterpret_cast(scalar)->value + reinterpret_cast(scalar->value.get())->value ? SQL_CB_NULL : SQL_CB_NON_NULL); break; @@ -410,7 +424,7 @@ bool GetInfoCache::LoadInfoFromServer() { // SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES since we need both // properties to determine the value for SQL_CORRELATION_NAME. supports_correlation_name = - reinterpret_cast(scalar)->value; + reinterpret_cast(scalar->value.get())->value; break; } case SqlInfoOptions::SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES: { @@ -418,7 +432,7 @@ bool GetInfoCache::LoadInfoFromServer() { // SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES since we need both // properties to determine the value for SQL_CORRELATION_NAME. requires_different_correlation_name = - reinterpret_cast(scalar)->value; + reinterpret_cast(scalar->value.get())->value; break; } case SqlInfoOptions::SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY: { @@ -428,7 +442,7 @@ bool GetInfoCache::LoadInfoFromServer() { case SqlInfoOptions::SQL_SUPPORTS_ORDER_BY_UNRELATED: { // Note: this is the negation of the Flight SQL property. info_[SQL_ORDER_BY_COLUMNS_IN_SELECT] = - reinterpret_cast(scalar)->value ? "N" + reinterpret_cast(scalar->value.get())->value ? "N" : "Y"; break; } @@ -438,7 +452,7 @@ bool GetInfoCache::LoadInfoFromServer() { } case SqlInfoOptions::SQL_SUPPORTS_NON_NULLABLE_COLUMNS: { info_[SQL_NON_NULLABLE_COLUMNS] = static_cast( - reinterpret_cast(scalar)->value + reinterpret_cast(scalar->value.get())->value ? SQL_NNC_NON_NULL : SQL_NNC_NULL); break; @@ -449,7 +463,7 @@ bool GetInfoCache::LoadInfoFromServer() { } case SqlInfoOptions::SQL_CATALOG_AT_START: { info_[SQL_CATALOG_LOCATION] = static_cast( - reinterpret_cast(scalar)->value + reinterpret_cast(scalar->value.get())->value ? SQL_CL_START : SQL_CL_END); break; @@ -467,22 +481,22 @@ bool GetInfoCache::LoadInfoFromServer() { } case SqlInfoOptions::SQL_TRANSACTIONS_SUPPORTED: { transactions_supported = - reinterpret_cast(scalar)->value; + reinterpret_cast(scalar->value.get())->value; break; } case SqlInfoOptions::SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT: { transaction_ddl_commit = - reinterpret_cast(scalar)->value; + reinterpret_cast(scalar->value.get())->value; break; } case SqlInfoOptions::SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED: { transaction_ddl_ignore = - reinterpret_cast(scalar)->value; + reinterpret_cast(scalar->value.get())->value; break; } case SqlInfoOptions::SQL_BATCH_UPDATES_SUPPORTED: { info_[SQL_BATCH_SUPPORT] = static_cast( - reinterpret_cast(scalar)->value + reinterpret_cast(scalar->value.get())->value ? SQL_BS_ROW_COUNT_EXPLICIT : 0); break; @@ -636,7 +650,7 @@ bool GetInfoCache::LoadInfoFromServer() { break; } case SqlInfoOptions::SQL_MAX_PROCEDURE_NAME_LENGTH: { - info_[SQL_MAX_SCHEMA_NAME_LEN] = + info_[SQL_MAX_PROCEDURE_NAME_LEN] = static_cast(ScalarToInt64(scalar)); break; } @@ -682,17 +696,17 @@ bool GetInfoCache::LoadInfoFromServer() { constexpr int32_t REPEATABLE_READ = 3; constexpr int32_t SERIALIZABLE = 4; int64_t scalar_value = static_cast(ScalarToInt64(scalar)); - uint32_t result = 0; + uint32_t result_val = 0; if ((scalar_value & (1 << READ_UNCOMMITTED)) != 0) { - result = SQL_TXN_READ_UNCOMMITTED; + result_val = SQL_TXN_READ_UNCOMMITTED; } else if ((scalar_value & (1 << READ_COMMITTED)) != 0) { - result = SQL_TXN_READ_COMMITTED; + result_val = SQL_TXN_READ_COMMITTED; } else if ((scalar_value & (1 << REPEATABLE_READ)) != 0) { - result = SQL_TXN_REPEATABLE_READ; + result_val = SQL_TXN_REPEATABLE_READ; } else if ((scalar_value & (1 << SERIALIZABLE)) != 0) { - result = SQL_TXN_SERIALIZABLE; + result_val = SQL_TXN_SERIALIZABLE; } - info_[SQL_DEFAULT_TXN_ISOLATION] = result; + info_[SQL_DEFAULT_TXN_ISOLATION] = result_val; break; } @@ -702,14 +716,14 @@ bool GetInfoCache::LoadInfoFromServer() { constexpr int32_t UNRELATED = 0; constexpr int32_t BEYOND_SELECT = 1; int32_t scalar_value = static_cast(ScalarToInt32(scalar)); - uint16_t result = SQL_GB_NOT_SUPPORTED; + uint16_t result_val = SQL_GB_NOT_SUPPORTED; if ((scalar_value & (1 << UNRELATED)) != 0) { - result = SQL_GB_NO_RELATION; + result_val = SQL_GB_NO_RELATION; } else if ((scalar_value & (1 << BEYOND_SELECT)) != 0) { - result = SQL_GB_GROUP_BY_CONTAINS_SELECT; + result_val = SQL_GB_GROUP_BY_CONTAINS_SELECT; } // Note GROUP_BY_EQUALS_SELECT and COLLATE cannot be described. - info_[SQL_GROUP_BY] = result; + info_[SQL_GROUP_BY] = result_val; break; } case SqlInfoOptions::SQL_SUPPORTED_GRAMMAR: { @@ -719,15 +733,15 @@ bool GetInfoCache::LoadInfoFromServer() { constexpr int32_t CORE = 1; constexpr int32_t EXTENDED = 2; int32_t scalar_value = static_cast(ScalarToInt32(scalar)); - uint32_t result = SQL_OIC_CORE; + uint32_t result_val = SQL_OIC_CORE; if ((scalar_value & (1 << MINIMUM)) != 0) { - result = SQL_OIC_CORE; + result_val = SQL_OIC_CORE; } else if ((scalar_value & (1 << CORE)) != 0) { - result = SQL_OIC_LEVEL1; + result_val = SQL_OIC_LEVEL1; } else if ((scalar_value & (1 << EXTENDED)) != 0) { - result = SQL_OIC_LEVEL2; + result_val = SQL_OIC_LEVEL2; } - info_[SQL_ODBC_API_CONFORMANCE] = result; + info_[SQL_ODBC_API_CONFORMANCE] = result_val; break; } case SqlInfoOptions::SQL_ANSI92_SUPPORTED_LEVEL: { @@ -737,18 +751,18 @@ bool GetInfoCache::LoadInfoFromServer() { constexpr int32_t INTERMEDIATE = 1; constexpr int32_t FULL = 2; int32_t scalar_value = static_cast(ScalarToInt32(scalar)); - uint32_t result = SQL_SC_SQL92_ENTRY; + uint32_t result_val = SQL_SC_SQL92_ENTRY; uint16_t odbc_sql_conformance = SQL_OSC_MINIMUM; if ((scalar_value & (1 << ENTRY)) != 0) { - result = SQL_SC_SQL92_ENTRY; + result_val = SQL_SC_SQL92_ENTRY; } else if ((scalar_value & (1 << INTERMEDIATE)) != 0) { - result = SQL_SC_SQL92_INTERMEDIATE; + result_val = SQL_SC_SQL92_INTERMEDIATE; odbc_sql_conformance = SQL_OSC_CORE; } else if ((scalar_value & (1 << FULL)) != 0) { - result = SQL_SC_SQL92_FULL; + result_val = SQL_SC_SQL92_FULL; odbc_sql_conformance = SQL_OSC_EXTENDED; } - info_[SQL_SQL_CONFORMANCE] = result; + info_[SQL_SQL_CONFORMANCE] = result_val; info_[SQL_ODBC_SQL_CONFORMANCE] = odbc_sql_conformance; break; } @@ -762,23 +776,23 @@ bool GetInfoCache::LoadInfoFromServer() { constexpr int32_t UNSUPPORTED = 0; constexpr int32_t LIMITED = 1; constexpr int32_t FULL = 2; - uint32_t result = 0; + uint32_t result_val = 0; // Assume inner and cross joins are supported. Flight SQL can't // report this currently. uint32_t relational_operators = SQL_SRJO_CROSS_JOIN | SQL_SRJO_INNER_JOIN; if ((scalar_value & (1 << FULL)) != 0) { - result = SQL_OJ_LEFT | SQL_OJ_RIGHT | SQL_OJ_FULL | SQL_OJ_NESTED; + result_val = SQL_OJ_LEFT | SQL_OJ_RIGHT | SQL_OJ_FULL | SQL_OJ_NESTED; relational_operators |= SQL_SRJO_FULL_OUTER_JOIN | SQL_SRJO_LEFT_OUTER_JOIN | SQL_SRJO_RIGHT_OUTER_JOIN; } else if ((scalar_value & (1 << LIMITED)) != 0) { - result = SQL_SC_SQL92_INTERMEDIATE; + result_val = SQL_SC_SQL92_INTERMEDIATE; } else if ((scalar_value & (1 << UNSUPPORTED)) != 0) { - result = 0; + result_val = 0; } - info_[SQL_OJ_CAPABILITIES] = result; - info_[SQL_OUTER_JOINS] = result != 0 ? "Y" : "N"; + info_[SQL_OJ_CAPABILITIES] = result_val; + info_[SQL_OUTER_JOINS] = result_val != 0 ? "Y" : "N"; info_[SQL_SQL92_RELATIONAL_JOIN_OPERATORS] = relational_operators; break; } @@ -791,17 +805,17 @@ bool GetInfoCache::LoadInfoFromServer() { constexpr int32_t INDEX = 1; constexpr int32_t PRIVILEGE = 2; // Assume schemas are supported in DML and Table manipulation. - uint32_t result = SQL_SU_DML_STATEMENTS | SQL_SU_TABLE_DEFINITION; + uint32_t result_val = SQL_SU_DML_STATEMENTS | SQL_SU_TABLE_DEFINITION; if ((scalar_value & (1 << PROCEDURE)) != 0) { - result |= SQL_SU_PROCEDURE_INVOCATION; + result_val |= SQL_SU_PROCEDURE_INVOCATION; } if ((scalar_value & (1 << INDEX)) != 0) { - result |= SQL_SU_INDEX_DEFINITION; + result_val |= SQL_SU_INDEX_DEFINITION; } if ((scalar_value & (1 << PRIVILEGE)) != 0) { - result |= SQL_SU_PRIVILEGE_DEFINITION; + result_val |= SQL_SU_PRIVILEGE_DEFINITION; } - info_[SQL_SCHEMA_USAGE] = result; + info_[SQL_SCHEMA_USAGE] = result_val; break; } case SqlInfoOptions::SQL_CATALOGS_SUPPORTED_ACTIONS: { @@ -813,17 +827,17 @@ bool GetInfoCache::LoadInfoFromServer() { constexpr int32_t INDEX = 1; constexpr int32_t PRIVILEGE = 2; // Assume catalogs are supported in DML and Table manipulation. - uint32_t result = SQL_CU_DML_STATEMENTS | SQL_CU_TABLE_DEFINITION; + uint32_t result_val = SQL_CU_DML_STATEMENTS | SQL_CU_TABLE_DEFINITION; if ((scalar_value & (1 << PROCEDURE)) != 0) { - result |= SQL_CU_PROCEDURE_INVOCATION; + result_val |= SQL_CU_PROCEDURE_INVOCATION; } if ((scalar_value & (1 << INDEX)) != 0) { - result |= SQL_CU_INDEX_DEFINITION; + result_val |= SQL_CU_INDEX_DEFINITION; } if ((scalar_value & (1 << PRIVILEGE)) != 0) { - result |= SQL_CU_PRIVILEGE_DEFINITION; + result_val |= SQL_CU_PRIVILEGE_DEFINITION; } - info_[SQL_CATALOG_USAGE] = result; + info_[SQL_CATALOG_USAGE] = result_val; break; } case SqlInfoOptions::SQL_SUPPORTED_POSITIONED_COMMANDS: { @@ -839,20 +853,20 @@ bool GetInfoCache::LoadInfoFromServer() { constexpr int32_t EXISTS = 1; constexpr int32_t INN = 2; constexpr int32_t QUANTIFIEDS = 3; - uint32_t result = 0; + uint32_t result_val = 0; if ((scalar_value & (1 << COMPARISONS)) != 0) { - result |= SQL_SQ_COMPARISON; + result_val |= SQL_SQ_COMPARISON; } if ((scalar_value & (1 << EXISTS)) != 0) { - result |= SQL_SQ_EXISTS; + result_val |= SQL_SQ_EXISTS; } if ((scalar_value & (1 << INN)) != 0) { - result |= SQL_SQ_IN; + result_val |= SQL_SQ_IN; } if ((scalar_value & (1 << QUANTIFIEDS)) != 0) { - result |= SQL_SQ_QUANTIFIED; + result_val |= SQL_SQ_QUANTIFIED; } - info_[SQL_SUBQUERIES] = result; + info_[SQL_SUBQUERIES] = result_val; break; } case SqlInfoOptions::SQL_SUPPORTED_UNIONS: { @@ -861,14 +875,14 @@ bool GetInfoCache::LoadInfoFromServer() { // Missing enum in C++. Values taken from java. constexpr int32_t UNION = 0; constexpr int32_t UNION_ALL = 1; - uint32_t result = 0; + uint32_t result_val = 0; if ((scalar_value & (1 << UNION)) != 0) { - result |= SQL_U_UNION; + result_val |= SQL_U_UNION; } if ((scalar_value & (1 << UNION_ALL)) != 0) { - result |= SQL_U_UNION_ALL; + result_val |= SQL_U_UNION_ALL; } - info_[SQL_UNION] = result; + info_[SQL_UNION] = result_val; break; } case SqlInfoOptions::SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS: { @@ -880,23 +894,23 @@ bool GetInfoCache::LoadInfoFromServer() { constexpr int32_t READ_COMMITTED = 2; constexpr int32_t REPEATABLE_READ = 3; constexpr int32_t SERIALIZABLE = 4; - uint32_t result = 0; + uint32_t result_val = 0; if ((scalar_value & (1 << NONE)) != 0) { - result = 0; + result_val = 0; } if ((scalar_value & (1 << READ_UNCOMMITTED)) != 0) { - result |= SQL_TXN_READ_UNCOMMITTED; + result_val |= SQL_TXN_READ_UNCOMMITTED; } if ((scalar_value & (1 << READ_COMMITTED)) != 0) { - result |= SQL_TXN_READ_COMMITTED; + result_val |= SQL_TXN_READ_COMMITTED; } if ((scalar_value & (1 << REPEATABLE_READ)) != 0) { - result |= SQL_TXN_REPEATABLE_READ; + result_val |= SQL_TXN_REPEATABLE_READ; } if ((scalar_value & (1 << SERIALIZABLE)) != 0) { - result |= SQL_TXN_SERIALIZABLE; + result_val |= SQL_TXN_SERIALIZABLE; } - info_[SQL_TXN_ISOLATION_OPTION] = result; + info_[SQL_TXN_ISOLATION_OPTION] = result_val; break; } case SqlInfoOptions::SQL_SUPPORTED_RESULT_SET_TYPES: @@ -922,40 +936,40 @@ bool GetInfoCache::LoadInfoFromServer() { // List properties case ARROW_SQL_NUMERIC_FUNCTIONS: { std::shared_ptr list_value = - reinterpret_cast(scalar)->value; - uint32_t result = 0; + reinterpret_cast(scalar->value.get())->value; + uint32_t result_val = 0; for (int64_t list_index = 0; list_index < list_value->length(); ++list_index) { if (!list_value->IsNull(list_index)) { ReportNumericFunction( reinterpret_cast(list_value.get()) ->GetString(list_index), - result); + result_val); } } - info_[SQL_NUMERIC_FUNCTIONS] = result; + info_[SQL_NUMERIC_FUNCTIONS] = result_val; break; } case ARROW_SQL_STRING_FUNCTIONS: { std::shared_ptr list_value = - reinterpret_cast(scalar)->value; - uint32_t result = 0; + reinterpret_cast(scalar->value.get())->value; + uint32_t result_val = 0; for (int64_t list_index = 0; list_index < list_value->length(); ++list_index) { if (!list_value->IsNull(list_index)) { ReportStringFunction( reinterpret_cast(list_value.get()) ->GetString(list_index), - result); + result_val); } } - info_[SQL_STRING_FUNCTIONS] = result; + info_[SQL_STRING_FUNCTIONS] = result_val; break; } case ARROW_SQL_SYSTEM_FUNCTIONS: { std::shared_ptr list_value = - reinterpret_cast(scalar)->value; + reinterpret_cast(scalar->value.get())->value; uint32_t sys_result = 0; uint32_t convert_result = 0; for (int64_t list_index = 0; list_index < list_value->length(); @@ -973,38 +987,38 @@ bool GetInfoCache::LoadInfoFromServer() { } case SqlInfoOptions::SQL_DATETIME_FUNCTIONS: { std::shared_ptr list_value = - reinterpret_cast(scalar)->value; - uint32_t result = 0; + reinterpret_cast(scalar->value.get())->value; + uint32_t result_val = 0; for (int64_t list_index = 0; list_index < list_value->length(); ++list_index) { if (!list_value->IsNull(list_index)) { ReportDatetimeFunction( reinterpret_cast(list_value.get()) ->GetString(list_index), - result); + result_val); } } - info_[SQL_TIMEDATE_FUNCTIONS] = result; + info_[SQL_TIMEDATE_FUNCTIONS] = result_val; break; } case ARROW_SQL_KEYWORDS: { - std::shared_ptr list_value = - reinterpret_cast(scalar)->value; - std::string result; - for (int64_t list_index = 0; list_index < list_value->length(); - ++list_index) { - if (!list_value->IsNull(list_index)) { - if (list_index != 0) { - result += ", "; - } - - result += reinterpret_cast(list_value.get()) - ->GetString(list_index); + std::shared_ptr list_value = + reinterpret_cast(scalar->value.get())->value; + std::string result_str; + for (int64_t list_index = 0; list_index < list_value->length(); + ++list_index) { + if (!list_value->IsNull(list_index)) { + if (list_index != 0) { + result_str += ", "; } + + result_str += reinterpret_cast(list_value.get()) + ->GetString(list_index); } - info_[SQL_KEYWORDS] = std::move(result); - break; + } + info_[SQL_KEYWORDS] = std::move(result_str); + break; } // Map properties @@ -1031,12 +1045,12 @@ bool GetInfoCache::LoadInfoFromServer() { map_value_scalar_ptr.get()) ->value; - int32_t info_type = + int32_t get_info_type = GetInfoTypeForArrowConvertEntry(map_key_scalar); - if (info_type < 0) { + if (get_info_type < 0) { continue; } - uint32_t info_to_write = 0; + uint32_t info_bitmask_value_to_write = 0; for (int64_t map_value_array_index = 0; map_value_array_index < map_value_scalar->length(); ++map_value_array_index) { @@ -1044,13 +1058,13 @@ bool GetInfoCache::LoadInfoFromServer() { auto list_entry_scalar = map_value_scalar->GetScalar(map_value_array_index) .ValueOrDie(); - info_to_write |= GetCvtBitForArrowConvertEntry( + info_bitmask_value_to_write |= GetCvtBitForArrowConvertEntry( reinterpret_cast( list_entry_scalar.get()) ->value); } } - info_[info_type] = info_to_write; + info_[get_info_type] = info_bitmask_value_to_write; } } break; @@ -1087,11 +1101,250 @@ bool GetInfoCache::LoadInfoFromServer() { info_[SQL_CORRELATION_NAME] = static_cast(SQL_CN_NONE); } } + LoadDefaultsForMissingEntries(); return true; } return false; } +void GetInfoCache::LoadDefaultsForMissingEntries() { + // For safety's sake, this function does not discriminate between driver and hard-coded values. + SetDefaultIfMissing(info_, SQL_ACCESSIBLE_PROCEDURES, "N"); + SetDefaultIfMissing(info_, SQL_ACCESSIBLE_TABLES, "Y"); + SetDefaultIfMissing(info_, SQL_ACTIVE_ENVIRONMENTS, static_cast(0)); + SetDefaultIfMissing(info_, SQL_AGGREGATE_FUNCTIONS, + static_cast(SQL_AF_ALL | SQL_AF_AVG | + SQL_AF_COUNT | SQL_AF_DISTINCT | + SQL_AF_MAX | SQL_AF_MIN | + SQL_AF_SUM)); + SetDefaultIfMissing(info_, SQL_ALTER_DOMAIN, static_cast(0)); + SetDefaultIfMissing(info_, SQL_ALTER_TABLE, static_cast(0)); + SetDefaultIfMissing(info_, SQL_ASYNC_MODE, + static_cast(SQL_AM_NONE)); + SetDefaultIfMissing(info_, SQL_BATCH_ROW_COUNT, static_cast(0)); + SetDefaultIfMissing(info_, SQL_BATCH_SUPPORT, static_cast(0)); + SetDefaultIfMissing(info_, SQL_BOOKMARK_PERSISTENCE, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_CATALOG_LOCATION, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CATALOG_NAME, "N"); + SetDefaultIfMissing(info_, SQL_CATALOG_NAME_SEPARATOR, ""); + SetDefaultIfMissing(info_, SQL_CATALOG_TERM, ""); + SetDefaultIfMissing(info_, SQL_CATALOG_USAGE, static_cast(0)); + SetDefaultIfMissing(info_, SQL_COLLATION_SEQ, ""); + SetDefaultIfMissing(info_, SQL_COLUMN_ALIAS, "Y"); + SetDefaultIfMissing(info_, SQL_CONCAT_NULL_BEHAVIOR, + static_cast(SQL_CB_NULL)); + SetDefaultIfMissing(info_, SQL_CONVERT_BIGINT, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_BINARY, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_BIT, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_CHAR, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_DATE, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_DECIMAL, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_DOUBLE, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_FLOAT, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_GUID, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_INTEGER,static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_INTERVAL_YEAR_MONTH, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_INTERVAL_DAY_TIME, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_LONGVARBINARY, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_LONGVARCHAR, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_NUMERIC, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_REAL, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_SMALLINT, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_TIME, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_TIMESTAMP, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_TINYINT, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_VARBINARY, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_VARCHAR, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_WCHAR, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_WVARCHAR, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_WLONGVARCHAR, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_CONVERT_WLONGVARCHAR, + static_cast(SQL_FN_CVT_CAST)); + SetDefaultIfMissing(info_, SQL_CORRELATION_NAME, + static_cast(SQL_CN_NONE)); + SetDefaultIfMissing(info_, SQL_CREATE_ASSERTION, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CREATE_CHARACTER_SET, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_CREATE_DOMAIN, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CREATE_SCHEMA, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CREATE_TABLE, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CREATE_TRANSLATION, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CREATE_VIEW, static_cast(0)); + SetDefaultIfMissing(info_, SQL_CURSOR_COMMIT_BEHAVIOR, + static_cast(SQL_CB_CLOSE)); + SetDefaultIfMissing(info_, SQL_CURSOR_ROLLBACK_BEHAVIOR, + static_cast(SQL_CB_CLOSE)); + SetDefaultIfMissing(info_, SQL_CURSOR_SENSITIVITY, + static_cast(SQL_UNSPECIFIED)); + SetDefaultIfMissing(info_, SQL_DATA_SOURCE_READ_ONLY, "N"); + SetDefaultIfMissing(info_, SQL_DBMS_NAME, "Arrow Flight SQL Server"); + SetDefaultIfMissing(info_, SQL_DBMS_VER, "00.01.0000"); + SetDefaultIfMissing(info_, SQL_DDL_INDEX, static_cast(0)); + SetDefaultIfMissing(info_, SQL_DEFAULT_TXN_ISOLATION, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_DESCRIBE_PARAMETER, "N"); + SetDefaultIfMissing(info_, SQL_DRIVER_NAME, "Arrow Flight SQL Driver"); + SetDefaultIfMissing(info_, SQL_DRIVER_ODBC_VER, "03.80"); + SetDefaultIfMissing(info_, SQL_DRIVER_VER, "01.00.0000"); + SetDefaultIfMissing(info_, SQL_DROP_ASSERTION, static_cast(0)); + SetDefaultIfMissing(info_, SQL_DROP_CHARACTER_SET, static_cast(0)); + SetDefaultIfMissing(info_, SQL_DROP_COLLATION, static_cast(0)); + SetDefaultIfMissing(info_, SQL_DROP_DOMAIN, static_cast(0)); + SetDefaultIfMissing(info_, SQL_DROP_SCHEMA, static_cast(0)); + SetDefaultIfMissing(info_, SQL_DROP_TABLE, static_cast(0)); + SetDefaultIfMissing(info_, SQL_DROP_TRANSLATION, static_cast(0)); + SetDefaultIfMissing(info_, SQL_DROP_VIEW, static_cast(0)); + SetDefaultIfMissing(info_, SQL_EXPRESSIONS_IN_ORDERBY, "N"); + SetDefaultIfMissing( + info_, SQL_GETDATA_EXTENSIONS, + static_cast(SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER)); + SetDefaultIfMissing(info_, SQL_GROUP_BY, + static_cast(SQL_GB_GROUP_BY_CONTAINS_SELECT)); + SetDefaultIfMissing(info_, SQL_IDENTIFIER_CASE, + static_cast(SQL_IC_MIXED)); + SetDefaultIfMissing(info_, SQL_IDENTIFIER_QUOTE_CHAR, "\""); + SetDefaultIfMissing(info_, SQL_INDEX_KEYWORDS, + static_cast(SQL_IK_NONE)); + SetDefaultIfMissing( + info_, SQL_INFO_SCHEMA_VIEWS, + static_cast(SQL_ISV_TABLES | SQL_ISV_COLUMNS | SQL_ISV_VIEWS)); + SetDefaultIfMissing(info_, SQL_INSERT_STATEMENT, + static_cast(SQL_IS_INSERT_LITERALS | + SQL_IS_INSERT_SEARCHED | + SQL_IS_SELECT_INTO)); + SetDefaultIfMissing(info_, SQL_INTEGRITY, "N"); + SetDefaultIfMissing(info_, SQL_KEYWORDS, ""); + SetDefaultIfMissing(info_, SQL_LIKE_ESCAPE_CLAUSE, "Y"); + SetDefaultIfMissing(info_, SQL_MAX_ASYNC_CONCURRENT_STATEMENTS, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_BINARY_LITERAL_LEN, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_CATALOG_NAME_LEN, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_CHAR_LITERAL_LEN, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_COLUMN_NAME_LEN, static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_COLUMNS_IN_GROUP_BY, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_COLUMNS_IN_INDEX, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_COLUMNS_IN_ORDER_BY, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_COLUMNS_IN_SELECT, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_COLUMNS_IN_TABLE, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_CURSOR_NAME_LEN, static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_DRIVER_CONNECTIONS, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_IDENTIFIER_LEN, + static_cast(65535)); + SetDefaultIfMissing(info_, SQL_MAX_INDEX_SIZE, static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_PROCEDURE_NAME_LEN, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_ROW_SIZE, static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_ROW_SIZE_INCLUDES_LONG, "N"); + SetDefaultIfMissing(info_, SQL_MAX_SCHEMA_NAME_LEN, static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_STATEMENT_LEN, static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_TABLE_NAME_LEN, static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_TABLES_IN_SELECT, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_MAX_USER_NAME_LEN, static_cast(0)); + SetDefaultIfMissing(info_, SQL_NON_NULLABLE_COLUMNS, + static_cast(SQL_NNC_NULL)); + SetDefaultIfMissing(info_, SQL_NULL_COLLATION, + static_cast(SQL_NC_END)); + SetDefaultIfMissing(info_, SQL_NUMERIC_FUNCTIONS, static_cast(0)); + SetDefaultIfMissing( + info_, SQL_OJ_CAPABILITIES, + static_cast(SQL_OJ_LEFT | SQL_OJ_RIGHT | SQL_OJ_FULL)); + SetDefaultIfMissing(info_, SQL_ORDER_BY_COLUMNS_IN_SELECT, "Y"); + SetDefaultIfMissing(info_, SQL_PROCEDURE_TERM, ""); + SetDefaultIfMissing(info_, SQL_PROCEDURES, "N"); + SetDefaultIfMissing(info_, SQL_QUOTED_IDENTIFIER_CASE, + static_cast(SQL_IC_SENSITIVE)); + SetDefaultIfMissing(info_, SQL_SCHEMA_TERM, "schema"); + SetDefaultIfMissing(info_, SQL_SCHEMA_USAGE, + static_cast(SQL_SU_DML_STATEMENTS)); + SetDefaultIfMissing(info_, SQL_SEARCH_PATTERN_ESCAPE, "\\"); + SetDefaultIfMissing(info_, SQL_SERVER_NAME, + "Arrow Flight SQL Server"); // This might actually need to be the hostname. + SetDefaultIfMissing(info_, SQL_SQL_CONFORMANCE, + static_cast(SQL_SC_SQL92_ENTRY)); + SetDefaultIfMissing(info_, SQL_SQL92_DATETIME_FUNCTIONS, + static_cast(SQL_SDF_CURRENT_DATE | + SQL_SDF_CURRENT_TIME | + SQL_SDF_CURRENT_TIMESTAMP)); + SetDefaultIfMissing(info_, SQL_SQL92_FOREIGN_KEY_DELETE_RULE, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_SQL92_FOREIGN_KEY_UPDATE_RULE, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_SQL92_GRANT, static_cast(0)); + SetDefaultIfMissing(info_, SQL_SQL92_NUMERIC_VALUE_FUNCTIONS, + static_cast(0)); + SetDefaultIfMissing(info_, SQL_SQL92_PREDICATES, + static_cast(SQL_SP_BETWEEN | SQL_SP_COMPARISON | + SQL_SP_EXISTS | SQL_SP_IN | + SQL_SP_ISNOTNULL | SQL_SP_ISNULL | + SQL_SP_LIKE)); + SetDefaultIfMissing(info_, SQL_SQL92_RELATIONAL_JOIN_OPERATORS, + static_cast( + SQL_SRJO_INNER_JOIN | SQL_SRJO_CROSS_JOIN | + SQL_SRJO_LEFT_OUTER_JOIN | SQL_SRJO_FULL_OUTER_JOIN | + SQL_SRJO_RIGHT_OUTER_JOIN)); + SetDefaultIfMissing(info_, SQL_SQL92_REVOKE, static_cast(0)); + SetDefaultIfMissing( + info_, SQL_SQL92_ROW_VALUE_CONSTRUCTOR, + static_cast(SQL_SRVC_VALUE_EXPRESSION | SQL_SRVC_NULL)); + SetDefaultIfMissing( + info_, SQL_SQL92_STRING_FUNCTIONS, + static_cast(SQL_SSF_CONVERT | SQL_SSF_LOWER | SQL_SSF_UPPER | + SQL_SSF_SUBSTRING | SQL_SSF_TRIM_BOTH | + SQL_SSF_TRIM_LEADING | SQL_SSF_TRIM_TRAILING)); + SetDefaultIfMissing(info_, SQL_SQL92_VALUE_EXPRESSIONS, + static_cast(SQL_SVE_CASE | SQL_SVE_CAST | + SQL_SVE_COALESCE | SQL_SVE_NULLIF)); + SetDefaultIfMissing(info_, SQL_STANDARD_CLI_CONFORMANCE, + static_cast(0)); + SetDefaultIfMissing( + info_, SQL_STRING_FUNCTIONS, + static_cast(SQL_FN_STR_CONCAT | SQL_FN_STR_LCASE | + SQL_FN_STR_LENGTH | SQL_FN_STR_LTRIM | + SQL_FN_STR_RTRIM | SQL_FN_STR_SPACE | + SQL_FN_STR_SUBSTRING | SQL_FN_STR_UCASE)); + SetDefaultIfMissing(info_, SQL_SUBQUERIES, + static_cast(SQL_SQ_CORRELATED_SUBQUERIES | + SQL_SQ_COMPARISON | SQL_SQ_EXISTS | + SQL_SQ_IN | SQL_SQ_QUANTIFIED)); + SetDefaultIfMissing( + info_, SQL_SYSTEM_FUNCTIONS, + static_cast(SQL_FN_SYS_IFNULL | SQL_FN_SYS_USERNAME)); + SetDefaultIfMissing(info_, SQL_TIMEDATE_ADD_INTERVALS, + static_cast( + SQL_FN_TSI_FRAC_SECOND | SQL_FN_TSI_SECOND | + SQL_FN_TSI_MINUTE | SQL_FN_TSI_HOUR | SQL_FN_TSI_DAY | + SQL_FN_TSI_WEEK | SQL_FN_TSI_MONTH | + SQL_FN_TSI_QUARTER | SQL_FN_TSI_YEAR)); + SetDefaultIfMissing(info_, SQL_TIMEDATE_DIFF_INTERVALS, + static_cast( + SQL_FN_TSI_FRAC_SECOND | SQL_FN_TSI_SECOND | + SQL_FN_TSI_MINUTE | SQL_FN_TSI_HOUR | SQL_FN_TSI_DAY | + SQL_FN_TSI_WEEK | SQL_FN_TSI_MONTH | + SQL_FN_TSI_QUARTER | SQL_FN_TSI_YEAR)); + SetDefaultIfMissing(info_, SQL_UNION, + static_cast(SQL_U_UNION | SQL_U_UNION_ALL)); + SetDefaultIfMissing(info_, SQL_XOPEN_CLI_YEAR, "1995"); + SetDefaultIfMissing(info_, SQL_ODBC_SQL_CONFORMANCE, + static_cast(SQL_OSC_MINIMUM)); + SetDefaultIfMissing(info_, SQL_ODBC_SAG_CLI_CONFORMANCE, + static_cast(SQL_OSCC_COMPLIANT)); + } + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h index 96f490c80012a..a859e9efdf3ff 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include @@ -27,7 +27,7 @@ namespace flight_sql { class GetInfoCache { private: - std::map info_; + std::unordered_map info_; arrow::flight::FlightCallOptions &call_options_; std::unique_ptr &sql_client_; std::mutex mutex_; @@ -42,6 +42,7 @@ class GetInfoCache { private: bool LoadInfoFromServer(); + void LoadDefaultsForMissingEntries(); }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc index 6dca30288b9dd..4e057a571634a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc @@ -137,6 +137,12 @@ void ODBCConnection::GetInfo(SQLUSMALLINT infoType, SQLPOINTER value, SQLSMALLIN GetAttribute(static_cast(SQL_ASYNC_NOTIFICATION_NOT_CAPABLE), value, bufferLength, outputLength); break; #endif + case SQL_BATCH_ROW_COUNT: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; + case SQL_BATCH_SUPPORT: + GetAttribute(static_cast(0), value, bufferLength, outputLength); + break; case SQL_DATA_SOURCE_NAME: GetStringAttribute(isUnicode, m_dsn, true, value, bufferLength, outputLength, GetDiagnostics()); break; @@ -214,9 +220,6 @@ void ODBCConnection::GetInfo(SQLUSMALLINT infoType, SQLPOINTER value, SQLSMALLIN case SQL_TABLE_TERM: GetStringAttribute(isUnicode, "table", true, value, bufferLength, outputLength, GetDiagnostics()); break; - case SQL_COLUMN_ALIAS: - GetStringAttribute(isUnicode, "Y", true, value, bufferLength, outputLength, GetDiagnostics()); - break; // Deprecated ODBC 2.x fields required for backwards compatibility. case SQL_ODBC_API_CONFORMANCE: GetAttribute(static_cast(SQL_OAC_LEVEL1), value, bufferLength, outputLength); @@ -242,9 +245,10 @@ void ODBCConnection::GetInfo(SQLUSMALLINT infoType, SQLPOINTER value, SQLSMALLIN // Driver-level string properties. case SQL_USER_NAME: + case SQL_COLUMN_ALIAS: case SQL_DBMS_NAME: case SQL_DBMS_VER: - case SQL_DRIVER_NAME: + case SQL_DRIVER_NAME: // TODO: This should be the driver's filename and shouldn't come from the SPI. case SQL_DRIVER_VER: case SQL_SEARCH_PATTERN_ESCAPE: case SQL_SERVER_NAME: @@ -260,10 +264,14 @@ void ODBCConnection::GetInfo(SQLUSMALLINT infoType, SQLPOINTER value, SQLSMALLIN case SQL_IDENTIFIER_QUOTE_CHAR: case SQL_INTEGRITY: case SQL_KEYWORDS: + case SQL_LIKE_ESCAPE_CLAUSE: + case SQL_MAX_ROW_SIZE_INCLUDES_LONG: + case SQL_ORDER_BY_COLUMNS_IN_SELECT: case SQL_OUTER_JOINS: // Not documented in SQLGetInfo, but other drivers return Y/N strings + case SQL_PROCEDURE_TERM: case SQL_PROCEDURES: case SQL_SPECIAL_CHARACTERS: - case SQL_MAX_ROW_SIZE_INCLUDES_LONG: + case SQL_XOPEN_CLI_YEAR: { const auto& info = m_spiConnection->GetInfo(infoType); const std::string& infoValue = boost::get(info); @@ -271,7 +279,7 @@ void ODBCConnection::GetInfo(SQLUSMALLINT infoType, SQLPOINTER value, SQLSMALLIN break; } - // Driver-level 32-bit integer propreties. + // Driver-level 32-bit integer properties. case SQL_GETDATA_EXTENSIONS: case SQL_INFO_SCHEMA_VIEWS: case SQL_CURSOR_SENSITIVITY: @@ -288,11 +296,11 @@ void ODBCConnection::GetInfo(SQLUSMALLINT infoType, SQLPOINTER value, SQLSMALLIN case SQL_CREATE_DOMAIN: case SQL_CREATE_SCHEMA: case SQL_CREATE_TABLE: + case SQL_CREATE_TRANSLATION: + case SQL_CREATE_VIEW: case SQL_INDEX_KEYWORDS: case SQL_INSERT_STATEMENT: - case SQL_LIKE_ESCAPE_CLAUSE: case SQL_OJ_CAPABILITIES: - case SQL_ORDER_BY_COLUMNS_IN_SELECT: case SQL_SCHEMA_USAGE: case SQL_SQL_CONFORMANCE: case SQL_SUBQUERIES: @@ -316,6 +324,7 @@ void ODBCConnection::GetInfo(SQLUSMALLINT infoType, SQLPOINTER value, SQLSMALLIN case SQL_CONVERT_DECIMAL: case SQL_CONVERT_DOUBLE: case SQL_CONVERT_FLOAT: + case SQL_CONVERT_GUID: case SQL_CONVERT_INTEGER: case SQL_CONVERT_INTERVAL_DAY_TIME: case SQL_CONVERT_INTERVAL_YEAR_MONTH: @@ -329,6 +338,31 @@ void ODBCConnection::GetInfo(SQLUSMALLINT infoType, SQLPOINTER value, SQLSMALLIN case SQL_CONVERT_TINYINT: case SQL_CONVERT_VARBINARY: case SQL_CONVERT_VARCHAR: + case SQL_CONVERT_WCHAR: + case SQL_CONVERT_WVARCHAR: + case SQL_CONVERT_WLONGVARCHAR: + case SQL_DDL_INDEX: + case SQL_DROP_ASSERTION: + case SQL_DROP_CHARACTER_SET: + case SQL_DROP_COLLATION: + case SQL_DROP_DOMAIN: + case SQL_DROP_SCHEMA: + case SQL_DROP_TABLE: + case SQL_DROP_TRANSLATION: + case SQL_DROP_VIEW: + case SQL_MAX_INDEX_SIZE: + case SQL_SQL92_DATETIME_FUNCTIONS: + case SQL_SQL92_FOREIGN_KEY_DELETE_RULE: + case SQL_SQL92_FOREIGN_KEY_UPDATE_RULE: + case SQL_SQL92_GRANT: + case SQL_SQL92_NUMERIC_VALUE_FUNCTIONS: + case SQL_SQL92_PREDICATES: + case SQL_SQL92_RELATIONAL_JOIN_OPERATORS: + case SQL_SQL92_REVOKE: + case SQL_SQL92_ROW_VALUE_CONSTRUCTOR: + case SQL_SQL92_STRING_FUNCTIONS: + case SQL_SQL92_VALUE_EXPRESSIONS: + case SQL_STANDARD_CLI_CONFORMANCE: { const auto& info = m_spiConnection->GetInfo(infoType); uint32_t infoValue = boost::get(info); @@ -345,16 +379,6 @@ void ODBCConnection::GetInfo(SQLUSMALLINT infoType, SQLPOINTER value, SQLSMALLIN case SQL_NULL_COLLATION: case SQL_CATALOG_LOCATION: case SQL_CORRELATION_NAME: - case SQL_CREATE_TRANSLATION: - case SQL_DDL_INDEX: - case SQL_DROP_ASSERTION: - case SQL_DROP_CHARACTER_SET: - case SQL_DROP_COLLATION: - case SQL_DROP_DOMAIN: - case SQL_DROP_SCHEMA: - case SQL_DROP_TABLE: - case SQL_DROP_TRANSLATION: - case SQL_DROP_VIEW: case SQL_GROUP_BY: case SQL_IDENTIFIER_CASE: case SQL_NON_NULLABLE_COLUMNS: @@ -371,7 +395,10 @@ void ODBCConnection::GetInfo(SQLUSMALLINT infoType, SQLPOINTER value, SQLSMALLIN case SQL_MAX_SCHEMA_NAME_LEN: case SQL_MAX_TABLE_NAME_LEN: case SQL_MAX_TABLES_IN_SELECT: + case SQL_MAX_PROCEDURE_NAME_LEN: case SQL_MAX_USER_NAME_LEN: + case SQL_ODBC_SQL_CONFORMANCE: + case SQL_ODBC_SAG_CLI_CONFORMANCE: { const auto& info = m_spiConnection->GetInfo(infoType); uint16_t infoValue = boost::get(info); From 38b4d2b773953e684f3734b061f312fc1b533ecd Mon Sep 17 00:00:00 2001 From: Alex McRae Date: Mon, 13 Jun 2022 14:12:31 -0700 Subject: [PATCH 128/183] Implement returning concise types Change-Id: Ief9dfbb2a3135f7532611676f3eea493b70923d4 --- .../flight_sql/flight_sql_result_set_metadata.cc | 14 +++++++++----- .../flight_sql/flight_sql_result_set_metadata.h | 4 ++-- .../flightsql-odbc/flight_sql/utils.cc | 13 +++++++++++-- .../odbcabstraction/spi/result_set_metadata.h | 6 +++--- .../odbcabstraction/odbc_impl/ODBCDescriptor.cc | 2 +- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index 6561589a479ae..61116eb427db5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -10,6 +10,7 @@ #include #include "utils.h" +#include #include #include @@ -57,9 +58,10 @@ size_t FlightSqlResultSetMetadata::GetScale(int column_position) { return metadata.GetScale().ValueOrElse([] { return 0; }); } -SqlDataType FlightSqlResultSetMetadata::GetDataType(int column_position) { +uint16_t FlightSqlResultSetMetadata::GetDataType(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - return GetDataTypeFromArrowField_V3(field); + const SqlDataType conciseType = GetDataTypeFromArrowField_V3(field); + return GetNonConciseDataType(conciseType); } driver::odbcabstraction::Nullability @@ -110,9 +112,11 @@ std::string FlightSqlResultSetMetadata::GetBaseTableName(int column_position) { return metadata.GetTableName().ValueOrElse([] { return ""; }); } -std::string FlightSqlResultSetMetadata::GetConciseType(int column_position) { - // TODO Implement after the PR from column metadata is merged - return ""; +uint16_t FlightSqlResultSetMetadata::GetConciseType(int column_position) { + const std::shared_ptr &field = schema_->field(column_position -1); + + const SqlDataType sqlColumnType = GetDataTypeFromArrowField_V3(field); + return sqlColumnType; } size_t FlightSqlResultSetMetadata::GetLength(int column_position) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h index 3349a0276b684..256fdb11f0612 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h @@ -30,7 +30,7 @@ class FlightSqlResultSetMetadata : public odbcabstraction::ResultSetMetadata { size_t GetScale(int column_position) override; - odbcabstraction::SqlDataType GetDataType(int column_position) override; + uint16_t GetDataType(int column_position) override; odbcabstraction::Nullability IsNullable(int column_position) override; @@ -48,7 +48,7 @@ class FlightSqlResultSetMetadata : public odbcabstraction::ResultSetMetadata { std::string GetBaseTableName(int column_position) override; - std::string GetConciseType(int column_position) override; + uint16_t GetConciseType(int column_position) override; size_t GetLength(int column_position) override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 986f0a7107bcc..997341e2bde4f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -37,6 +37,11 @@ using namespace odbcabstraction; using arrow::util::make_optional; using arrow::util::nullopt; +/// \brief Returns the mapping from Arrow type to SqlDataType +/// \param field the field to return the SqlDataType for +/// \return the concise SqlDataType for the field. +/// \note use GetNonConciseDataType on the output to get the verbose type +/// \note the concise and verbose types are the same for all but types relating to times and intervals SqlDataType GetDataTypeFromArrowField_V3(const std::shared_ptr &field) { const std::shared_ptr &type = field->type(); @@ -78,10 +83,12 @@ GetDataTypeFromArrowField_V3(const std::shared_ptr &field) { case arrow::Type::TIME32: case arrow::Type::TIME64: return odbcabstraction::SqlDataType_TYPE_TIME; - - // TODO: Handle remaining types. case arrow::Type::INTERVAL_MONTHS: + return odbcabstraction::SqlDataType_INTERVAL_MONTH; // TODO: maybe SqlDataType_INTERVAL_YEAR_TO_MONTH case arrow::Type::INTERVAL_DAY_TIME: + return odbcabstraction::SqlDataType_INTERVAL_DAY; + + // TODO: Handle remaining types. case arrow::Type::INTERVAL_MONTH_DAY_NANO: case arrow::Type::LIST: case arrow::Type::STRUCT: @@ -305,6 +312,8 @@ optional GetSqlDateTimeSubCode(SqlDataType data_type) { optional GetCharOctetLength(SqlDataType data_type, const optional& column_size) { + // TODO: Replace NO_TOTAL with the correct default values + // TODO: Get correct default values from connection settings switch (data_type) { case SqlDataType_CHAR: case SqlDataType_VARCHAR: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set_metadata.h index de8feaade3fbe..d3914049ba382 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set_metadata.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set_metadata.h @@ -42,7 +42,7 @@ class ResultSetMetadata { /// \brief It retrieves the SQL_DATA_TYPE of the column. /// \param column_position[in] the position of the column, starting from 1. /// \return the SQL_DATA_TYPE - virtual SqlDataType GetDataType(int column_position) = 0; + virtual uint16_t GetDataType(int column_position) = 0; /// \brief It returns a boolean value indicating if the column can have /// null values. @@ -86,10 +86,10 @@ class ResultSetMetadata { /// \return the base table name. virtual std::string GetBaseTableName(int column_position) = 0; - /// \brief It retrieves the concise data type. + /// \brief It retrieves the concise data type (SQL_DESC_CONCISE_TYPE). /// \param column_position[in] the position of the column, starting from 1. /// \return the concise data type. - virtual std::string GetConciseType(int column_position) = 0; + virtual uint16_t GetConciseType(int column_position) = 0; /// \brief It retrieves the maximum or the actual character length /// of a character string or binary data type. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc index c0bcead4ce1ed..2d1abcab6540a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc @@ -458,6 +458,7 @@ void ODBCDescriptor::PopulateFromResultSetMetadata(ResultSetMetadata* rsmd) { m_records[i].m_schemaName = rsmd->GetSchemaName(oneBasedIndex); m_records[i].m_tableName = rsmd->GetTableName(oneBasedIndex); m_records[i].m_typeName = rsmd->GetTypeName(oneBasedIndex); + m_records[i].m_conciseType = GetSqlTypeForODBCVersion(rsmd->GetConciseType(oneBasedIndex), m_is2xConnection); m_records[i].m_dataPtr = nullptr; m_records[i].m_indicatorPtr = nullptr; m_records[i].m_displaySize = rsmd->GetColumnDisplaySize(oneBasedIndex); @@ -467,7 +468,6 @@ void ODBCDescriptor::PopulateFromResultSetMetadata(ResultSetMetadata* rsmd) { m_records[i].m_caseSensitive = rsmd->IsCaseSensitive(oneBasedIndex)? SQL_TRUE : SQL_FALSE; m_records[i].m_datetimeIntervalPrecision; // TODO - update when rsmd adds this m_records[i].m_numPrecRadix = rsmd->GetNumPrecRadix(oneBasedIndex); - m_records[i].m_conciseType = GetSqlTypeForODBCVersion(rsmd->GetDataType(oneBasedIndex), m_is2xConnection); // TODO: Check if this needs to be different than datatype. m_records[i].m_datetimeIntervalCode; // TODO m_records[i].m_fixedPrecScale = rsmd->IsFixedPrecScale(oneBasedIndex) ? SQL_TRUE : SQL_FALSE; m_records[i].m_nullable = rsmd->IsNullable(oneBasedIndex); From e233472f7530334eb5fc06f0fbe5fd6dc56a77b3 Mon Sep 17 00:00:00 2001 From: James Duong Date: Wed, 15 Jun 2022 13:58:33 -0700 Subject: [PATCH 129/183] Treat SQL_ATTR_AUTOCOMMIT as a SQLUINTEGER instead of SQLULEN Per the ODBC spec, SQL_ATTR_AUTOCOMMIT should always be SQLUINTEGER. This behaves correctly for SetConnectAttr and this patch fixes this for SQLGetConnectAttr Change-Id: I7e0939c5cbe1ad3a8e5eb2050289fd65e6e2534c --- .../flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc index 4e057a571634a..313b7b04f3c24 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCConnection.cc @@ -566,7 +566,7 @@ void ODBCConnection::GetConnectAttr(SQLINTEGER attribute, SQLPOINTER value, GetAttribute(static_cast(SQL_FALSE), value, bufferLength, outputLength); return; case SQL_ATTR_AUTOCOMMIT: - GetAttribute(static_cast(SQL_AUTOCOMMIT_ON), value, bufferLength, outputLength); + GetAttribute(static_cast(SQL_AUTOCOMMIT_ON), value, bufferLength, outputLength); return; #ifdef SQL_ATTR_DBC_INFO_TOKEN case SQL_ATTR_DBC_INFO_TOKEN: From 85d7f00b81c98ceb29cbcb7b8a8e8e4cbc4b62ed Mon Sep 17 00:00:00 2001 From: Vinicius Fraga Date: Wed, 15 Jun 2022 14:05:30 -0300 Subject: [PATCH 130/183] Match driver version SQLInfo with Warpdrive Change-Id: Ifd018764e55bbe417723817980c9904437d8ec6c --- .../flightsql-odbc/flight_sql/get_info_cache.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc index 1e4ae1ff73161..4443ea48dd4a2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc @@ -198,7 +198,7 @@ GetInfoCache::GetInfoCache(FlightCallOptions &call_options, : call_options_(call_options), sql_client_(client), has_server_info_(false) { info_[SQL_DRIVER_NAME] = "Arrow Flight ODBC Driver"; - info_[SQL_DRIVER_VER] = "01.00.0000"; // This should be generated dynamically. + info_[SQL_DRIVER_VER] = ConvertToDBMSVer("0.9.0.0"); // This should be generated dynamically. info_[SQL_GETDATA_EXTENSIONS] = static_cast(SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER); From aa83ebe778b8cccdbcd90e67dbeaaacdfecdb7d7 Mon Sep 17 00:00:00 2001 From: Vinicius Fraga Date: Thu, 16 Jun 2022 08:27:43 -0300 Subject: [PATCH 131/183] Match the SQLState of auth errors with the legacy driver Change-Id: Ice947cb2f12ef1b47d8fb853848512fff45f3b49 --- .../odbcabstraction/include/odbcabstraction/exceptions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h index 41a4051be9a49..6d7288a9098b5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h @@ -35,7 +35,7 @@ class DriverException : public std::exception { /// \brief Authentication specific exception class AuthenticationException : public DriverException { public: - explicit AuthenticationException(std::string message, std::string sql_state = "28000", + explicit AuthenticationException(std::string message, std::string sql_state = "08S01", int32_t native_error = ODBCErrorCodes_AUTH); }; From a44f18ed7d77ee729170464215173869b9929f72 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Fri, 17 Jun 2022 15:15:46 -0300 Subject: [PATCH 132/183] Fix SQL_C_BINARY data conversions This fixes retrieving data as SQL_C_BINARY by handling it the same conversion as SQL_C_DEFAULT on accessor level. Change-Id: I44e98793f71e9eca0c65dc202187eb5467bec8ca --- .../flightsql-odbc/flight_sql/flight_sql_result_set_column.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index 2468d2252569a..4b4e13a60f7bb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -45,7 +45,8 @@ FlightSqlResultSetColumn::GetAccessorForTargetType(CDataType target_type) { const std::shared_ptr &original_array = result_set_->GetArrayForColumn(column_n_); - if (target_type == odbcabstraction::CDataType_DEFAULT) { + // When retrieving data as binary, its bytes should be the same as it's default type + if (target_type == odbcabstraction::CDataType_DEFAULT || target_type == odbcabstraction::CDataType_BINARY) { target_type = ConvertArrowTypeToC(original_array->type_id()); } From b03a6604bec1c2b5239eb0b5e86ddf2e5ad987ba Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 7 Jun 2022 17:53:24 -0300 Subject: [PATCH 133/183] Fill up row status array This makes the driver fill up the row status array that ODBC applications can pass using as SQL_DESC_ARRAY_STATUS_PTR. Each row can have a status SUCCESS, SUCCESS_WITH_INFO (when data is truncated) and ERROR. Change-Id: I85590c766daac7510aca68e667c7a4a907193f73 --- .../accessors/binary_array_accessor.cc | 10 ++++--- .../accessors/binary_array_accessor.h | 5 ++-- .../accessors/binary_array_accessor_test.cc | 4 +-- .../accessors/boolean_array_accessor.cc | 4 ++- .../accessors/boolean_array_accessor.h | 2 +- .../accessors/boolean_array_accessor_test.cc | 2 +- .../accessors/date_array_accessor.cc | 4 ++- .../accessors/date_array_accessor.h | 2 +- .../accessors/date_array_accessor_test.cc | 4 +-- .../accessors/decimal_array_accessor.cc | 4 ++- .../accessors/decimal_array_accessor.h | 6 ++--- .../accessors/decimal_array_accessor_test.cc | 2 +- .../accessors/primitive_array_accessor.cc | 3 ++- .../accessors/primitive_array_accessor.h | 3 ++- .../primitive_array_accessor_test.cc | 2 +- .../accessors/string_array_accessor.cc | 14 ++++++---- .../accessors/string_array_accessor.h | 2 +- .../accessors/string_array_accessor_test.cc | 8 +++--- .../accessors/time_array_accessor.cc | 2 +- .../accessors/time_array_accessor.h | 2 +- .../accessors/time_array_accessor_test.cc | 8 +++--- .../accessors/timestamp_array_accessor.cc | 4 ++- .../accessors/timestamp_array_accessor.h | 2 +- .../timestamp_array_accessor_test.cc | 8 +++--- .../flight_sql/accessors/types.h | 27 +++++++++++-------- .../flight_sql/flight_sql_result_set.cc | 23 +++++++++++++--- .../flight_sql/flight_sql_result_set.h | 2 +- .../flightsql-odbc/flight_sql/main.cc | 10 +++---- .../odbc_impl/ODBCDescriptor.h | 4 +++ .../include/odbcabstraction/spi/result_set.h | 2 +- .../include/odbcabstraction/types.h | 6 +++++ .../odbc_impl/ODBCStatement.cc | 2 +- 32 files changed, 116 insertions(+), 67 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc index 9d5985e261683..4cbd3e97e771f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc @@ -18,9 +18,10 @@ using namespace odbcabstraction; namespace { -inline void MoveSingleCellToBinaryBuffer(ColumnBinding *binding, +inline RowStatus MoveSingleCellToBinaryBuffer(ColumnBinding *binding, BinaryArray *array, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { + RowStatus result = odbcabstraction::RowStatus_SUCCESS; const char *value = array->Value(i).data(); size_t size_in_bytes = array->value_length(i); @@ -35,6 +36,7 @@ inline void MoveSingleCellToBinaryBuffer(ColumnBinding *binding, 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; @@ -46,6 +48,8 @@ inline void MoveSingleCellToBinaryBuffer(ColumnBinding *binding, if (binding->strlen_buffer) { binding->strlen_buffer[i] = static_cast(remaining_length); } + + return result; } } // namespace @@ -57,10 +61,10 @@ BinaryArrayFlightSqlAccessor::BinaryArrayFlightSqlAccessor( BinaryArrayFlightSqlAccessor>(array) {} template <> -void BinaryArrayFlightSqlAccessor::MoveSingleCell_impl( +RowStatus BinaryArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, BinaryArray *array, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { - MoveSingleCellToBinaryBuffer(binding, array, i, value_offset, update_value_offset, diagnostics); + return MoveSingleCellToBinaryBuffer(binding, array, i, value_offset, update_value_offset, diagnostics); } template diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h index 9bbc5e53aa910..d76fb9506ebdb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h @@ -23,8 +23,9 @@ class BinaryArrayFlightSqlAccessor public: explicit BinaryArrayFlightSqlAccessor(Array *array); - void MoveSingleCell_impl(ColumnBinding *binding, BinaryArray *array, - int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); + RowStatus MoveSingleCell_impl(ColumnBinding *binding, BinaryArray *array, + int64_t i, int64_t &value_offset, bool update_value_offset, + odbcabstraction::Diagnostics &diagnostics); size_t GetCellLength_impl(ColumnBinding *binding) const; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc index c1fafb4de2f07..61a7ba2a2cb94 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor_test.cc @@ -32,7 +32,7 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Basic) { int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(values[i].length(), strlen_buffer[i]); @@ -69,7 +69,7 @@ TEST(BinaryArrayAccessor, Test_CDataType_BINARY_Truncation) { do { diagnostics.Clear(); int64_t original_value_offset = value_offset; - ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, true, diagnostics)); + ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, true, diagnostics, nullptr)); ASSERT_EQ(values[0].length() - original_value_offset, strlen_buffer[0]); int64_t chunk_length = 0; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc index 534e8e2ffb16a..12efc79f0eeb1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc @@ -19,7 +19,7 @@ BooleanArrayFlightSqlAccessor::BooleanArrayFlightSqlAccessor( BooleanArrayFlightSqlAccessor>(array) {} template -void BooleanArrayFlightSqlAccessor::MoveSingleCell_impl( +RowStatus BooleanArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, BooleanArray *array, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { typedef unsigned char c_type; @@ -31,6 +31,8 @@ void BooleanArrayFlightSqlAccessor::MoveSingleCell_impl( if (binding->strlen_buffer) { binding->strlen_buffer[i] = static_cast(GetCellLength_impl(binding)); } + + return odbcabstraction::RowStatus_SUCCESS; } template diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h index 9a7ef0a793b8f..ec719c28ce28c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h @@ -24,7 +24,7 @@ class BooleanArrayFlightSqlAccessor public: explicit BooleanArrayFlightSqlAccessor(Array *array); - void MoveSingleCell_impl(ColumnBinding *binding, BooleanArray *array, + RowStatus MoveSingleCell_impl(ColumnBinding *binding, BooleanArray *array, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); size_t GetCellLength_impl(ColumnBinding *binding) const; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc index bce7e4411547e..c4f22c121eaa6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor_test.cc @@ -29,7 +29,7 @@ TEST(BooleanArrayFlightSqlAccessor, Test_BooleanArray_CDataType_BIT) { int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(unsigned char), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc index 30bbdde4180bf..e7312a8521644 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc @@ -45,7 +45,7 @@ DateArrayFlightSqlAccessor< array) {} template -void DateArrayFlightSqlAccessor::MoveSingleCell_impl( +RowStatus DateArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { typedef unsigned char c_type; @@ -62,6 +62,8 @@ void DateArrayFlightSqlAccessor::MoveSingleCell_impl( if (binding->strlen_buffer) { binding->strlen_buffer[cell_counter] = static_cast(GetCellLength_impl(binding)); } + + return odbcabstraction::RowStatus_SUCCESS; } template diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h index 764a6754a9558..9dcdb33008897 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h @@ -25,7 +25,7 @@ class DateArrayFlightSqlAccessor public: explicit DateArrayFlightSqlAccessor(Array *array); - void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, + RowStatus MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc index 01a247e34e751..a590a13c91aee 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc @@ -33,7 +33,7 @@ TEST(DateArrayAccessor, Test_Date32Array_CDataType_DATE) { int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (size_t i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(DATE_STRUCT), strlen_buffer[i]); @@ -65,7 +65,7 @@ TEST(DateArrayAccessor, Test_Date64Array_CDataType_DATE) { int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (size_t i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(DATE_STRUCT), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc index 79058df48e0c8..680cff46ca9aa 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc @@ -35,7 +35,7 @@ DecimalArrayFlightSqlAccessor::DecimalArrayFlightSqlAc } template <> -void DecimalArrayFlightSqlAccessor::MoveSingleCell_impl( +RowStatus DecimalArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, Decimal128Array *array, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { auto result = &(static_cast(binding->buffer)[i]); @@ -69,6 +69,8 @@ void DecimalArrayFlightSqlAccessor::MoveSing if (binding->strlen_buffer) { binding->strlen_buffer[i] = static_cast(GetCellLength_impl(binding)); } + + return odbcabstraction::RowStatus_SUCCESS; } template diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h index 5cf787e88cb89..751ce5ca5bba9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h @@ -25,9 +25,9 @@ class DecimalArrayFlightSqlAccessor public: explicit DecimalArrayFlightSqlAccessor(Array *array); - void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, - int64_t i, int64_t &value_offset, bool update_value_offset, - odbcabstraction::Diagnostics &diagnostics); + RowStatus MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, + int64_t i, int64_t &value_offset, bool update_value_offset, + odbcabstraction::Diagnostics &diagnostics); size_t GetCellLength_impl(ColumnBinding *binding) const; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc index 19bdccb62f36b..4245a6229998c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc @@ -67,7 +67,7 @@ void AssertNumericOutput(int input_precision, int input_scale, const std::vector int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(NUMERIC_STRUCT), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc index 11a66aacf63be..25dd0210d5b4a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc @@ -23,7 +23,8 @@ template size_t PrimitiveArrayFlightSqlAccessor::GetColumnarData_impl( const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics, + uint16_t* row_status_array) { return CopyFromArrayValuesToBinding(sliced_array, binding); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h index ccc530903d834..3d7fdfde921ff 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h @@ -29,7 +29,8 @@ class PrimitiveArrayFlightSqlAccessor size_t GetColumnarData_impl(const std::shared_ptr &sliced_array, ColumnBinding *binding, int64_t &value_offset, - bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); + bool update_value_offset, odbcabstraction::Diagnostics &diagnostics, + uint16_t* row_status_array); size_t GetCellLength_impl(ColumnBinding *binding) const; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc index 6ee4555dfbffd..ed87eaad5ae28 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor_test.cc @@ -36,7 +36,7 @@ void TestPrimitiveArraySqlAccessor() { int64_t value_offset = 0; driver::odbcabstraction::Diagnostics diagnostics("Dummy", "Dummy", odbcabstraction::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(c_type), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc index 6162ff84a5128..d06421e2c72d6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -17,12 +17,13 @@ using namespace odbcabstraction; namespace { template -inline void MoveSingleCellToCharBuffer(CharToWStrConverter *converter, +inline RowStatus MoveSingleCellToCharBuffer(CharToWStrConverter *converter, ColumnBinding *binding, StringArray *array, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { + RowStatus result = odbcabstraction::RowStatus_SUCCESS; const char *raw_value = array->Value(i).data(); const void *value; @@ -54,6 +55,7 @@ inline void MoveSingleCellToCharBuffer(CharToWStrConverter *converter, value_offset = -1; } } else { + result = odbcabstraction::RowStatus_SUCCESS_WITH_INFO; diagnostics.AddTruncationWarning(); size_t chars_written = binding->buffer_length / sizeof(CHAR_TYPE); // If we failed to even write one char, the buffer is too small to hold a @@ -69,6 +71,8 @@ inline void MoveSingleCellToCharBuffer(CharToWStrConverter *converter, if (binding->strlen_buffer) { binding->strlen_buffer[i] = static_cast(remaining_length); } + + return result; } } // namespace @@ -81,18 +85,18 @@ StringArrayFlightSqlAccessor::StringArrayFlightSqlAccessor( converter_() {} template <> -void StringArrayFlightSqlAccessor::MoveSingleCell_impl( +RowStatus StringArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, StringArray *array, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { - MoveSingleCellToCharBuffer(&converter_, binding, array, i, + return MoveSingleCellToCharBuffer(&converter_, binding, array, i, value_offset, update_value_offset, diagnostics); } template <> -void StringArrayFlightSqlAccessor::MoveSingleCell_impl( +RowStatus StringArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, StringArray *array, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { - MoveSingleCellToCharBuffer(&converter_, binding, array, i, + return MoveSingleCellToCharBuffer(&converter_, binding, array, i, value_offset, update_value_offset, diagnostics); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h index 9cde63e3fe47e..bf3f7ce51703e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h @@ -25,7 +25,7 @@ class StringArrayFlightSqlAccessor public: explicit StringArrayFlightSqlAccessor(Array *array); - void MoveSingleCell_impl(ColumnBinding *binding, StringArray *array, + RowStatus MoveSingleCell_impl(ColumnBinding *binding, StringArray *array, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc index d22547993e27a..2fe23f3123064 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc @@ -31,7 +31,7 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Basic) { int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(values[i].length(), strlen_buffer[i]); @@ -63,7 +63,7 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Truncation) { do { diagnostics.Clear(); int64_t original_value_offset = value_offset; - ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, true, diagnostics)); + ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, true, diagnostics, nullptr)); ASSERT_EQ(values[0].length() - original_value_offset, strlen_buffer[0]); ss << buffer.data(); @@ -89,7 +89,7 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Basic) { int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (int i = 0; i < values.size(); ++i) { ASSERT_EQ(values[i].length() * sizeof(SqlWChar), strlen_buffer[i]); @@ -123,7 +123,7 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Truncation) { driver::odbcabstraction::Diagnostics diagnostics("Dummy", "Dummy", odbcabstraction::V_3); do { int64_t original_value_offset = value_offset; - ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, true, diagnostics)); + ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, true, diagnostics, nullptr)); ASSERT_EQ(values[0].length() * sizeof(SqlWChar) - original_value_offset, strlen_buffer[0]); finalStr += std::basic_string(buffer.data()); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc index c9a3cd909026b..449e2d6f673df 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc @@ -35,7 +35,7 @@ TimeArrayFlightSqlAccessor< array) {} template -void TimeArrayFlightSqlAccessor::MoveSingleCell_impl( +RowStatus TimeArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostic) { typedef unsigned char c_type; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h index d9eb51c2e519d..8b511a8c1bb37 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h @@ -25,7 +25,7 @@ class TimeArrayFlightSqlAccessor public: explicit TimeArrayFlightSqlAccessor(Array *array); - void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, + RowStatus MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostic); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc index 33a1bf6978bf2..9633d94fbd6d1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc @@ -35,7 +35,7 @@ TEST(TEST_TIME32, TIME_WITH_SECONDS) { int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(t32_values.size(), - accessor.GetColumnarData(&binding, 0, t32_values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, t32_values.size(), value_offset, false, diagnostics, nullptr)); for (size_t i = 0; i < t32_values.size(); ++i) { ASSERT_EQ(sizeof(TIME_STRUCT), strlen_buffer[i]); @@ -68,7 +68,7 @@ TEST(TEST_TIME32, TIME_WITH_MILLI) { int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(t32_values.size(), - accessor.GetColumnarData(&binding, 0, t32_values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, t32_values.size(), value_offset, false, diagnostics, nullptr)); for (size_t i = 0; i < t32_values.size(); ++i) { ASSERT_EQ(sizeof(TIME_STRUCT), strlen_buffer[i]); @@ -104,7 +104,7 @@ TEST(TEST_TIME64, TIME_WITH_MICRO) { int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(t64_values.size(), - accessor.GetColumnarData(&binding, 0, t64_values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, t64_values.size(), value_offset, false, diagnostics, nullptr)); for (size_t i = 0; i < t64_values.size(); ++i) { ASSERT_EQ(sizeof(TIME_STRUCT), strlen_buffer[i]); @@ -140,7 +140,7 @@ TEST(TEST_TIME64, TIME_WITH_NANO) { int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(t64_values.size(), - accessor.GetColumnarData(&binding, 0, t64_values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, t64_values.size(), value_offset, false, diagnostics, nullptr)); for (size_t i = 0; i < t64_values.size(); ++i) { ASSERT_EQ(sizeof(TIME_STRUCT), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc index b05e836291d4a..26432c7043674 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc @@ -44,7 +44,7 @@ TimestampArrayFlightSqlAccessor::TimestampArrayFlightSqlAccessor(Ar array->type())) {} template -void +RowStatus TimestampArrayFlightSqlAccessor::MoveSingleCell_impl(ColumnBinding *binding, TimestampArray *array, int64_t cell_counter, @@ -72,6 +72,8 @@ TimestampArrayFlightSqlAccessor::MoveSingleCell_impl(ColumnBinding if (binding->strlen_buffer) { binding->strlen_buffer[cell_counter] = static_cast(GetCellLength_impl(binding)); } + + return odbcabstraction::RowStatus_SUCCESS; } template diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h index 2089260dfff24..e7daba00eea8f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h @@ -24,7 +24,7 @@ class TimestampArrayFlightSqlAccessor public: explicit TimestampArrayFlightSqlAccessor(Array *array); - void MoveSingleCell_impl(ColumnBinding *binding, TimestampArray *array, int64_t cell_counter, + RowStatus MoveSingleCell_impl(ColumnBinding *binding, TimestampArray *array, int64_t cell_counter, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc index eff18a7e46ed1..93b860ae74a8e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc @@ -35,7 +35,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MILI) { ColumnBinding binding(CDataType_TIMESTAMP, 0, 0, buffer.data(), 0, strlen_buffer.data()); odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (size_t i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); @@ -75,7 +75,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_SECONDS) { odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (size_t i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); @@ -113,7 +113,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MICRO) { odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (size_t i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); @@ -152,7 +152,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_NANO) { odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics)); + accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (size_t i = 0; i < values.size(); ++i) { ASSERT_EQ(sizeof(TIMESTAMP_STRUCT), strlen_buffer[i]); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h index cff8bebf50bc2..192770c99675d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h @@ -14,6 +14,7 @@ #include #include #include +#include "odbcabstraction/types.h" namespace driver { namespace flight_sql { @@ -53,7 +54,7 @@ class Accessor { /// \brief Populates next cells virtual size_t GetColumnarData(ColumnBinding *binding, int64_t starting_row, size_t cells, int64_t &value_offset, bool update_value_offset, - odbcabstraction::Diagnostics &diagnostics) = 0; + odbcabstraction::Diagnostics &diagnostics, uint16_t* row_status_array) = 0; virtual size_t GetCellLength(ColumnBinding *binding) const = 0; }; @@ -67,13 +68,13 @@ class FlightSqlAccessor : public Accessor { size_t GetColumnarData(ColumnBinding *binding, int64_t starting_row, size_t cells, int64_t &value_offset, bool update_value_offset, - odbcabstraction::Diagnostics &diagnostics) override { + odbcabstraction::Diagnostics &diagnostics, uint16_t* row_status_array) override { const std::shared_ptr &array = array_->Slice(starting_row, static_cast(cells)); return GetColumnarData( arrow::internal::checked_pointer_cast(array), binding, - value_offset, update_value_offset, diagnostics); + value_offset, update_value_offset, diagnostics, row_status_array); } size_t GetCellLength(ColumnBinding *binding) const override { @@ -85,14 +86,14 @@ class FlightSqlAccessor : public Accessor { size_t GetColumnarData(const std::shared_ptr &sliced_array, ColumnBinding *binding, int64_t &value_offset, bool update_value_offset, - odbcabstraction::Diagnostics &diagnostics) { + odbcabstraction::Diagnostics &diagnostics, uint16_t* row_status_array) { return static_cast(this)->GetColumnarData_impl( - sliced_array, binding, value_offset, update_value_offset, diagnostics); + sliced_array, binding, value_offset, update_value_offset, diagnostics, row_status_array); } size_t GetColumnarData_impl(const std::shared_ptr &sliced_array, ColumnBinding *binding, int64_t &value_offset, bool update_value_offset, - odbcabstraction::Diagnostics &diagnostics) { + odbcabstraction::Diagnostics &diagnostics, uint16_t* row_status_array) { int64_t length = sliced_array->length(); for (int64_t i = 0; i < length; ++i) { if (sliced_array->IsNull(i)) { @@ -104,21 +105,25 @@ class FlightSqlAccessor : public Accessor { } else { // TODO: Optimize this by creating different versions of MoveSingleCell // depending on if strlen_buffer is null. - MoveSingleCell(binding, sliced_array.get(), i, value_offset, update_value_offset, - diagnostics); + auto row_status = MoveSingleCell(binding, sliced_array.get(), i, value_offset, update_value_offset, + diagnostics); + if (row_status_array) { + row_status_array[i] = row_status; + } } } return length; } - void MoveSingleCell(ColumnBinding *binding, ARROW_ARRAY *array, int64_t i, - int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { + odbcabstraction::RowStatus MoveSingleCell(ColumnBinding *binding, ARROW_ARRAY *array, int64_t i, + int64_t &value_offset, bool update_value_offset, + odbcabstraction::Diagnostics &diagnostics) { return static_cast(this)->MoveSingleCell_impl(binding, array, i, value_offset, update_value_offset, diagnostics); } - void MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, + odbcabstraction::RowStatus MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { std::stringstream ss; ss << "Unknown type conversion from StringArray to target C type " diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index bac5fc2d78678..0763b9c24015a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -14,6 +14,7 @@ #include "flight_sql_result_set_column.h" #include "flight_sql_result_set_metadata.h" #include "utils.h" +#include "odbcabstraction/types.h" namespace driver { namespace flight_sql { @@ -52,7 +53,7 @@ FlightSqlResultSet::FlightSqlResultSet( ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema_)); } -size_t FlightSqlResultSet::Move(size_t rows) { +size_t FlightSqlResultSet::Move(size_t rows, uint16_t *row_status_array) { // Consider it might be the first call to Move() and current_chunk is not // populated yet assert(rows > 0); @@ -104,9 +105,22 @@ size_t FlightSqlResultSet::Move(size_t rows) { auto *accessor = column.GetAccessorForBinding(); ColumnBinding shifted_binding = column.binding; shifted_binding.buffer = static_cast(shifted_binding.buffer) + accessor->GetCellLength(&shifted_binding) * fetched_rows; + uint16_t *shifted_row_status_array = row_status_array ? &row_status_array[fetched_rows] : nullptr; - size_t accessor_rows = accessor->GetColumnarData( - &shifted_binding, current_row_, rows_to_fetch, value_offset, false, diagnostics_); + if (shifted_row_status_array) { + std::fill(shifted_row_status_array, &shifted_row_status_array[rows_to_fetch], odbcabstraction::RowStatus_SUCCESS); + } + + size_t accessor_rows; + try { + accessor_rows = accessor->GetColumnarData(&shifted_binding, current_row_, rows_to_fetch, value_offset, false, + diagnostics_, shifted_row_status_array); + } catch (std::exception &err) { + if (shifted_row_status_array) { + std::fill(shifted_row_status_array, &shifted_row_status_array[rows_to_fetch], odbcabstraction::RowStatus_ERROR); + } + throw err; + } if (rows_to_fetch != accessor_rows) { throw DriverException( @@ -151,7 +165,8 @@ bool FlightSqlResultSet::GetData(int column_n, int16_t target_type, // Note: current_row_ is always positioned at the index _after_ the one we are // on after calling Move(). So if we want to get data from the _last_ row // fetched, we need to subtract one from the current row. - accessor->GetColumnarData(&binding, current_row_ - 1, 1, value_offset, true, diagnostics_); + // TODO: Should GetData update row status array? + accessor->GetColumnarData(&binding, current_row_ - 1, 1, value_offset, true, diagnostics_, nullptr); // If there was truncation, the converter would have reported it to the diagnostics. return diagnostics_.HasWarning(); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index 73c127e55b495..0a43821936a90 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -71,7 +71,7 @@ class FlightSqlResultSet : public ResultSet { void *buffer, size_t buffer_length, ssize_t *strlen_buffer) override; - size_t Move(size_t rows) override; + size_t Move(size_t rows, uint16_t *row_status_array) override; std::shared_ptr GetArrayForColumn(int column); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 59c26ff3311ac..5e3b54da9d07e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -53,7 +53,7 @@ void TestBindColumn(const std::shared_ptr &connection) { size_t total = 0; while (true) { - size_t fetched_rows = result_set->Move(batch_size); + size_t fetched_rows = result_set->Move(batch_size, nullptr); std::cout << "Fetched " << fetched_rows << " rows." << std::endl; total += fetched_rows; @@ -79,7 +79,7 @@ void TestGetData(const std::shared_ptr &connection) { std::cout << metadata->GetDataType(1) << std::endl; - while (result_set->Move(1) == 1) { + while (result_set->Move(1, nullptr) == 1) { driver::odbcabstraction::NUMERIC_STRUCT result; ssize_t result_length; result_set->GetData(1, driver::odbcabstraction::CDataType_NUMERIC, 0, 0, @@ -127,7 +127,7 @@ void TestBindColumnBigInt(const std::shared_ptr &connection) { size_t total = 0; while (true) { - size_t fetched_rows = result_set->Move(batch_size); + size_t fetched_rows = result_set->Move(batch_size, nullptr); std::cout << "Fetched " << fetched_rows << " rows." << std::endl; total += fetched_rows; @@ -153,7 +153,7 @@ void TestGetTablesV2(const std::shared_ptr &connection) { result_set->GetMetadata(); size_t column_count = metadata->GetColumnCount(); - while (result_set->Move(1) == 1) { + while (result_set->Move(1, nullptr) == 1) { int buffer_length = 1024; std::vector result(buffer_length); ssize_t result_length; @@ -180,7 +180,7 @@ void TestGetColumnsV3(const std::shared_ptr &connection) { std::vector result(buffer_length); ssize_t result_length; - while (result_set->Move(1) == 1) { + while (result_set->Move(1, nullptr) == 1) { for (int i = 0; i < column_count; ++i) { result_set->GetData(1 + i, driver::odbcabstraction::CDataType_CHAR, 0, 0, result.data(), buffer_length, &result_length); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h index b29cec75c64b2..77c80df9bbecd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h @@ -112,6 +112,10 @@ namespace ODBC return m_arraySize; } + inline SQLUSMALLINT* GetArrayStatusPtr() { + return m_arrayStatusPtr; + } + inline void SetRowsProcessed(SQLULEN rows) { if (m_rowsProccessedPtr) { *m_rowsProccessedPtr = rows; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h index 59e47fca50508..107a3900085ab 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h @@ -58,7 +58,7 @@ class ResultSet { /// /// \param rows The maximum number of rows to be fetched. /// \returns The number of rows fetched. - virtual size_t Move(size_t rows) = 0; + virtual size_t Move(size_t rows, uint16_t *row_status_array) = 0; /// \brief Populates `buffer` with the value on current row for given column. /// If the value doesn't fit the buffer this method returns true and diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 112f12d4fb1bf..856f6deee597d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -155,5 +155,11 @@ typedef struct tagNUMERIC_STRUCT { uint8_t val[16]; //[e], [f] } NUMERIC_STRUCT; +enum RowStatus: uint16_t { + RowStatus_SUCCESS = 0, // Same as SQL_ROW_SUCCESS + RowStatus_SUCCESS_WITH_INFO = 6, // Same as SQL_ROW_SUCCESS_WITH_INFO + RowStatus_ERROR = 5 // Same as SQL_ROW_ERROR +}; + } // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc index b92babe3ac313..12d26b19894de 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc @@ -309,7 +309,7 @@ bool ODBCStatement::Fetch(size_t rows) { m_currentArd->NotifyBindingsHavePropagated(); } - size_t rowsFetched = m_currenResult->Move(rows); + size_t rowsFetched = m_currenResult->Move(rows, m_ird->GetArrayStatusPtr()); m_ird->SetRowsProcessed(static_cast(rowsFetched)); m_rowNumber += rowsFetched; From 05c9130db3a35e767ccc0eed28b9766011f69990 Mon Sep 17 00:00:00 2001 From: James Duong Date: Sun, 19 Jun 2022 17:51:57 -0700 Subject: [PATCH 134/183] Fix build break in row status changes - Fix time accessor to return a status - Fix build warnings introduced Change-Id: I0f9776dbaa523ae683589b68dc6605f8e2b57fcb --- .../flight_sql/accessors/time_array_accessor.cc | 1 + .../flightsql-odbc/flight_sql/flight_sql_result_set.cc | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc index 449e2d6f673df..a740463cac5e1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc @@ -59,6 +59,7 @@ RowStatus TimeArrayFlightSqlAccessor::MoveSingleCell_i if (binding->strlen_buffer) { binding->strlen_buffer[cell_counter] = static_cast(GetCellLength_impl(binding)); } + return odbcabstraction::RowStatus_SUCCESS; } template diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index 0763b9c24015a..0730d731eafa5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -100,8 +100,6 @@ size_t FlightSqlResultSet::Move(size_t rows, uint16_t *row_status_array) { if (!column.is_bound) continue; - int64_t value_offset = 0; - auto *accessor = column.GetAccessorForBinding(); ColumnBinding shifted_binding = column.binding; shifted_binding.buffer = static_cast(shifted_binding.buffer) + accessor->GetCellLength(&shifted_binding) * fetched_rows; @@ -113,13 +111,14 @@ size_t FlightSqlResultSet::Move(size_t rows, uint16_t *row_status_array) { size_t accessor_rows; try { + int64_t value_offset = 0; accessor_rows = accessor->GetColumnarData(&shifted_binding, current_row_, rows_to_fetch, value_offset, false, diagnostics_, shifted_row_status_array); - } catch (std::exception &err) { + } catch (...) { if (shifted_row_status_array) { std::fill(shifted_row_status_array, &shifted_row_status_array[rows_to_fetch], odbcabstraction::RowStatus_ERROR); } - throw err; + throw; } if (rows_to_fetch != accessor_rows) { From 898afc2e98fb77c6425cc6c3cd9aa9c4002e541f Mon Sep 17 00:00:00 2001 From: James Duong Date: Sun, 19 Jun 2022 21:44:17 -0700 Subject: [PATCH 135/183] Fix re-use of statement after SQLCloseCursor Correctly reset of the state of the ODBC Statement after SQLCloseCursor and notify the abstraction that it will need to re-initialize bindings the next time SQLFetch is called. Change-Id: I2e88f6c53c62019404d44960ce5eccf33af42d1f --- .../include/odbcabstraction/odbc_impl/ODBCDescriptor.h | 4 ++++ .../odbcabstraction/odbc_impl/ODBCStatement.cc | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h index 77c80df9bbecd..b51c4630c30c0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h @@ -126,6 +126,10 @@ namespace ODBC m_hasBindingsChanged = false; } + void NotifyBindingsHaveChanged() { + m_hasBindingsChanged = true; + } + private: driver::odbcabstraction::Diagnostics m_diagnostics; std::vector m_registeredOnStatementsAsApd; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc index 12d26b19894de..7529146043dbf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc @@ -633,6 +633,11 @@ void ODBCStatement::closeCursor(bool suppressErrors) { m_currenResult->Close(); m_currenResult = nullptr; } + + // Reset the fetching state of this statement. + m_currentArd->NotifyBindingsHaveChanged(); + m_rowNumber = 0; + m_hasReachedEndOfResult = false; } bool ODBCStatement::GetData(SQLSMALLINT recordNumber, SQLSMALLINT cType, SQLPOINTER dataPtr, SQLLEN bufferLength, SQLLEN* indicatorPtr) { From 5dc3cd0e85a291eb59a31d313cbb6177ffd684aa Mon Sep 17 00:00:00 2001 From: James Duong Date: Sun, 19 Jun 2022 22:01:40 -0700 Subject: [PATCH 136/183] Fix rows missing data when using block fetching Fix incorrect skipping of converting rows. For primitive types, do not rely on the buffer length and instead convert all rows since the array is already sliced to match the ODBC array. Change-Id: Iaec332946f09d4bc533884739f52bb5ed73880ac --- .../flightsql-odbc/flight_sql/accessors/common.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h index c1f1aa6d809c0..554dc46173c49 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h @@ -44,10 +44,11 @@ inline size_t CopyFromArrayValuesToBinding(const std::shared_ptr &array, } } + // Copy the entire array to the bound ODBC buffers. + // Note that the array should already have been sliced down to the same number + // of elements in the ODBC data array by the point in which this function is called. const auto *values = typed_array->raw_values(); - size_t value_length = - std::min(static_cast(length), binding->buffer_length); - memcpy(binding->buffer, values, element_size * value_length); + memcpy(binding->buffer, values, element_size * length); return length; } From 1eba60c18c2ee9b18abcc86333e4bfa11a6f2b21 Mon Sep 17 00:00:00 2001 From: jvictorhuguenin Date: Tue, 14 Jun 2022 17:03:40 -0300 Subject: [PATCH 137/183] Implement Precision and Scale on the driver side Change-Id: I7ec9edef561899956f5cc3cd4ec85659c0b66cd6 --- .../flight_sql_result_set_metadata.cc | 18 +++- .../flightsql-odbc/flight_sql/utils.cc | 85 ++++++++++++++++++- .../flightsql-odbc/flight_sql/utils.h | 6 ++ 3 files changed, 102 insertions(+), 7 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index 61116eb427db5..b52478f64418a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -49,13 +49,23 @@ std::string FlightSqlResultSetMetadata::GetName(int column_position) { } size_t FlightSqlResultSetMetadata::GetPrecision(int column_position) { - arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); - return metadata.GetPrecision().ValueOrElse([] { return 0; }); + const std::shared_ptr &field = schema_->field(column_position - 1); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); + + int32_t column_size = metadata.GetPrecision().ValueOrElse([] { return 0; }); + SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + + return GetColumnSize(data_type_v3, column_size).value_or(0); } size_t FlightSqlResultSetMetadata::GetScale(int column_position) { - arrow::flight::sql::ColumnMetadata metadata = GetMetadata(schema_->field(column_position - 1)); - return metadata.GetScale().ValueOrElse([] { return 0; }); + const std::shared_ptr &field = schema_->field(column_position - 1); + arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); + + int32_t type_scale = metadata.GetScale().ValueOrElse([] { return 0; }); + SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + + return GetTypeScale(data_type_v3, type_scale).value_or(0); } uint16_t FlightSqlResultSetMetadata::GetDataType(int column_position) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 997341e2bde4f..ef06928d14005 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -332,6 +332,85 @@ optional GetCharOctetLength(SqlDataType data_type, return arrow::util::nullopt; } } +optional GetTypeScale(SqlDataType data_type, + const optional& type_scale) { + switch (data_type) { + case SqlDataType_TYPE_TIMESTAMP: + case SqlDataType_TYPE_TIME: + return 3; + case SqlDataType_DECIMAL: + return type_scale; + case SqlDataType_NUMERIC: + return type_scale; + case SqlDataType_TINYINT: + case SqlDataType_SMALLINT: + case SqlDataType_INTEGER: + case SqlDataType_BIGINT: + return 0; + default: + return arrow::util::nullopt; + } +} +optional GetColumnSize(SqlDataType data_type, + const optional& column_size) { + switch (data_type) { + case SqlDataType_CHAR: + case SqlDataType_VARCHAR: + case SqlDataType_LONGVARCHAR: + return column_size; + case SqlDataType_WCHAR: + case SqlDataType_WVARCHAR: + case SqlDataType_WLONGVARCHAR: + return column_size.has_value() ? arrow::util::make_optional(column_size.value() * sizeof(SqlWChar)) + : arrow::util::nullopt; + case SqlDataType_BINARY: + case SqlDataType_VARBINARY: + case SqlDataType_LONGVARBINARY: + return column_size; + case SqlDataType_DECIMAL: + return 19; // The same as sizeof(SQL_NUMERIC_STRUCT) + case SqlDataType_NUMERIC: + return 19; // The same as sizeof(SQL_NUMERIC_STRUCT) + case SqlDataType_BIT: + case SqlDataType_TINYINT: + return 1; + case SqlDataType_SMALLINT: + return 2; + case SqlDataType_INTEGER: + return 4; + case SqlDataType_BIGINT: + return 8; + case SqlDataType_REAL: + return 4; + case SqlDataType_FLOAT: + case SqlDataType_DOUBLE: + return 8; + case SqlDataType_TYPE_DATE: + return 10; // The same as sizeof(SQL_DATE_STRUCT) + case SqlDataType_TYPE_TIME: + return 12; // The same as sizeof(SQL_TIME_STRUCT) + case SqlDataType_TYPE_TIMESTAMP: + return 23; // The same as sizeof(SQL_TIME_STRUCT) + case SqlDataType_INTERVAL_MONTH: + case SqlDataType_INTERVAL_YEAR: + case SqlDataType_INTERVAL_YEAR_TO_MONTH: + case SqlDataType_INTERVAL_DAY: + case SqlDataType_INTERVAL_HOUR: + case SqlDataType_INTERVAL_MINUTE: + case SqlDataType_INTERVAL_SECOND: + case SqlDataType_INTERVAL_DAY_TO_HOUR: + case SqlDataType_INTERVAL_DAY_TO_MINUTE: + case SqlDataType_INTERVAL_DAY_TO_SECOND: + case SqlDataType_INTERVAL_HOUR_TO_MINUTE: + case SqlDataType_INTERVAL_HOUR_TO_SECOND: + case SqlDataType_INTERVAL_MINUTE_TO_SECOND: + return 28; // The same as sizeof(SQL_INTERVAL_STRUCT) + case SqlDataType_GUID: + return 16; + default: + return arrow::util::nullopt; + } +} optional GetBufferLength(SqlDataType data_type, const optional& column_size) { @@ -368,11 +447,11 @@ optional GetBufferLength(SqlDataType data_type, case SqlDataType_DOUBLE: return 8; case SqlDataType_TYPE_DATE: - return 6; // The same as sizeof(SQL_DATE_STRUCT) + return 10; // The same as sizeof(SQL_DATE_STRUCT) case SqlDataType_TYPE_TIME: - return 6; // The same as sizeof(SQL_TIME_STRUCT) + return 12; // The same as sizeof(SQL_TIME_STRUCT) case SqlDataType_TYPE_TIMESTAMP: - return 16; // The same as sizeof(SQL_TIME_STRUCT) + return 23; // The same as sizeof(SQL_TIME_STRUCT) case SqlDataType_INTERVAL_MONTH: case SqlDataType_INTERVAL_YEAR: case SqlDataType_INTERVAL_YEAR_TO_MONTH: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index b0aead1d74670..7c3994cd86abd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -79,6 +79,12 @@ optional GetCharOctetLength(odbcabstraction::SqlDataType data_type, optional GetBufferLength(odbcabstraction::SqlDataType data_type, const optional& column_size); +optional GetTypeScale(odbcabstraction::SqlDataType data_type, + const optional& type_scale); + +optional GetColumnSize(odbcabstraction::SqlDataType data_type, + const optional& column_size); + optional GetDisplaySize(odbcabstraction::SqlDataType data_type, const optional& column_size); From 36dea8341527ffa6d602ba481958edd9735d5ca7 Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 20 Jun 2022 05:44:22 -0700 Subject: [PATCH 138/183] Fix misuse of bind offset ptr - The bind offset pointer should not be used for the indicator pointer if it is null. - The bind offset pointer is always a SQLULEN instead of SQLLEN Note that SQL_DESC_BIND_OFFSET_PTR is not supposed to work with SQLExtendedFetch, however we allow for it anyway because Power Pivot uses it. Change-Id: I7379a68730f62a0208935a9733bdb091b80e1577 --- .../include/odbcabstraction/odbc_impl/ODBCDescriptor.h | 2 +- .../flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h index b51c4630c30c0..04006f64202da 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h @@ -138,7 +138,7 @@ namespace ODBC ODBCConnection* m_owningConnection; ODBCStatement* m_parentStatement; SQLUSMALLINT* m_arrayStatusPtr; - SQLLEN* m_bindOffsetPtr; + SQLULEN* m_bindOffsetPtr; SQLULEN* m_rowsProccessedPtr; SQLULEN m_arraySize; SQLINTEGER m_bindType; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc index 7529146043dbf..ca1189ca68309 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc @@ -301,7 +301,7 @@ bool ODBCStatement::Fetch(size_t rows) { ardRecord.m_scale, reinterpret_cast(ardRecord.m_dataPtr) + bindOffset, GetLength(ardRecord), reinterpret_cast( - reinterpret_cast(ardRecord.m_indicatorPtr) + bindOffset)); + ardRecord.m_indicatorPtr ? reinterpret_cast(ardRecord.m_indicatorPtr) + bindOffset : nullptr)); } else { m_currenResult->BindColumn(i+1, CDataType_CHAR /* arbitrary type, not used */, 0, 0, nullptr, 0, nullptr); } From 67bcf9b5dabc8a1c1e5cc4f279239e1e49da95d5 Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 20 Jun 2022 06:34:25 -0700 Subject: [PATCH 139/183] Fix incorrect SQLGetData iteration when buffer length is zero Fix bug where the internal offset tracked for SQLGetData would be negative if the application passed in a zero buffer length since it would previously assume the NUL terminator got written. Power Pivot relies on this behaviour. Change-Id: I63e0d037bd0429ecb8cecfd063b41c0e96c4d2e7 --- .../flight_sql/accessors/string_array_accessor.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc index d06421e2c72d6..f28b81a0c4e2b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -62,9 +62,9 @@ inline RowStatus MoveSingleCellToCharBuffer(CharToWStrConverter *converter, // NUL-terminator. if (chars_written > 0) { char_buffer[(chars_written - 1)] = '\0'; - } - if (update_value_offset) { - value_offset += binding->buffer_length - sizeof(CHAR_TYPE); + if (update_value_offset) { + value_offset += binding->buffer_length - sizeof(CHAR_TYPE); + } } } From 8c03d5969145feedd4f240387518f9e12338d6bd Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 20 Jun 2022 14:46:20 -0700 Subject: [PATCH 140/183] Make SQL_ROW_BIND_OFFSET_PTR lazily evaluated Evaluate and use the row bind offset pointer at the point in which bindings have an effect, not when it was last set. The application is allowed to set SQL_ROW_BIND_OFFSET_PTR to a pointer, change the value that is being pointed at, then fetch data. Power Pivot does this. Fix a bug where the indicator pointer was being offset when an arrow result partially fills the request for data. Set the row status array to SQL_ROW_NOROW for array entries that didn't get fetched into. Change-Id: I945d568e89914a4d0fcdcb7fdbc62b859a268a61 --- .../flight_sql/flight_sql_result_set.cc | 19 +++++++++++++++++-- .../flight_sql/flight_sql_result_set.h | 2 +- .../flightsql-odbc/flight_sql/main.cc | 10 +++++----- .../include/odbcabstraction/spi/result_set.h | 4 +++- .../include/odbcabstraction/types.h | 3 ++- .../odbc_impl/ODBCStatement.cc | 7 +++---- 6 files changed, 31 insertions(+), 14 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index 0730d731eafa5..6954d0ffd4bd9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -53,7 +53,7 @@ FlightSqlResultSet::FlightSqlResultSet( ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema_)); } -size_t FlightSqlResultSet::Move(size_t rows, uint16_t *row_status_array) { +size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, uint16_t *row_status_array) { // Consider it might be the first call to Move() and current_chunk is not // populated yet assert(rows > 0); @@ -102,7 +102,19 @@ size_t FlightSqlResultSet::Move(size_t rows, uint16_t *row_status_array) { auto *accessor = column.GetAccessorForBinding(); ColumnBinding shifted_binding = column.binding; - shifted_binding.buffer = static_cast(shifted_binding.buffer) + accessor->GetCellLength(&shifted_binding) * fetched_rows; + if (shifted_binding.buffer) { + shifted_binding.buffer = + static_cast(shifted_binding.buffer) + + accessor->GetCellLength(&shifted_binding) * fetched_rows + + bind_offset; + } + + if (shifted_binding.strlen_buffer) { + shifted_binding.strlen_buffer = reinterpret_cast( + reinterpret_cast( + &shifted_binding.strlen_buffer[fetched_rows]) + + bind_offset); + } uint16_t *shifted_row_status_array = row_status_array ? &row_status_array[fetched_rows] : nullptr; if (shifted_row_status_array) { @@ -131,6 +143,9 @@ size_t FlightSqlResultSet::Move(size_t rows, uint16_t *row_status_array) { fetched_rows += rows_to_fetch; } + if (rows > fetched_rows && row_status_array) { + std::fill(&row_status_array[fetched_rows], &row_status_array[rows], odbcabstraction::RowStatus_NOROW); + } return fetched_rows; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index 0a43821936a90..713b5d94acc1c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -71,7 +71,7 @@ class FlightSqlResultSet : public ResultSet { void *buffer, size_t buffer_length, ssize_t *strlen_buffer) override; - size_t Move(size_t rows, uint16_t *row_status_array) override; + size_t Move(size_t rows, size_t bind_offset, uint16_t *row_status_array) override; std::shared_ptr GetArrayForColumn(int column); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 5e3b54da9d07e..354848cd09d96 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -53,7 +53,7 @@ void TestBindColumn(const std::shared_ptr &connection) { size_t total = 0; while (true) { - size_t fetched_rows = result_set->Move(batch_size, nullptr); + size_t fetched_rows = result_set->Move(batch_size, 0, nullptr); std::cout << "Fetched " << fetched_rows << " rows." << std::endl; total += fetched_rows; @@ -79,7 +79,7 @@ void TestGetData(const std::shared_ptr &connection) { std::cout << metadata->GetDataType(1) << std::endl; - while (result_set->Move(1, nullptr) == 1) { + while (result_set->Move(1, 0, nullptr) == 1) { driver::odbcabstraction::NUMERIC_STRUCT result; ssize_t result_length; result_set->GetData(1, driver::odbcabstraction::CDataType_NUMERIC, 0, 0, @@ -127,7 +127,7 @@ void TestBindColumnBigInt(const std::shared_ptr &connection) { size_t total = 0; while (true) { - size_t fetched_rows = result_set->Move(batch_size, nullptr); + size_t fetched_rows = result_set->Move(batch_size, 0, nullptr); std::cout << "Fetched " << fetched_rows << " rows." << std::endl; total += fetched_rows; @@ -153,7 +153,7 @@ void TestGetTablesV2(const std::shared_ptr &connection) { result_set->GetMetadata(); size_t column_count = metadata->GetColumnCount(); - while (result_set->Move(1, nullptr) == 1) { + while (result_set->Move(1, 0, nullptr) == 1) { int buffer_length = 1024; std::vector result(buffer_length); ssize_t result_length; @@ -180,7 +180,7 @@ void TestGetColumnsV3(const std::shared_ptr &connection) { std::vector result(buffer_length); ssize_t result_length; - while (result_set->Move(1, nullptr) == 1) { + while (result_set->Move(1, 0, nullptr) == 1) { for (int i = 0; i < column_count; ++i) { result_set->GetData(1 + i, driver::odbcabstraction::CDataType_CHAR, 0, 0, result.data(), buffer_length, &result_length); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h index 107a3900085ab..bb70c48c5fb83 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h @@ -57,8 +57,10 @@ class ResultSet { /// will be truncated. /// /// \param rows The maximum number of rows to be fetched. + /// \param bind_offset The offset for bound columns and indicators. + /// \param row_status_array The array to write statuses. /// \returns The number of rows fetched. - virtual size_t Move(size_t rows, uint16_t *row_status_array) = 0; + virtual size_t Move(size_t rows, size_t bind_offset, uint16_t *row_status_array) = 0; /// \brief Populates `buffer` with the value on current row for given column. /// If the value doesn't fit the buffer this method returns true and diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 856f6deee597d..ba9b683e5a01d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -158,7 +158,8 @@ typedef struct tagNUMERIC_STRUCT { enum RowStatus: uint16_t { RowStatus_SUCCESS = 0, // Same as SQL_ROW_SUCCESS RowStatus_SUCCESS_WITH_INFO = 6, // Same as SQL_ROW_SUCCESS_WITH_INFO - RowStatus_ERROR = 5 // Same as SQL_ROW_ERROR + RowStatus_ERROR = 5, // Same as SQL_ROW_ERROR + RowStatus_NOROW = 3 // Same as SQL_ROW_NOROW }; } // namespace odbcabstraction diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc index ca1189ca68309..b8531654e0964 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc @@ -298,10 +298,9 @@ bool ODBCStatement::Fetch(size_t rows) { if (i < m_currentArd->GetRecords().size() && m_currentArd->GetRecords()[i].m_isBound) { const DescriptorRecord& ardRecord = m_currentArd->GetRecords()[i]; m_currenResult->BindColumn(i+1, ardRecord.m_type, ardRecord.m_precision, - ardRecord.m_scale, reinterpret_cast(ardRecord.m_dataPtr) + bindOffset, + ardRecord.m_scale, ardRecord.m_dataPtr, GetLength(ardRecord), - reinterpret_cast( - ardRecord.m_indicatorPtr ? reinterpret_cast(ardRecord.m_indicatorPtr) + bindOffset : nullptr)); + ardRecord.m_indicatorPtr); } else { m_currenResult->BindColumn(i+1, CDataType_CHAR /* arbitrary type, not used */, 0, 0, nullptr, 0, nullptr); } @@ -309,7 +308,7 @@ bool ODBCStatement::Fetch(size_t rows) { m_currentArd->NotifyBindingsHavePropagated(); } - size_t rowsFetched = m_currenResult->Move(rows, m_ird->GetArrayStatusPtr()); + size_t rowsFetched = m_currenResult->Move(rows, m_currentArd->GetBindOffset(), m_ird->GetArrayStatusPtr()); m_ird->SetRowsProcessed(static_cast(rowsFetched)); m_rowNumber += rowsFetched; From 7c387c5c63cccc04ac1fefefaad6869131a49cee Mon Sep 17 00:00:00 2001 From: James Duong Date: Tue, 21 Jun 2022 08:34:34 -0700 Subject: [PATCH 141/183] Implement row-wise binding Support SQL_DESC_BIND_TYPE being a non-zero value to support row-wise bindings. Row-wise binding is required to work with Power Pivot when retrieving only small columns (such as primitive types, and shorter string columns). Change-Id: Ie10e855ed288b66b849e6feb18cef73b1f84d4cb --- .../flight_sql/flight_sql_result_set.cc | 80 ++++++++++++++----- .../flight_sql/flight_sql_result_set.h | 2 +- .../flightsql-odbc/flight_sql/main.cc | 10 +-- .../include/odbcabstraction/spi/result_set.h | 5 +- .../odbc_impl/ODBCStatement.cc | 3 +- 5 files changed, 74 insertions(+), 26 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index 6954d0ffd4bd9..755fb89d095f5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -53,7 +53,7 @@ FlightSqlResultSet::FlightSqlResultSet( ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema_)); } -size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, uint16_t *row_status_array) { +size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, size_t bind_type, uint16_t *row_status_array) { // Consider it might be the first call to Move() and current_chunk is not // populated yet assert(rows > 0); @@ -102,30 +102,73 @@ size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, uint16_t *row_s auto *accessor = column.GetAccessorForBinding(); ColumnBinding shifted_binding = column.binding; - if (shifted_binding.buffer) { - shifted_binding.buffer = - static_cast(shifted_binding.buffer) + - accessor->GetCellLength(&shifted_binding) * fetched_rows + - bind_offset; - } - - if (shifted_binding.strlen_buffer) { - shifted_binding.strlen_buffer = reinterpret_cast( - reinterpret_cast( - &shifted_binding.strlen_buffer[fetched_rows]) + - bind_offset); - } uint16_t *shifted_row_status_array = row_status_array ? &row_status_array[fetched_rows] : nullptr; if (shifted_row_status_array) { std::fill(shifted_row_status_array, &shifted_row_status_array[rows_to_fetch], odbcabstraction::RowStatus_SUCCESS); } - size_t accessor_rows; + size_t accessor_rows = 0; try { - int64_t value_offset = 0; - accessor_rows = accessor->GetColumnarData(&shifted_binding, current_row_, rows_to_fetch, value_offset, false, - diagnostics_, shifted_row_status_array); + if (!bind_type) { + // Columnar binding. Have the accessor convert multiple rows. + if (shifted_binding.buffer) { + shifted_binding.buffer = + static_cast(shifted_binding.buffer) + + accessor->GetCellLength(&shifted_binding) * fetched_rows + + bind_offset; + } + + if (shifted_binding.strlen_buffer) { + shifted_binding.strlen_buffer = reinterpret_cast( + reinterpret_cast( + &shifted_binding.strlen_buffer[fetched_rows]) + + bind_offset); + } + + int64_t value_offset = 0; + accessor_rows = accessor->GetColumnarData(&shifted_binding, current_row_, rows_to_fetch, value_offset, false, + diagnostics_, shifted_row_status_array); + } + else { + // Row-wise binding. Identify the base position of the buffer and indicator based on the bind offset, + // the number of already-fetched rows, and the bind_type holding the size of an application-side row. + if (shifted_binding.buffer) { + shifted_binding.buffer = + static_cast(shifted_binding.buffer) + bind_offset + + bind_type * fetched_rows; + } + + if (shifted_binding.strlen_buffer) { + shifted_binding.strlen_buffer = reinterpret_cast( + reinterpret_cast(shifted_binding.strlen_buffer) + + bind_offset + bind_type * fetched_rows); + } + + // Loop and run the accessor one-row-at-a-time. + for (size_t i = 0; i < rows_to_fetch; ++i) { + int64_t value_offset = 0; + + // Adjust offsets passed to the accessor as we fetch rows. + // Note that current_row_ is updated outside of this loop. + accessor_rows += accessor->GetColumnarData(&shifted_binding, current_row_ + i, 1, value_offset, false, + diagnostics_, shifted_row_status_array); + if (shifted_binding.buffer) { + shifted_binding.buffer = + static_cast(shifted_binding.buffer) + bind_type; + } + + if (shifted_binding.strlen_buffer) { + shifted_binding.strlen_buffer = reinterpret_cast( + reinterpret_cast(shifted_binding.strlen_buffer) + + bind_type); + } + + if (shifted_row_status_array) { + shifted_row_status_array++; + } + } + } } catch (...) { if (shifted_row_status_array) { std::fill(shifted_row_status_array, &shifted_row_status_array[rows_to_fetch], odbcabstraction::RowStatus_ERROR); @@ -133,6 +176,7 @@ size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, uint16_t *row_s throw; } + if (rows_to_fetch != accessor_rows) { throw DriverException( "Expected the same number of rows for all columns"); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index 713b5d94acc1c..94953ad4cc1d7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -71,7 +71,7 @@ class FlightSqlResultSet : public ResultSet { void *buffer, size_t buffer_length, ssize_t *strlen_buffer) override; - size_t Move(size_t rows, size_t bind_offset, uint16_t *row_status_array) override; + size_t Move(size_t rows, size_t bind_offset, size_t bind_type, uint16_t *row_status_array) override; std::shared_ptr GetArrayForColumn(int column); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 354848cd09d96..231f210150572 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -53,7 +53,7 @@ void TestBindColumn(const std::shared_ptr &connection) { size_t total = 0; while (true) { - size_t fetched_rows = result_set->Move(batch_size, 0, nullptr); + size_t fetched_rows = result_set->Move(batch_size, 0, 0, nullptr); std::cout << "Fetched " << fetched_rows << " rows." << std::endl; total += fetched_rows; @@ -79,7 +79,7 @@ void TestGetData(const std::shared_ptr &connection) { std::cout << metadata->GetDataType(1) << std::endl; - while (result_set->Move(1, 0, nullptr) == 1) { + while (result_set->Move(1, 0, 0, nullptr) == 1) { driver::odbcabstraction::NUMERIC_STRUCT result; ssize_t result_length; result_set->GetData(1, driver::odbcabstraction::CDataType_NUMERIC, 0, 0, @@ -127,7 +127,7 @@ void TestBindColumnBigInt(const std::shared_ptr &connection) { size_t total = 0; while (true) { - size_t fetched_rows = result_set->Move(batch_size, 0, nullptr); + size_t fetched_rows = result_set->Move(batch_size, 0, 0, nullptr); std::cout << "Fetched " << fetched_rows << " rows." << std::endl; total += fetched_rows; @@ -153,7 +153,7 @@ void TestGetTablesV2(const std::shared_ptr &connection) { result_set->GetMetadata(); size_t column_count = metadata->GetColumnCount(); - while (result_set->Move(1, 0, nullptr) == 1) { + while (result_set->Move(1, 0, 0, nullptr) == 1) { int buffer_length = 1024; std::vector result(buffer_length); ssize_t result_length; @@ -180,7 +180,7 @@ void TestGetColumnsV3(const std::shared_ptr &connection) { std::vector result(buffer_length); ssize_t result_length; - while (result_set->Move(1, 0, nullptr) == 1) { + while (result_set->Move(1, 0, 0, nullptr) == 1) { for (int i = 0; i < column_count; ++i) { result_set->GetData(1 + i, driver::odbcabstraction::CDataType_CHAR, 0, 0, result.data(), buffer_length, &result_length); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h index bb70c48c5fb83..f706e91a847bd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/result_set.h @@ -58,9 +58,12 @@ class ResultSet { /// /// \param rows The maximum number of rows to be fetched. /// \param bind_offset The offset for bound columns and indicators. + /// \param bind_type The type of binding. Zero indicates columnar binding, non-zero indicates + /// that this holds the size of an application row buffer. This corresponds + /// directly to SQL_DESC_BIND_TYPE in ODBC. /// \param row_status_array The array to write statuses. /// \returns The number of rows fetched. - virtual size_t Move(size_t rows, size_t bind_offset, uint16_t *row_status_array) = 0; + virtual size_t Move(size_t rows, size_t bind_offset, size_t bind_type, uint16_t *row_status_array) = 0; /// \brief Populates `buffer` with the value on current row for given column. /// If the value doesn't fit the buffer this method returns true and diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc index b8531654e0964..317c8610490af 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc @@ -308,7 +308,8 @@ bool ODBCStatement::Fetch(size_t rows) { m_currentArd->NotifyBindingsHavePropagated(); } - size_t rowsFetched = m_currenResult->Move(rows, m_currentArd->GetBindOffset(), m_ird->GetArrayStatusPtr()); + size_t rowsFetched = m_currenResult->Move(rows, m_currentArd->GetBindOffset(), + m_currentArd->GetBoundStructOffset(), m_ird->GetArrayStatusPtr()); m_ird->SetRowsProcessed(static_cast(rowsFetched)); m_rowNumber += rowsFetched; From 7995b25490262c85bfb2cc694f1b21e6894905a4 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Wed, 8 Jun 2022 10:58:44 -0300 Subject: [PATCH 142/183] Add time to timestamp converter. - This patch fix a conversion error that happens when trying to fetch a time data as timestamp. This error could be reproduced when making the explicit conversion or using pyodbc to query a time column Change-Id: I075376bedcef6b0d36101cf2105973696f4d5f35 --- .../flightsql-odbc/flight_sql/utils.cc | 80 +++++++++++- .../flightsql-odbc/flight_sql/utils_test.cc | 123 +++++++++++++++--- .../odbcabstraction/calendar_utils.cc | 15 +++ .../include/odbcabstraction/calendar_utils.h | 2 + 4 files changed, 197 insertions(+), 23 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index ef06928d14005..2b42c2b5085d0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -5,20 +5,40 @@ */ #include "utils.h" -#include -#include + +#include +#include #include + +#include #include +#include #include + +#include "json_converter.h" + #include -#include + #include -#include "json_converter.h" +#include namespace driver { namespace flight_sql { namespace { +int64_t GetTodayTimeFromEpoch() { + tm date{}; + int64_t t = std::time(0); + + odbcabstraction::GetTimeForMillisSinceEpoch(date, t); + + date.tm_hour =0; + date.tm_min =0; + date.tm_sec =0; + + return std::mktime(&date); +} + bool IsComplexType(arrow::Type::type type_id) { switch (type_id) { case arrow::Type::LIST: @@ -774,12 +794,58 @@ ArrayConvertTask GetConverter(arrow::Type::type original_type_id, return CheckConversion(arrow::compute::CallFunction( "cast", {first_converted_array}, &cast_options)); }; + } else if (original_type_id == arrow::Type::TIME32 && + target_type == odbcabstraction::CDataType_TIMESTAMP) { + return [=](const std::shared_ptr &original_array) { + arrow::compute::CastOptions cast_options; + cast_options.to_type = arrow::int32(); + + auto first_converted_array = CheckConversion( + arrow::compute::Cast(original_array, cast_options)); + + cast_options.to_type = arrow::int64(); + + auto second_converted_array = CheckConversion( + arrow::compute::Cast(first_converted_array, cast_options)); + + auto seconds_from_epoch = GetTodayTimeFromEpoch(); + + auto third_converted_array = CheckConversion( + arrow::compute::Add(second_converted_array, std::make_shared(seconds_from_epoch * 1000))); + + arrow::compute::CastOptions cast_options_2; + cast_options_2.to_type = arrow::timestamp(arrow::TimeUnit::MILLI); + + return CheckConversion( + arrow::compute::Cast(third_converted_array, cast_options_2)); + }; + } else if (original_type_id == arrow::Type::TIME64 && + target_type == odbcabstraction::CDataType_TIMESTAMP) { + return [=](const std::shared_ptr &original_array) { + arrow::compute::CastOptions cast_options; + cast_options.to_type = arrow::int64(); + + auto first_converted_array = CheckConversion( + arrow::compute::Cast(original_array, cast_options)); + + auto seconds_from_epoch = GetTodayTimeFromEpoch(); + + auto second_converted_array = CheckConversion( + arrow::compute::Add(first_converted_array, + std::make_shared(seconds_from_epoch * 1000000000))); + + arrow::compute::CastOptions cast_options_2; + cast_options_2.to_type = arrow::timestamp(arrow::TimeUnit::NANO); + + return CheckConversion( + arrow::compute::Cast(second_converted_array, cast_options_2)); + }; } else if (original_type_id == arrow::Type::STRING && target_type == odbcabstraction::CDataType_DATE) { return [=](const std::shared_ptr &original_array) { // The Strptime requires a date format. Using the ISO 8601 format - arrow::compute::StrptimeOptions options("%Y-%m-%d", arrow::TimeUnit::SECOND, - false); + arrow::compute::StrptimeOptions options("%Y-%m-%d", + arrow::TimeUnit::SECOND, false); auto converted_result = arrow::compute::Strptime({original_array}, options); @@ -812,7 +878,7 @@ ArrayConvertTask GetConverter(arrow::Type::type original_type_id, return finish.ValueOrDie(); }; - } else if (IsComplexType(original_type_id) && + } else if (IsComplexType(original_type_id) && (target_type == odbcabstraction::CDataType_CHAR || target_type == odbcabstraction::CDataType_WCHAR)) { return [=](const std::shared_ptr &original_array) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc index 10b9cf7d62dd8..a65f90d08194b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils_test.cc @@ -5,40 +5,131 @@ */ #include "utils.h" + +#include "odbcabstraction/calendar_utils.h" + #include "arrow/testing/builder.h" -#include +#include "arrow/testing/gtest_util.h" +#include "arrow/testing/util.h" #include "gtest/gtest.h" namespace driver { namespace flight_sql { +void AssertConvertedArray(const std::shared_ptr& expected_array, + const std::shared_ptr& converted_array, + uint64_t size, + arrow::Type::type arrow_type) { + ASSERT_EQ(converted_array->type_id(), arrow_type); + ASSERT_EQ(converted_array->length(),size); + ASSERT_EQ(expected_array->ToString(), converted_array->ToString()); +} + +std::shared_ptr convertArray( + const std::shared_ptr& original_array, + odbcabstraction::CDataType c_type) { + auto converter = GetConverter(original_array->type_id(), + c_type); + return converter(original_array); +} + void TestArrayConversion(const std::vector& input, + const std::shared_ptr& expected_array, odbcabstraction::CDataType c_type, arrow::Type::type arrow_type) { - std::shared_ptr array; - arrow::ArrayFromVector(input, &array); + std::shared_ptr original_array; + arrow::ArrayFromVector(input, &original_array); - auto converter = GetConverter(array->type_id(), - c_type); - auto converted_array = converter(array); + auto converted_array = convertArray(original_array, c_type); - ASSERT_EQ(converted_array->type_id(), arrow_type); - ASSERT_EQ(converted_array->length(), input.size()); + AssertConvertedArray(expected_array, converted_array, input.size(), arrow_type); +} + +void TestTime32ArrayConversion(const std::vector& input, + const std::shared_ptr& expected_array, + odbcabstraction::CDataType c_type, + arrow::Type::type arrow_type) { + std::shared_ptr original_array; + arrow::ArrayFromVector(time32(arrow::TimeUnit::MILLI), + input, &original_array); + + auto converted_array = convertArray(original_array, c_type); + + AssertConvertedArray(expected_array, converted_array, input.size(), arrow_type); +} + +void TestTime64ArrayConversion(const std::vector& input, + const std::shared_ptr& expected_array, + odbcabstraction::CDataType c_type, + arrow::Type::type arrow_type) { + std::shared_ptr original_array; + arrow::ArrayFromVector(time64(arrow::TimeUnit::NANO), + input, &original_array); + + auto converted_array = convertArray(original_array, c_type); + + AssertConvertedArray(expected_array, converted_array, input.size(), arrow_type); +} + +TEST(Utils, Time32ToTimeStampArray) { + std::vector input_data = {14896, 17820}; + + const auto seconds_from_epoch = odbcabstraction::GetTodayTimeFromEpoch(); + std::vector expected_data; + expected_data.reserve(2); + + for (const auto &item : input_data) { + expected_data.emplace_back(item + seconds_from_epoch * 1000); + } + + std::shared_ptr expected; + auto timestamp_field = field("timestamp_field", timestamp(arrow::TimeUnit::MILLI)); + arrow::ArrayFromVector(timestamp_field->type(), + expected_data, &expected); + + TestTime32ArrayConversion(input_data, expected, + odbcabstraction::CDataType_TIMESTAMP, + arrow::Type::TIMESTAMP); +} + +TEST(Utils, Time64ToTimeStampArray) { + std::vector input_data = {1579489200000, 1646881200000}; + + const auto seconds_from_epoch = odbcabstraction::GetTodayTimeFromEpoch(); + std::vector expected_data; + expected_data.reserve(2); + + for (const auto &item : input_data) { + expected_data.emplace_back(item + seconds_from_epoch * 1000000000); + } + + std::shared_ptr expected; + auto timestamp_field = field("timestamp_field", timestamp(arrow::TimeUnit::NANO)); + arrow::ArrayFromVector(timestamp_field->type(), + expected_data, &expected); + + TestTime64ArrayConversion(input_data, expected, + odbcabstraction::CDataType_TIMESTAMP, + arrow::Type::TIMESTAMP); } TEST(Utils, StringToDateArray) { - TestArrayConversion({"2020-01-20", "2022-03-10"}, - odbcabstraction::CDataType_DATE, arrow::Type::DATE64); + std::shared_ptr expected; + arrow::ArrayFromVector( + {1579489200000, 1646881200000}, &expected); + + TestArrayConversion({"2020-01-20", "2022-03-10"}, expected, + odbcabstraction::CDataType_DATE, + arrow::Type::DATE64); } TEST(Utils, StringToTimeArray) { - TestArrayConversion({"10:00", "12:00"}, - odbcabstraction::CDataType_TIME, arrow::Type::TIME64); -} + std::shared_ptr expected; + arrow::ArrayFromVector(time64(arrow::TimeUnit::MICRO), + {36000000000, 43200000000}, &expected); -TEST(Utils, StringToTimeStampArray) { - TestArrayConversion({"2013-05-27 19:15:00", "2013-05-31 16:40:00"}, - odbcabstraction::CDataType_TIMESTAMP, arrow::Type::TIMESTAMP); + TestArrayConversion({"10:00", "12:00"}, expected, + odbcabstraction::CDataType_TIME, arrow::Type::TIME64); } TEST(Utils, ConvertSqlPatternToRegexString) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc index 14ce702eb6fc6..6b3b5aa98e97c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc @@ -4,11 +4,26 @@ * See "LICENSE" for license information. */ +#include "odbcabstraction/calendar_utils.h" + #include #include namespace driver { namespace odbcabstraction { + int64_t GetTodayTimeFromEpoch() { + tm date{}; + int64_t t = std::time(0); + + GetTimeForMillisSinceEpoch(date, t); + + date.tm_hour =0; + date.tm_min =0; + date.tm_sec =0; + + return std::mktime(&date); +} + void GetTimeForMillisSinceEpoch(tm& date, int64_t value) { #if defined(_WIN32) gmtime_s(&date, &value); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h index 381d432ceab4f..bfd6362660041 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h @@ -11,6 +11,8 @@ namespace driver { namespace odbcabstraction { + int64_t GetTodayTimeFromEpoch(); + void GetTimeForMillisSinceEpoch(tm& date, int64_t value); } // namespace flight_sql } // namespace driver From 4e2219dbc5a5ebaf229a9b5f0d037ce24a436c97 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Thu, 23 Jun 2022 11:05:14 -0300 Subject: [PATCH 143/183] Small fix on time to timestamp converter Change-Id: I6db175e63b7de4fe3954d028e29325ec34108ed1 --- .../flightsql-odbc/flight_sql/utils.cc | 13 ------------ .../odbcabstraction/calendar_utils.cc | 20 +++++++++++-------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 2b42c2b5085d0..3146592f1666b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -26,19 +26,6 @@ namespace driver { namespace flight_sql { namespace { -int64_t GetTodayTimeFromEpoch() { - tm date{}; - int64_t t = std::time(0); - - odbcabstraction::GetTimeForMillisSinceEpoch(date, t); - - date.tm_hour =0; - date.tm_min =0; - date.tm_sec =0; - - return std::mktime(&date); -} - bool IsComplexType(arrow::Type::type type_id) { switch (type_id) { case arrow::Type::LIST: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc index 6b3b5aa98e97c..566e0de37bfe7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc @@ -11,17 +11,21 @@ namespace driver { namespace odbcabstraction { - int64_t GetTodayTimeFromEpoch() { - tm date{}; - int64_t t = std::time(0); +int64_t GetTodayTimeFromEpoch() { + tm date{}; + int64_t t = std::time(0); - GetTimeForMillisSinceEpoch(date, t); + GetTimeForMillisSinceEpoch(date, t); - date.tm_hour =0; - date.tm_min =0; - date.tm_sec =0; + date.tm_hour = 0; + date.tm_min = 0; + date.tm_sec = 0; - return std::mktime(&date); + #if defined(_WIN32) + return _mkgmtime(&date); + #else + return timegm(&date); + #endif } void GetTimeForMillisSinceEpoch(tm& date, int64_t value) { From 029b28c56902b755bdb3418750a290d60f75a950 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Thu, 23 Jun 2022 13:10:43 -0300 Subject: [PATCH 144/183] Revert "Fix SQL_C_BINARY data conversions" This reverts commit a44f18ed7d77ee729170464215173869b9929f72. Change-Id: I3bcd5567c28e00ee305fdb73f876de475ef4abc8 --- .../flightsql-odbc/flight_sql/flight_sql_result_set_column.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index 4b4e13a60f7bb..2468d2252569a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -45,8 +45,7 @@ FlightSqlResultSetColumn::GetAccessorForTargetType(CDataType target_type) { const std::shared_ptr &original_array = result_set_->GetArrayForColumn(column_n_); - // When retrieving data as binary, its bytes should be the same as it's default type - if (target_type == odbcabstraction::CDataType_DEFAULT || target_type == odbcabstraction::CDataType_BINARY) { + if (target_type == odbcabstraction::CDataType_DEFAULT) { target_type = ConvertArrowTypeToC(original_array->type_id()); } From 267e94246409c3630126393116faf39abcc21d08 Mon Sep 17 00:00:00 2001 From: jvictorhuguenin Date: Tue, 21 Jun 2022 17:51:13 -0300 Subject: [PATCH 145/183] Fix default sizes for GetLength, GetDisplaySize and GetOctetLength Change-Id: I8514e0a52a3db64a967683af774bad210ff3e4c4 --- .../flight_sql_result_set_metadata.cc | 17 +++- .../flight_sql_statement_get_columns.cc | 2 +- .../flightsql-odbc/flight_sql/utils.cc | 85 +++++++++++++++---- .../flightsql-odbc/flight_sql/utils.h | 7 +- 4 files changed, 87 insertions(+), 24 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index b52478f64418a..1ff1325b6315e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -24,6 +24,7 @@ using arrow::util::make_optional; using arrow::util::nullopt; constexpr int32_t StringColumnLength = 1024; // TODO: Get from connection +constexpr int32_t DefaultDecimalPrecision = 38; namespace { std::shared_ptr empty_metadata_map(new arrow::KeyValueMetadata); @@ -126,7 +127,7 @@ uint16_t FlightSqlResultSetMetadata::GetConciseType(int column_position) { const std::shared_ptr &field = schema_->field(column_position -1); const SqlDataType sqlColumnType = GetDataTypeFromArrowField_V3(field); - return sqlColumnType; + return sqlColumnType; } size_t FlightSqlResultSetMetadata::GetLength(int column_position) { @@ -136,7 +137,7 @@ size_t FlightSqlResultSetMetadata::GetLength(int column_position) { int32_t column_size = metadata.GetPrecision().ValueOrElse([] { return StringColumnLength; }); SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); - return GetBufferLength(data_type_v3, column_size).value_or(NO_TOTAL); + return GetBufferLength(data_type_v3, column_size).value_or(StringColumnLength); } std::string FlightSqlResultSetMetadata::GetLiteralPrefix(int column_position) { @@ -167,10 +168,18 @@ size_t FlightSqlResultSetMetadata::GetOctetLength(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); - int32_t column_size = metadata.GetPrecision().ValueOrElse([] { return StringColumnLength; }); + arrow::Result column_size = metadata.GetPrecision(); SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); - return GetCharOctetLength(data_type_v3, column_size).value_or(NO_TOTAL); + // Workaround to get the precision for Decimal and Numeric types, since server doesn't return it currently. + // TODO: Use the server precision when its fixed. + std::shared_ptr arrow_type = field->type(); + if (arrow_type->id() == arrow::Type::DECIMAL128){ + int32_t precision = GetDecimalTypePrecision(arrow_type); + return GetCharOctetLength(data_type_v3, column_size, precision).value_or(DefaultDecimalPrecision+2); + } + + return GetCharOctetLength(data_type_v3, column_size).value_or(StringColumnLength); } std::string FlightSqlResultSetMetadata::GetTypeName(int column_position) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc index 56ce2868cfb91..7cbd633bc1e64 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc @@ -124,7 +124,7 @@ Transform_inner(const odbcabstraction::OdbcVersion odbc_version, ? make_optional(precision_result.ValueOrDie()) : nullopt; data.char_octet_length = - GetCharOctetLength(data_type_v3, data.column_size); + GetCharOctetLength(data_type_v3, precision_result); data.buffer_length = GetBufferLength(data_type_v3, data.column_size); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 3146592f1666b..0e513cb8b7981 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -318,25 +318,64 @@ optional GetSqlDateTimeSubCode(SqlDataType data_type) { } optional GetCharOctetLength(SqlDataType data_type, - const optional& column_size) { - // TODO: Replace NO_TOTAL with the correct default values - // TODO: Get correct default values from connection settings + const arrow::Result& column_size, const int32_t decimal_precison) { switch (data_type) { - case SqlDataType_CHAR: - case SqlDataType_VARCHAR: - case SqlDataType_LONGVARCHAR: - return column_size.has_value() ? column_size.value() : NO_TOTAL; - case SqlDataType_WCHAR: - case SqlDataType_WVARCHAR: - case SqlDataType_WLONGVARCHAR: - return column_size.has_value() ? (column_size.value() * sizeof(SqlWChar)) - : NO_TOTAL; - case SqlDataType_BINARY: - case SqlDataType_VARBINARY: - case SqlDataType_LONGVARBINARY: - return column_size.has_value() ? column_size.value() : NO_TOTAL; - default: - return arrow::util::nullopt; + case SqlDataType_BINARY: + case SqlDataType_VARBINARY: + case SqlDataType_LONGVARBINARY: + case SqlDataType_CHAR: + case SqlDataType_VARCHAR: + case SqlDataType_LONGVARCHAR: + if (column_size.ok()) { + return column_size.ValueOrDie(); + } else { + return arrow::util::nullopt; + } + case SqlDataType_WCHAR: + case SqlDataType_WVARCHAR: + case SqlDataType_WLONGVARCHAR: + if (column_size.ok()) { + return column_size.ValueOrDie() * sizeof(SqlWChar); + } else { + return arrow::util::nullopt; + } + case SqlDataType_TINYINT: + case SqlDataType_BIT: + return 1; // The same as sizeof(SQL_C_BIT) + case SqlDataType_SMALLINT: + return 2; // The same as sizeof(SQL_C_SMALLINT) + case SqlDataType_INTEGER: + return 4; // The same as sizeof(SQL_C_INTEGER) + case SqlDataType_BIGINT: + case SqlDataType_FLOAT: + case SqlDataType_DOUBLE: + return 8; // The same as sizeof(SQL_C_DOUBLE) + case SqlDataType_DECIMAL: + case SqlDataType_NUMERIC: + return decimal_precison + 2; // One char for each digit and two extra chars for a sign and a decimal point + case SqlDataType_TYPE_DATE: + case SqlDataType_TYPE_TIME: + return 6; // The same as sizeof(SQL_TIME_STRUCT) + case SqlDataType_TYPE_TIMESTAMP: + return 16; // The same as sizeof(SQL_TIMESTAMP_STRUCT) + case SqlDataType_INTERVAL_MONTH: + case SqlDataType_INTERVAL_YEAR: + case SqlDataType_INTERVAL_YEAR_TO_MONTH: + case SqlDataType_INTERVAL_DAY: + case SqlDataType_INTERVAL_HOUR: + case SqlDataType_INTERVAL_MINUTE: + case SqlDataType_INTERVAL_SECOND: + case SqlDataType_INTERVAL_DAY_TO_HOUR: + case SqlDataType_INTERVAL_DAY_TO_MINUTE: + case SqlDataType_INTERVAL_DAY_TO_SECOND: + case SqlDataType_INTERVAL_HOUR_TO_MINUTE: + case SqlDataType_INTERVAL_HOUR_TO_SECOND: + case SqlDataType_INTERVAL_MINUTE_TO_SECOND: + return 34; // The same as sizeof(SQL_INTERVAL_STRUCT) + case SqlDataType_GUID: + return 16; + default: + return arrow::util::nullopt; } } optional GetTypeScale(SqlDataType data_type, @@ -966,5 +1005,15 @@ std::string ConvertToDBMSVer(const std::string &str) { return result; } +int32_t GetDecimalTypeScale(const std::shared_ptr& decimalType){ + auto decimal128Type = std::dynamic_pointer_cast(decimalType); + return decimal128Type->scale(); +} + +int32_t GetDecimalTypePrecision(const std::shared_ptr& decimalType){ + auto decimal128Type = std::dynamic_pointer_cast(decimalType); + return decimal128Type->precision(); +} + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index 7c3994cd86abd..71f7f5ecff45b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -74,7 +74,8 @@ int16_t GetNonConciseDataType(odbcabstraction::SqlDataType data_type); optional GetSqlDateTimeSubCode(odbcabstraction::SqlDataType data_type); optional GetCharOctetLength(odbcabstraction::SqlDataType data_type, - const optional& column_size); + const arrow::Result& column_size, + const int32_t decimal_precison=0); optional GetBufferLength(odbcabstraction::SqlDataType data_type, const optional& column_size); @@ -108,5 +109,9 @@ ArrayConvertTask GetConverter(arrow::Type::type original_type_id, std::string ConvertToDBMSVer(const std::string& str); +int32_t GetDecimalTypeScale(const std::shared_ptr& decimalType); + +int32_t GetDecimalTypePrecision(const std::shared_ptr& decimalType); + } // namespace flight_sql } // namespace driver From d48dfe57305114ebd75ca7e1cf14f404325b43bb Mon Sep 17 00:00:00 2001 From: Eugene Roslikov Date: Fri, 24 Jun 2022 09:28:51 -0700 Subject: [PATCH 146/183] Fix for Conversions to SQL_C_NUMERIC from any type fails Conversion to SQL_C_NUMERIC from bigint, integer, float, double, decimal and numeric is working now. Actual fixes are for incorrect handling of the sign, setting a default output precision and allow DECIMAL128 as the source for conversions. Change-Id: I5b16a2c77ffe94d05b341d37393d9a041300d942 --- .../accessors/decimal_array_accessor.cc | 18 ++---------------- .../accessors/decimal_array_accessor_test.cc | 2 +- .../flightsql-odbc/flight_sql/utils.cc | 4 ++++ .../odbcabstraction/odbc_impl/ODBCStatement.cc | 2 +- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc index 680cff46ca9aa..4d82eabfb2b73 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc @@ -9,17 +9,6 @@ #include #include -namespace { -void Negate(uint8_t* values) { - uint8_t carry = 1; - for (size_t i = 0; i < 16; ++i) { - uint8_t& elem = values[i]; - elem = ~elem + carry; - carry &= (elem == 0); - } -} -} // namespace - namespace driver { namespace flight_sql { @@ -59,12 +48,9 @@ RowStatus DecimalArrayFlightSqlAccessor::Mov result->precision = static_cast(binding->precision); result->scale = static_cast(binding->scale); - // If the most significant bit is set this number is negative (sign = 0). - result->sign = (static_cast(result->val[15]) >> 7) == 0; + // If the most significant bit is set this number is negative (sign = 1). + result->sign = (static_cast(result->val[15]) >> 7) == 1; result->precision = data_type_->precision(); - if (result->sign == 0) { - Negate(result->val); - } if (binding->strlen_buffer) { binding->strlen_buffer[i] = static_cast(GetCellLength_impl(binding)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc index 4245a6229998c..c3d3f6a9660d3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc @@ -42,7 +42,7 @@ std::string ConvertNumericToString(NUMERIC_STRUCT &numeric) { auto decimal = Decimal128(v[1], v[0]); const std::string &string = decimal.ToString(numeric.scale); - return (numeric.sign ? "" : "-") + string; + return string; } } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 0e513cb8b7981..00334162e5ad6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -695,6 +695,8 @@ GetDefaultDataTypeForTypeId(arrow::Type::type type_id) { return arrow::uint64(); case arrow::Type::BINARY: return arrow::binary(); + case arrow::Type::DECIMAL128: + return arrow::decimal128(arrow::Decimal128Type::kMaxPrecision, 0); case arrow::Type::DATE64: return arrow::date64(); case arrow::Type::TIME64: @@ -777,6 +779,8 @@ odbcabstraction::CDataType ConvertArrowTypeToC(arrow::Type::type type_id) { return odbcabstraction::CDataType_UBIGINT; case arrow::Type::BINARY: return odbcabstraction::CDataType_BINARY; + case arrow::Type::DECIMAL128: + return odbcabstraction::CDataType_NUMERIC; case arrow::Type::DATE64: case arrow::Type::DATE32: return odbcabstraction::CDataType_DATE; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc index 317c8610490af..1b4ce061c914a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc @@ -650,7 +650,7 @@ bool ODBCStatement::GetData(SQLSMALLINT recordNumber, SQLSMALLINT cType, SQLPOIN SQLSMALLINT evaluatedCType = cType; // TODO: Get proper default precision and scale from abstraction. - int precision = 0; + int precision = 38; // arrow::Decimal128Type::kMaxPrecision; int scale = 0; if (cType == SQL_ARD_TYPE) { From ceac9f86ef57b33f0af57c214537a89a3433c2fd Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Wed, 22 Jun 2022 15:23:37 -0300 Subject: [PATCH 147/183] Improve connection error message and exceptions - Add new exception with for the Communication Link failure - Change the sql_state from the AuthenticationException - Adjust the Authentication methods to raise the two new exceptions Change-Id: Iea2d8c72bc3f50554b1557ddf4b4d9745e6ab9be --- .../flight_sql/flight_sql_auth_method.cc | 18 +++++++++++++++--- .../odbcabstraction/exceptions.cc | 5 +++++ .../include/odbcabstraction/error_codes.h | 1 + .../include/odbcabstraction/exceptions.h | 9 ++++++++- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index a87ec6524d0cf..3cdaab8483b6e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -27,6 +27,7 @@ using arrow::flight::FlightCallOptions; using arrow::flight::FlightClient; using arrow::flight::TimeoutDuration; using driver::odbcabstraction::AuthenticationException; +using driver::odbcabstraction::CommunicationException; using driver::odbcabstraction::Connection; namespace { @@ -75,10 +76,19 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { Result> bearer_result = client_.AuthenticateBasicToken(auth_call_options, user_, password_); + if (!bearer_result.ok()) { - throw AuthenticationException( - "Failed to authenticate with user and password: " + - bearer_result.status().ToString()); + const auto& flightStatus = arrow::flight::FlightStatusDetail::UnwrapStatus(bearer_result.status()); + if (flightStatus != nullptr) { + if (flightStatus->code() == arrow::flight::FlightStatusCode::Unauthenticated) { + throw AuthenticationException("Failed to authenticate with user and password: " + + bearer_result.status().ToString()); + } else if (flightStatus->code() == arrow::flight::FlightStatusCode::Unavailable) { + throw CommunicationException(bearer_result.status().message()); + } + } + + throw odbcabstraction::DriverException(bearer_result.status().message()); } call_options.headers.push_back(bearer_result.ValueOrDie()); @@ -111,6 +121,8 @@ class UserPasswordAuthMethod : public FlightSqlAuthMethod { if (flightStatus != nullptr) { if (flightStatus->code() == arrow::flight::FlightStatusCode::Unauthenticated) { throw AuthenticationException("Failed to authenticate with token: " + token_ + " Message: " + status.message()); + } else if (flightStatus->code() == arrow::flight::FlightStatusCode::Unavailable) { + throw CommunicationException(status.message()); } } throw odbcabstraction::DriverException(status.message()); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc index c0128188d8909..0f7a07da39004 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/exceptions.cc @@ -26,6 +26,11 @@ AuthenticationException::AuthenticationException(std::string message, std::strin int32_t native_error) : DriverException(message, sql_state, native_error) {} +CommunicationException::CommunicationException(std::string message, std::string sql_state, + int32_t native_error) + : DriverException(message + ". Please ensure your encryption settings match the server.", + sql_state, native_error) {} + NullWithoutIndicatorException::NullWithoutIndicatorException( std::string message, std::string sql_state, int32_t native_error) : DriverException(message, sql_state, native_error) {} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/error_codes.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/error_codes.h index 7624c225c24f7..65862322e1bb2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/error_codes.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/error_codes.h @@ -16,6 +16,7 @@ namespace odbcabstraction { ODBCErrorCodes_AUTH = 200, ODBCErrorCodes_TLS = 300, ODBCErrorCodes_FRACTIONAL_TRUNCATION_ERROR = 400, + ODBCErrorCodes_COMMUNICATION = 500, ODBCErrorCodes_GENERAL_WARNING = 1000000, ODBCErrorCodes_TRUNCATION_WARNING = 1000100, ODBCErrorCodes_FRACTIONAL_TRUNCATION_WARNING = 1000100, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h index 6d7288a9098b5..6f82a45c1bcb0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/exceptions.h @@ -35,10 +35,17 @@ class DriverException : public std::exception { /// \brief Authentication specific exception class AuthenticationException : public DriverException { public: - explicit AuthenticationException(std::string message, std::string sql_state = "08S01", + explicit AuthenticationException(std::string message, std::string sql_state = "28000", int32_t native_error = ODBCErrorCodes_AUTH); }; +/// \brief Communication link specific exception +class CommunicationException : public DriverException { +public: + explicit CommunicationException(std::string message, std::string sql_state = "08S01", + int32_t native_error = ODBCErrorCodes_COMMUNICATION); +}; + /// \brief Error when null is retrieved from the database but no indicator was supplied. /// (This means the driver has no way to report ot the application that there was a NULL value). class NullWithoutIndicatorException : public DriverException { From 895bdb2588bcecf9ab2a2876e887debf2f9539c9 Mon Sep 17 00:00:00 2001 From: Vinicius Fraga Date: Wed, 22 Jun 2022 18:25:32 -0300 Subject: [PATCH 148/183] Add support for StringColumnLength when Precision/Scale is not available Change-Id: I26c806ce8c1c8f28ea34d1a5a8a1d710a86f5904 --- .../flight_sql/flight_sql_connection.cc | 46 +++++++++++++++++-- .../flight_sql/flight_sql_connection.h | 7 +++ .../flight_sql/flight_sql_connection_test.cc | 20 ++++++++ .../flight_sql/flight_sql_result_set.cc | 13 ++++-- .../flight_sql/flight_sql_result_set.h | 5 +- .../flight_sql_result_set_metadata.cc | 32 +++++++------ .../flight_sql_result_set_metadata.h | 13 ++++-- .../flight_sql/flight_sql_statement.cc | 29 ++++++------ .../flight_sql/flight_sql_statement.h | 5 +- .../flight_sql_statement_get_tables.cc | 18 ++++---- .../flight_sql_statement_get_tables.h | 14 ++++-- .../include/odbcabstraction/types.h | 4 ++ .../include/odbcabstraction/utils.h | 21 +++++++++ .../flightsql-odbc/odbcabstraction/utils.cc | 24 ++++++++++ 14 files changed, 199 insertions(+), 52 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 9b3afd6f97fe9..fbb155b154551 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -58,11 +58,13 @@ const std::string FlightSqlConnection::USE_ENCRYPTION = "useEncryption"; const std::string FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION = "disableCertificateVerification"; const std::string FlightSqlConnection::TRUSTED_CERTS = "trustedCerts"; const std::string FlightSqlConnection::USE_SYSTEM_TRUST_STORE = "useSystemTrustStore"; +const std::string FlightSqlConnection::STRING_COLUMN_LENGTH = "StringColumnLength"; const std::vector FlightSqlConnection::ALL_KEYS = { FlightSqlConnection::DSN, FlightSqlConnection::DRIVER, FlightSqlConnection::HOST, FlightSqlConnection::PORT, - FlightSqlConnection::TOKEN, FlightSqlConnection::UID, FlightSqlConnection::USER_ID, FlightSqlConnection::PWD, FlightSqlConnection::USE_ENCRYPTION, - FlightSqlConnection::TRUSTED_CERTS, FlightSqlConnection::USE_SYSTEM_TRUST_STORE, FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION }; + FlightSqlConnection::TOKEN, FlightSqlConnection::UID, FlightSqlConnection::USER_ID, FlightSqlConnection::PWD, + FlightSqlConnection::USE_ENCRYPTION, FlightSqlConnection::TRUSTED_CERTS, FlightSqlConnection::USE_SYSTEM_TRUST_STORE, + FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, FlightSqlConnection::STRING_COLUMN_LENGTH }; namespace { @@ -114,7 +116,8 @@ const std::set BUILT_IN_PROP FlightSqlConnection::USE_ENCRYPTION, FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, FlightSqlConnection::TRUSTED_CERTS, - FlightSqlConnection::USE_SYSTEM_TRUST_STORE + FlightSqlConnection::USE_SYSTEM_TRUST_STORE, + FlightSqlConnection::STRING_COLUMN_LENGTH }; Connection::ConnPropertyMap::const_iterator @@ -175,6 +178,7 @@ void FlightSqlConnection::Connect(const ConnPropertyMap &properties, info_.SetProperty(SQL_USER_NAME, auth_method->GetUser()); attribute_[CONNECTION_DEAD] = static_cast(SQL_FALSE); + PopulateMetadataSettings(properties); PopulateCallOptions(properties); } catch (...) { attribute_[CONNECTION_DEAD] = static_cast(SQL_TRUE); @@ -184,6 +188,34 @@ void FlightSqlConnection::Connect(const ConnPropertyMap &properties, } } +void FlightSqlConnection::PopulateMetadataSettings(const Connection::ConnPropertyMap &conn_property_map) { + metadata_settings_.string_column_length_ = GetStringColumnLength(conn_property_map); +} + +int32_t FlightSqlConnection::GetStringColumnLength(const Connection::ConnPropertyMap &conn_property_map) { + const int32_t default_string_column_length = 1024; + const int32_t min_string_column_length = 1; + int32_t string_column_length; + + try { + string_column_length = AsInt32( + default_string_column_length, + min_string_column_length, + conn_property_map, + FlightSqlConnection::STRING_COLUMN_LENGTH + ); + } catch (const std::exception& e) { + diagnostics_.AddWarning( + std::string("Invalid value for connection property " + FlightSqlConnection::STRING_COLUMN_LENGTH + + ". Please ensure it has a valid numeric value. Using default: " + + std::to_string(default_string_column_length) + ". Message: " + e.what()), + "01000", odbcabstraction::ODBCErrorCodes_GENERAL_WARNING); + string_column_length = default_string_column_length; + } + + return string_column_length; +} + const FlightCallOptions & FlightSqlConnection::PopulateCallOptions(const ConnPropertyMap &props) { // Set CONNECTION_TIMEOUT attribute or LOGIN_TIMEOUT depending on if this @@ -288,7 +320,13 @@ void FlightSqlConnection::Close() { std::shared_ptr FlightSqlConnection::CreateStatement() { return std::shared_ptr( - new FlightSqlStatement(diagnostics_, *sql_client_, call_options_)); + new FlightSqlStatement( + diagnostics_, + *sql_client_, + call_options_, + metadata_settings_ + ) + ); } bool FlightSqlConnection::SetAttribute(Connection::AttributeId attribute, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 83b7bbcc1eee4..e84e2dbab6530 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -13,6 +13,7 @@ #include #include "get_info_cache.h" +#include "odbcabstraction/types.h" namespace driver { namespace flight_sql { @@ -30,6 +31,7 @@ std::shared_ptr LoadFlightSslConfigs( class FlightSqlConnection : public odbcabstraction::Connection { private: + odbcabstraction::MetadataSettings metadata_settings_; std::map attribute_; arrow::flight::FlightCallOptions call_options_; std::unique_ptr sql_client_; @@ -38,6 +40,8 @@ class FlightSqlConnection : public odbcabstraction::Connection { odbcabstraction::OdbcVersion odbc_version_; bool closed_; + void PopulateMetadataSettings(const Connection::ConnPropertyMap &connPropertyMap); + public: static const std::vector ALL_KEYS; static const std::string DSN; @@ -54,6 +58,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { static const std::string DISABLE_CERTIFICATE_VERIFICATION; static const std::string TRUSTED_CERTS; static const std::string USE_SYSTEM_TRUST_STORE; + static const std::string STRING_COLUMN_LENGTH; explicit FlightSqlConnection(odbcabstraction::OdbcVersion odbc_version); @@ -93,6 +98,8 @@ class FlightSqlConnection : public odbcabstraction::Connection { /// \brief A setter to the field closed_. /// \note Visible for testing void SetClosed(bool is_closed); + + int32_t GetStringColumnLength(const ConnPropertyMap &connPropertyMap); }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index cafc5a2b63a9c..58001e90e551d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -53,6 +53,26 @@ TEST(AttributeTests, GetAttributeWithoutSetting) { connection.Close(); } +TEST(MetadataSettingsTest, StringColumnLengthTest) { + FlightSqlConnection connection(odbcabstraction::V_3); + connection.SetClosed(false); + + const int32_t expected_string_column_length = 100000; + + const Connection::ConnPropertyMap properties = { + {FlightSqlConnection::HOST, std::string("localhost")}, // expect not used + {FlightSqlConnection::PORT, std::string("32010")}, // expect not used + {FlightSqlConnection::USE_ENCRYPTION, std::string("false")}, // expect not used + {FlightSqlConnection::STRING_COLUMN_LENGTH, std::to_string(expected_string_column_length)}, + }; + + const int32_t actual_string_column_length = connection.GetStringColumnLength(properties); + + EXPECT_EQ(expected_string_column_length, actual_string_column_length); + + connection.Close(); +} + TEST(BuildLocationTests, ForTcp) { std::vector missing_attr; Connection::ConnPropertyMap properties = { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index 755fb89d095f5..99b4920b01eff 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -34,12 +34,15 @@ FlightSqlResultSet::FlightSqlResultSet( const arrow::flight::FlightCallOptions &call_options, const std::shared_ptr &flight_info, const std::shared_ptr &transformer, - odbcabstraction::Diagnostics& diagnostics) - : chunk_iterator_(flight_sql_client, call_options, flight_info), + odbcabstraction::Diagnostics& diagnostics, + const odbcabstraction::MetadataSettings &metadata_settings) + : + metadata_settings_(metadata_settings), + chunk_iterator_(flight_sql_client, call_options, flight_info), transformer_(transformer), - metadata_(transformer ? new FlightSqlResultSetMetadata( - transformer->GetTransformedSchema()) - : new FlightSqlResultSetMetadata(flight_info)), + metadata_(transformer ? new FlightSqlResultSetMetadata(transformer->GetTransformedSchema(), + metadata_settings_) + : new FlightSqlResultSetMetadata(flight_info, metadata_settings_)), columns_(metadata_->GetColumnCount()), get_data_offsets_(metadata_->GetColumnCount(), 0), diagnostics_(diagnostics), diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index 94953ad4cc1d7..13c9eb019f6be 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -10,6 +10,7 @@ #include "flight_sql_stream_chunk_iterator.h" #include "record_batch_transformer.h" #include "utils.h" +#include "odbcabstraction/types.h" #include #include #include @@ -41,6 +42,7 @@ class FlightSqlResultSetColumn; class FlightSqlResultSet : public ResultSet { private: + const odbcabstraction::MetadataSettings& metadata_settings_; FlightStreamChunkIterator chunk_iterator_; FlightStreamChunk current_chunk_; std::shared_ptr schema_; @@ -61,7 +63,8 @@ class FlightSqlResultSet : public ResultSet { const arrow::flight::FlightCallOptions &call_options, const std::shared_ptr &flight_info, const std::shared_ptr &transformer, - odbcabstraction::Diagnostics& diagnostics); + odbcabstraction::Diagnostics& diagnostics, + const odbcabstraction::MetadataSettings &metadata_settings); void Close() override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index 1ff1325b6315e..edbcd2133a394 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -23,7 +23,6 @@ using arrow::Field; using arrow::util::make_optional; using arrow::util::nullopt; -constexpr int32_t StringColumnLength = 1024; // TODO: Get from connection constexpr int32_t DefaultDecimalPrecision = 38; namespace { @@ -51,9 +50,8 @@ std::string FlightSqlResultSetMetadata::GetName(int column_position) { size_t FlightSqlResultSetMetadata::GetPrecision(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); - int32_t column_size = metadata.GetPrecision().ValueOrElse([] { return 0; }); + int32_t column_size = GetFieldPrecision(field).ValueOrElse([] { return 0; }); SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); return GetColumnSize(data_type_v3, column_size).value_or(0); @@ -106,9 +104,8 @@ std::string FlightSqlResultSetMetadata::GetColumnLabel(int column_position) { size_t FlightSqlResultSetMetadata::GetColumnDisplaySize( int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); - int32_t column_size = metadata.GetPrecision().ValueOrElse([] { return StringColumnLength; }); + int32_t column_size = GetFieldPrecision(field).ValueOrElse([this] { return metadata_settings_.string_column_length_; }); SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); return GetDisplaySize(data_type_v3, column_size).value_or(NO_TOTAL); @@ -132,12 +129,15 @@ uint16_t FlightSqlResultSetMetadata::GetConciseType(int column_position) { size_t FlightSqlResultSetMetadata::GetLength(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); - int32_t column_size = metadata.GetPrecision().ValueOrElse([] { return StringColumnLength; }); + int32_t column_size = GetFieldPrecision(field).ValueOrElse([this] { return metadata_settings_.string_column_length_; }); SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); - return GetBufferLength(data_type_v3, column_size).value_or(StringColumnLength); + return GetBufferLength(data_type_v3, column_size).value_or(metadata_settings_.string_column_length_); +} + +arrow::Result FlightSqlResultSetMetadata::GetFieldPrecision(const std::shared_ptr &field) { + return GetMetadata(field).GetPrecision(); } std::string FlightSqlResultSetMetadata::GetLiteralPrefix(int column_position) { @@ -168,7 +168,7 @@ size_t FlightSqlResultSetMetadata::GetOctetLength(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); - arrow::Result column_size = metadata.GetPrecision(); + arrow::Result column_size = GetFieldPrecision(field); SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); // Workaround to get the precision for Decimal and Numeric types, since server doesn't return it currently. @@ -179,7 +179,7 @@ size_t FlightSqlResultSetMetadata::GetOctetLength(int column_position) { return GetCharOctetLength(data_type_v3, column_size, precision).value_or(DefaultDecimalPrecision+2); } - return GetCharOctetLength(data_type_v3, column_size).value_or(StringColumnLength); + return GetCharOctetLength(data_type_v3, column_size).value_or(metadata_settings_.string_column_length_); } std::string FlightSqlResultSetMetadata::GetTypeName(int column_position) { @@ -234,11 +234,17 @@ bool FlightSqlResultSetMetadata::IsFixedPrecScale(int column_position) { } FlightSqlResultSetMetadata::FlightSqlResultSetMetadata( - std::shared_ptr schema) - : schema_(std::move(schema)) {} + std::shared_ptr schema, + const odbcabstraction::MetadataSettings& metadata_settings) + : + metadata_settings_(metadata_settings), + schema_(std::move(schema)) {} FlightSqlResultSetMetadata::FlightSqlResultSetMetadata( - const std::shared_ptr &flight_info) { + const std::shared_ptr &flight_info, + const odbcabstraction::MetadataSettings& metadata_settings) + : + metadata_settings_(metadata_settings){ arrow::ipc::DictionaryMemo dict_memo; ThrowIfNotOK(flight_info->GetSchema(&dict_memo, &schema_)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h index 256fdb11f0612..c96461edaf183 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h @@ -9,18 +9,23 @@ #include #include #include +#include "odbcabstraction/types.h" namespace driver { namespace flight_sql { class FlightSqlResultSetMetadata : public odbcabstraction::ResultSetMetadata { private: + const odbcabstraction::MetadataSettings& metadata_settings_; std::shared_ptr schema_; public: - explicit FlightSqlResultSetMetadata( - const std::shared_ptr &flight_info); + FlightSqlResultSetMetadata( + const std::shared_ptr &flight_info, + const odbcabstraction::MetadataSettings& metadata_settings); - explicit FlightSqlResultSetMetadata(std::shared_ptr schema); + FlightSqlResultSetMetadata( + std::shared_ptr schema, + const odbcabstraction::MetadataSettings& metadata_settings); size_t GetColumnCount() override; @@ -77,6 +82,8 @@ class FlightSqlResultSetMetadata : public odbcabstraction::ResultSetMetadata { bool IsUnsigned(int column_position) override; bool IsFixedPrecScale(int column_position) override; + + arrow::Result GetFieldPrecision(const std::shared_ptr &field); }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index 96ffd0c50a2d2..f8d81dcd07058 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -54,9 +54,10 @@ void ClosePreparedStatementIfAny( FlightSqlStatement::FlightSqlStatement( const odbcabstraction::Diagnostics& diagnostics, FlightSqlClient &sql_client, - FlightCallOptions call_options) + FlightCallOptions call_options, + const odbcabstraction::MetadataSettings& metadata_settings) : diagnostics_("Apache Arrow", diagnostics.GetDataSourceComponent(), diagnostics.GetOdbcVersion()), - sql_client_(sql_client), call_options_(std::move(call_options)) { + sql_client_(sql_client), call_options_(std::move(call_options)), metadata_settings_(metadata_settings) { attribute_[METADATA_ID] = static_cast(SQL_FALSE); attribute_[MAX_LENGTH] = static_cast(0); attribute_[NOSCAN] = static_cast(SQL_NOSCAN_OFF); @@ -105,7 +106,7 @@ FlightSqlStatement::Prepare(const std::string &query) { const auto &result_set_metadata = std::make_shared( - prepared_statement_->dataset_schema()); + prepared_statement_->dataset_schema(), metadata_settings_); return boost::optional>( result_set_metadata); } @@ -117,7 +118,7 @@ bool FlightSqlStatement::ExecutePrepared() { ThrowIfNotOK(result.status()); current_result_set_ = std::make_shared( - sql_client_, call_options_, result.ValueOrDie(), nullptr, diagnostics_); + sql_client_, call_options_, result.ValueOrDie(), nullptr, diagnostics_, metadata_settings_); return true; } @@ -130,7 +131,7 @@ bool FlightSqlStatement::Execute(const std::string &query) { ThrowIfNotOK(result.status()); current_result_set_ = std::make_shared( - sql_client_, call_options_, result.ValueOrDie(), nullptr, diagnostics_); + sql_client_, call_options_, result.ValueOrDie(), nullptr, diagnostics_, metadata_settings_); return true; } @@ -153,18 +154,20 @@ std::shared_ptr FlightSqlStatement::GetTables( (schema_name && schema_name->empty()) && (table_name && table_name->empty())) { current_result_set_ = - GetTablesForSQLAllCatalogs(column_names, call_options_, sql_client_, diagnostics_); + GetTablesForSQLAllCatalogs( + column_names, call_options_, sql_client_, diagnostics_, metadata_settings_); } else if ((catalog_name && catalog_name->empty()) && (schema_name && *schema_name == "%") && (table_name && table_name->empty())) { current_result_set_ = GetTablesForSQLAllDbSchemas( - column_names, call_options_, sql_client_, schema_name, diagnostics_); + column_names, call_options_, sql_client_, schema_name, diagnostics_, metadata_settings_); } else if ((catalog_name && catalog_name->empty()) && (schema_name && schema_name->empty()) && (table_name && table_name->empty()) && (table_type && *table_type == "%")) { current_result_set_ = - GetTablesForSQLAllTableTypes(column_names, call_options_, sql_client_, diagnostics_); + GetTablesForSQLAllTableTypes( + column_names, call_options_, sql_client_, diagnostics_, metadata_settings_); } else { if (table_type) { ParseTableTypes(*table_type, table_types); @@ -172,7 +175,7 @@ std::shared_ptr FlightSqlStatement::GetTables( current_result_set_ = GetTablesForGenericUse( column_names, call_options_, sql_client_, catalog_name, schema_name, - table_name, table_types, diagnostics_); + table_name, table_types, diagnostics_, metadata_settings_); } return current_result_set_; @@ -213,7 +216,7 @@ std::shared_ptr FlightSqlStatement::GetColumns_V2( odbcabstraction::V_2, column_name); current_result_set_ = std::make_shared( - sql_client_, call_options_, flight_info, transformer, diagnostics_); + sql_client_, call_options_, flight_info, transformer, diagnostics_, metadata_settings_); return current_result_set_; } @@ -233,7 +236,7 @@ std::shared_ptr FlightSqlStatement::GetColumns_V3( odbcabstraction::V_3, column_name); current_result_set_ = std::make_shared( - sql_client_, call_options_, flight_info, transformer, diagnostics_); + sql_client_, call_options_, flight_info, transformer, diagnostics_, metadata_settings_); return current_result_set_; } @@ -251,7 +254,7 @@ std::shared_ptr FlightSqlStatement::GetTypeInfo_V2(int16_t data_type) odbcabstraction::V_2, data_type); current_result_set_ = std::make_shared( - sql_client_, call_options_, flight_info, transformer, diagnostics_); + sql_client_, call_options_, flight_info, transformer, diagnostics_, metadata_settings_); return current_result_set_; } @@ -269,7 +272,7 @@ std::shared_ptr FlightSqlStatement::GetTypeInfo_V3(int16_t data_type) odbcabstraction::V_3, data_type); current_result_set_ = std::make_shared( - sql_client_, call_options_, flight_info, transformer, diagnostics_); + sql_client_, call_options_, flight_info, transformer, diagnostics_, metadata_settings_); return current_result_set_; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h index 5cdf9dd670142..9e7e6e4e081c2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.h @@ -7,6 +7,7 @@ #pragma once #include "flight_sql_statement_get_tables.h" +#include "odbcabstraction/types.h" #include #include @@ -26,6 +27,7 @@ class FlightSqlStatement : public odbcabstraction::Statement { arrow::flight::sql::FlightSqlClient &sql_client_; std::shared_ptr current_result_set_; std::shared_ptr prepared_statement_; + const odbcabstraction::MetadataSettings& metadata_settings_; std::shared_ptr GetTables(const std::string *catalog_name, const std::string *schema_name, @@ -36,7 +38,8 @@ class FlightSqlStatement : public odbcabstraction::Statement { FlightSqlStatement( const odbcabstraction::Diagnostics &diagnostics, arrow::flight::sql::FlightSqlClient &sql_client, - arrow::flight::FlightCallOptions call_options); + arrow::flight::FlightCallOptions call_options, + const odbcabstraction::MetadataSettings& metadata_settings); bool SetAttribute(StatementAttributeId attribute, const Attribute &value) override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc index d3bbb40159bed..1536a13a8bd09 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.cc @@ -66,7 +66,8 @@ std::shared_ptr GetTablesForSQLAllCatalogs(const ColumnNames &names, FlightCallOptions &call_options, FlightSqlClient &sql_client, - odbcabstraction::Diagnostics &diagnostics) { + odbcabstraction::Diagnostics &diagnostics, + const odbcabstraction::MetadataSettings &metadata_settings) { Result> result = sql_client.GetCatalogs(call_options); @@ -86,13 +87,13 @@ GetTablesForSQLAllCatalogs(const ColumnNames &names, .Build(); return std::make_shared(sql_client, call_options, - flight_info, transformer, diagnostics); + flight_info, transformer, diagnostics, metadata_settings); } std::shared_ptr GetTablesForSQLAllDbSchemas( const ColumnNames &names, FlightCallOptions &call_options, FlightSqlClient &sql_client, const std::string *schema_name, - odbcabstraction::Diagnostics &diagnostics ) { + odbcabstraction::Diagnostics &diagnostics, const odbcabstraction::MetadataSettings &metadata_settings) { Result> result = sql_client.GetDbSchemas(call_options, nullptr, schema_name); @@ -112,14 +113,15 @@ std::shared_ptr GetTablesForSQLAllDbSchemas( .Build(); return std::make_shared(sql_client, call_options, - flight_info, transformer, diagnostics); + flight_info, transformer, diagnostics, metadata_settings); } std::shared_ptr GetTablesForSQLAllTableTypes(const ColumnNames &names, FlightCallOptions &call_options, FlightSqlClient &sql_client, - odbcabstraction::Diagnostics &diagnostics) { + odbcabstraction::Diagnostics &diagnostics, + const odbcabstraction::MetadataSettings &metadata_settings) { Result> result = sql_client.GetTableTypes(call_options); @@ -139,7 +141,7 @@ GetTablesForSQLAllTableTypes(const ColumnNames &names, .Build(); return std::make_shared(sql_client, call_options, - flight_info, transformer, diagnostics); + flight_info, transformer, diagnostics, metadata_settings); } std::shared_ptr GetTablesForGenericUse( @@ -147,7 +149,7 @@ std::shared_ptr GetTablesForGenericUse( FlightSqlClient &sql_client, const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::vector &table_types, - odbcabstraction::Diagnostics &diagnostics) { + odbcabstraction::Diagnostics &diagnostics, const odbcabstraction::MetadataSettings &metadata_settings) { Result> result = sql_client.GetTables( call_options, catalog_name, schema_name, table_name, false, &table_types); @@ -167,7 +169,7 @@ std::shared_ptr GetTablesForGenericUse( .Build(); return std::make_shared(sql_client, call_options, - flight_info, transformer, diagnostics); + flight_info, transformer, diagnostics, metadata_settings); } } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h index cdbdba104bb1f..57b5aecc60a12 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h @@ -6,10 +6,12 @@ #pragma once +#include "flight_sql_connection.h" #include "arrow/flight/types.h" #include #include #include "record_batch_transformer.h" +#include "odbcabstraction/types.h" #include #include @@ -35,23 +37,27 @@ std::shared_ptr GetTablesForSQLAllCatalogs(const ColumnNames &column_names, FlightCallOptions &call_options, FlightSqlClient &sql_client, - odbcabstraction::Diagnostics &diagnostics); + odbcabstraction::Diagnostics &diagnostics, + const odbcabstraction::MetadataSettings &metadata_settings); + std::shared_ptr GetTablesForSQLAllDbSchemas( const ColumnNames &column_names, FlightCallOptions &call_options, FlightSqlClient &sql_client, const std::string *schema_name, - odbcabstraction::Diagnostics &diagnostics); + odbcabstraction::Diagnostics &diagnostics, const odbcabstraction::MetadataSettings &metadata_settings); std::shared_ptr GetTablesForSQLAllTableTypes(const ColumnNames &column_names, FlightCallOptions &call_options, FlightSqlClient &sql_client, - odbcabstraction::Diagnostics &diagnostics); + odbcabstraction::Diagnostics &diagnostics, + const odbcabstraction::MetadataSettings &metadata_settings); std::shared_ptr GetTablesForGenericUse( const ColumnNames &column_names, FlightCallOptions &call_options, FlightSqlClient &sql_client, const std::string *catalog_name, const std::string *schema_name, const std::string *table_name, const std::vector &table_types, - odbcabstraction::Diagnostics &diagnostics); + odbcabstraction::Diagnostics &diagnostics, + const odbcabstraction::MetadataSettings &metadata_settings); } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index ba9b683e5a01d..85de12d89badb 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -162,5 +162,9 @@ enum RowStatus: uint16_t { RowStatus_NOROW = 3 // Same as SQL_ROW_NOROW }; +struct MetadataSettings { + int32_t string_column_length_{1024}; +}; + } // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h index a9d030df8693f..7e73e7d302d1b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h @@ -28,5 +28,26 @@ bool AsBool(const std::string& value, bool default_value); /// \return the parsed valued. bool AsBool(bool default_value, const Connection::ConnPropertyMap& connPropertyMap, const std::string& property_name); + +/// Parse a string value to an int32_t. +/// \param value the value to be parsed. +/// \param default_value the default value in case the parse fails. +/// \param min_value the minimum value to be parsed, else the default value is returned. +/// \return the parsed valued. +/// \exception std::invalid_argument exception from \link std::stoi \endlink +/// \exception std::out_of_range exception from \link std::stoi \endlink +int32_t AsInt32(const std::string& value, int32_t default_value, int32_t min_value); + +/// Looks up for a value inside the ConnPropertyMap and then try to parse it. +/// In case it does not find or it cannot parse, the default value will be returned. +/// \param default_value the default value to be parsed. +/// \param min_value the minimum value to be parsed, else the default value is returned. +/// \param connPropertyMap the map with the connection properties. +/// \param property_name the name of the property that will be looked up. +/// \return the parsed valued. +/// \exception std::invalid_argument exception from \link std::stoi \endlink +/// \exception std::out_of_range exception from \link std::stoi \endlink +int32_t AsInt32(int32_t default_value, int32_t min_value, const Connection::ConnPropertyMap& connPropertyMap, + const std::string& property_name); } // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc index 9bd9e55b1285c..6ab21aec30791 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc @@ -34,5 +34,29 @@ bool AsBool(bool default_value, const Connection::ConnPropertyMap& connPropertyM return default_value; } } + +int32_t AsInt32(const std::string& value, int32_t default_value, int32_t min_value) { + const int32_t string_column_length = std::stoi(value); + + if (string_column_length >= min_value && string_column_length <= INT32_MAX) { + return string_column_length; + } else { + return default_value; + } +} + +int32_t AsInt32(int32_t default_value, int32_t min_value, const Connection::ConnPropertyMap& connPropertyMap, + const std::string& property_name) { + + auto extracted_property = connPropertyMap.find( + property_name); + + if (extracted_property != connPropertyMap.end()) { + return AsInt32(extracted_property->second, default_value, min_value); + } + else { + return default_value; + } +} } // namespace odbcabstraction } // namespace driver From fe51579e125ba9438c38e57841eb4243508b1ed9 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 28 Jun 2022 13:43:23 -0300 Subject: [PATCH 149/183] Add UseWideChar property to connection This makes the driver consider using wide chars (2 or 4 bytes wide) instead of single-byte chars by default on Windows. Also allows changing whether to use CHAR or WCHAR with a "UseWideCHar" property on DSN. Should help preventing encoding issues. Change-Id: Ia8a4ad5294071bbf59926c6131637d685a60ad69 --- .../flight_sql/flight_sql_connection.cc | 19 +++++++++-- .../flight_sql/flight_sql_connection.h | 3 ++ .../flight_sql/flight_sql_connection_test.cc | 17 ++++++++++ .../flight_sql/flight_sql_result_set.h | 4 +++ .../flight_sql_result_set_column.cc | 2 +- .../flight_sql_result_set_metadata.cc | 24 ++++++------- .../flight_sql_result_set_metadata.h | 2 -- .../flight_sql/flight_sql_statement.cc | 8 ++--- .../flight_sql_statement_get_columns.cc | 12 ++++--- .../flight_sql_statement_get_columns.h | 5 ++- .../flight_sql_statement_get_tables.h | 1 + .../flight_sql_statement_get_type_info.cc | 14 +++++--- .../flight_sql_statement_get_type_info.h | 7 ++-- .../flightsql-odbc/flight_sql/main.cc | 3 +- .../flightsql-odbc/flight_sql/utils.cc | 34 ++++++++++++++++--- .../flightsql-odbc/flight_sql/utils.h | 6 ++-- .../include/odbcabstraction/types.h | 1 + 17 files changed, 121 insertions(+), 41 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index fbb155b154551..6c451f4715003 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -59,12 +59,14 @@ const std::string FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION = "disab const std::string FlightSqlConnection::TRUSTED_CERTS = "trustedCerts"; const std::string FlightSqlConnection::USE_SYSTEM_TRUST_STORE = "useSystemTrustStore"; const std::string FlightSqlConnection::STRING_COLUMN_LENGTH = "StringColumnLength"; +const std::string FlightSqlConnection::USE_WIDE_CHAR = "UseWideChar"; const std::vector FlightSqlConnection::ALL_KEYS = { FlightSqlConnection::DSN, FlightSqlConnection::DRIVER, FlightSqlConnection::HOST, FlightSqlConnection::PORT, FlightSqlConnection::TOKEN, FlightSqlConnection::UID, FlightSqlConnection::USER_ID, FlightSqlConnection::PWD, FlightSqlConnection::USE_ENCRYPTION, FlightSqlConnection::TRUSTED_CERTS, FlightSqlConnection::USE_SYSTEM_TRUST_STORE, - FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, FlightSqlConnection::STRING_COLUMN_LENGTH }; + FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, FlightSqlConnection::STRING_COLUMN_LENGTH, + FlightSqlConnection::USE_WIDE_CHAR}; namespace { @@ -117,7 +119,8 @@ const std::set BUILT_IN_PROP FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, FlightSqlConnection::TRUSTED_CERTS, FlightSqlConnection::USE_SYSTEM_TRUST_STORE, - FlightSqlConnection::STRING_COLUMN_LENGTH + FlightSqlConnection::STRING_COLUMN_LENGTH, + FlightSqlConnection::USE_WIDE_CHAR }; Connection::ConnPropertyMap::const_iterator @@ -190,6 +193,7 @@ void FlightSqlConnection::Connect(const ConnPropertyMap &properties, void FlightSqlConnection::PopulateMetadataSettings(const Connection::ConnPropertyMap &conn_property_map) { metadata_settings_.string_column_length_ = GetStringColumnLength(conn_property_map); + metadata_settings_.use_wide_char_ = GetUseWideChar(conn_property_map); } int32_t FlightSqlConnection::GetStringColumnLength(const Connection::ConnPropertyMap &conn_property_map) { @@ -216,6 +220,17 @@ int32_t FlightSqlConnection::GetStringColumnLength(const Connection::ConnPropert return string_column_length; } +bool FlightSqlConnection::GetUseWideChar(const ConnPropertyMap &connPropertyMap) { + #if defined _WIN32 || defined _WIN64 + // Windows should use wide chars by default + bool default_value = true; + #else + // Mac and Linux should not use wide chars by default + bool default_value = false; +#endif + return AsBool(default_value, connPropertyMap, FlightSqlConnection::USE_WIDE_CHAR); +} + const FlightCallOptions & FlightSqlConnection::PopulateCallOptions(const ConnPropertyMap &props) { // Set CONNECTION_TIMEOUT attribute or LOGIN_TIMEOUT depending on if this diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index e84e2dbab6530..d2f7193a83aec 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -59,6 +59,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { static const std::string TRUSTED_CERTS; static const std::string USE_SYSTEM_TRUST_STORE; static const std::string STRING_COLUMN_LENGTH; + static const std::string USE_WIDE_CHAR; explicit FlightSqlConnection(odbcabstraction::OdbcVersion odbc_version); @@ -100,6 +101,8 @@ class FlightSqlConnection : public odbcabstraction::Connection { void SetClosed(bool is_closed); int32_t GetStringColumnLength(const ConnPropertyMap &connPropertyMap); + + bool GetUseWideChar(const ConnPropertyMap &connPropertyMap); }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index 58001e90e551d..a68223f3789bd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -73,6 +73,23 @@ TEST(MetadataSettingsTest, StringColumnLengthTest) { connection.Close(); } +TEST(MetadataSettingsTest, UseWideCharTest) { + FlightSqlConnection connection(odbcabstraction::V_3); + connection.SetClosed(false); + + const Connection::ConnPropertyMap properties1 = { + {FlightSqlConnection::USE_WIDE_CHAR, std::string("true")}, + }; + const Connection::ConnPropertyMap properties2 = { + {FlightSqlConnection::USE_WIDE_CHAR, std::string("false")}, + }; + + EXPECT_EQ(true, connection.GetUseWideChar(properties1)); + EXPECT_EQ(false, connection.GetUseWideChar(properties2)); + + connection.Close(); +} + TEST(BuildLocationTests, ForTcp) { std::vector missing_attr; Connection::ConnPropertyMap properties = { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index 13c9eb019f6be..0a96633388d53 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -83,6 +83,10 @@ class FlightSqlResultSet : public ResultSet { void BindColumn(int column_n, int16_t target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) override; + + inline bool UseWideChar() { + return metadata_settings_.use_wide_char_; + } }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index 2468d2252569a..a8329f9b6db3c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -46,7 +46,7 @@ FlightSqlResultSetColumn::GetAccessorForTargetType(CDataType target_type) { result_set_->GetArrayForColumn(column_n_); if (target_type == odbcabstraction::CDataType_DEFAULT) { - target_type = ConvertArrowTypeToC(original_array->type_id()); + target_type = ConvertArrowTypeToC(original_array->type_id(), result_set_->UseWideChar()); } // TODO: Figure out if that's the best way of caching diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index edbcd2133a394..8ec50961a25d5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -34,6 +34,10 @@ inline arrow::flight::sql::ColumnMetadata GetMetadata(const std::shared_ptr GetFieldPrecision(const std::shared_ptr &field) { + return GetMetadata(field).GetPrecision(); +} } size_t FlightSqlResultSetMetadata::GetColumnCount() { @@ -52,7 +56,7 @@ size_t FlightSqlResultSetMetadata::GetPrecision(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); int32_t column_size = GetFieldPrecision(field).ValueOrElse([] { return 0; }); - SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field, metadata_settings_.use_wide_char_); return GetColumnSize(data_type_v3, column_size).value_or(0); } @@ -62,14 +66,14 @@ size_t FlightSqlResultSetMetadata::GetScale(int column_position) { arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); int32_t type_scale = metadata.GetScale().ValueOrElse([] { return 0; }); - SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field, metadata_settings_.use_wide_char_); return GetTypeScale(data_type_v3, type_scale).value_or(0); } uint16_t FlightSqlResultSetMetadata::GetDataType(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - const SqlDataType conciseType = GetDataTypeFromArrowField_V3(field); + const SqlDataType conciseType = GetDataTypeFromArrowField_V3(field, metadata_settings_.use_wide_char_); return GetNonConciseDataType(conciseType); } @@ -106,7 +110,7 @@ size_t FlightSqlResultSetMetadata::GetColumnDisplaySize( const std::shared_ptr &field = schema_->field(column_position - 1); int32_t column_size = GetFieldPrecision(field).ValueOrElse([this] { return metadata_settings_.string_column_length_; }); - SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field, metadata_settings_.use_wide_char_); return GetDisplaySize(data_type_v3, column_size).value_or(NO_TOTAL); } @@ -123,7 +127,7 @@ std::string FlightSqlResultSetMetadata::GetBaseTableName(int column_position) { uint16_t FlightSqlResultSetMetadata::GetConciseType(int column_position) { const std::shared_ptr &field = schema_->field(column_position -1); - const SqlDataType sqlColumnType = GetDataTypeFromArrowField_V3(field); + const SqlDataType sqlColumnType = GetDataTypeFromArrowField_V3(field, metadata_settings_.use_wide_char_); return sqlColumnType; } @@ -131,15 +135,11 @@ size_t FlightSqlResultSetMetadata::GetLength(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); int32_t column_size = GetFieldPrecision(field).ValueOrElse([this] { return metadata_settings_.string_column_length_; }); - SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field, metadata_settings_.use_wide_char_); return GetBufferLength(data_type_v3, column_size).value_or(metadata_settings_.string_column_length_); } -arrow::Result FlightSqlResultSetMetadata::GetFieldPrecision(const std::shared_ptr &field) { - return GetMetadata(field).GetPrecision(); -} - std::string FlightSqlResultSetMetadata::GetLiteralPrefix(int column_position) { // TODO: Flight SQL column metadata does not have this, should we add to the spec? return ""; @@ -159,7 +159,7 @@ std::string FlightSqlResultSetMetadata::GetLocalTypeName(int column_position) { size_t FlightSqlResultSetMetadata::GetNumPrecRadix(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field, metadata_settings_.use_wide_char_); return GetRadixFromSqlDataType(data_type_v3).value_or(NO_TOTAL); } @@ -169,7 +169,7 @@ size_t FlightSqlResultSetMetadata::GetOctetLength(int column_position) { arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); arrow::Result column_size = GetFieldPrecision(field); - SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field); + SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field, metadata_settings_.use_wide_char_); // Workaround to get the precision for Decimal and Numeric types, since server doesn't return it currently. // TODO: Use the server precision when its fixed. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h index c96461edaf183..cd48cc0fa11c6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.h @@ -82,8 +82,6 @@ class FlightSqlResultSetMetadata : public odbcabstraction::ResultSetMetadata { bool IsUnsigned(int column_position) override; bool IsFixedPrecScale(int column_position) override; - - arrow::Result GetFieldPrecision(const std::shared_ptr &field); }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc index f8d81dcd07058..943a35589c6ad 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement.cc @@ -213,7 +213,7 @@ std::shared_ptr FlightSqlStatement::GetColumns_V2( auto flight_info = result.ValueOrDie(); auto transformer = std::make_shared( - odbcabstraction::V_2, column_name); + metadata_settings_, odbcabstraction::V_2, column_name); current_result_set_ = std::make_shared( sql_client_, call_options_, flight_info, transformer, diagnostics_, metadata_settings_); @@ -233,7 +233,7 @@ std::shared_ptr FlightSqlStatement::GetColumns_V3( auto flight_info = result.ValueOrDie(); auto transformer = std::make_shared( - odbcabstraction::V_3, column_name); + metadata_settings_, odbcabstraction::V_3, column_name); current_result_set_ = std::make_shared( sql_client_, call_options_, flight_info, transformer, diagnostics_, metadata_settings_); @@ -251,7 +251,7 @@ std::shared_ptr FlightSqlStatement::GetTypeInfo_V2(int16_t data_type) auto flight_info = result.ValueOrDie(); auto transformer = std::make_shared( - odbcabstraction::V_2, data_type); + metadata_settings_, odbcabstraction::V_2, data_type); current_result_set_ = std::make_shared( sql_client_, call_options_, flight_info, transformer, diagnostics_, metadata_settings_); @@ -269,7 +269,7 @@ std::shared_ptr FlightSqlStatement::GetTypeInfo_V3(int16_t data_type) auto flight_info = result.ValueOrDie(); auto transformer = std::make_shared( - odbcabstraction::V_3, data_type); + metadata_settings_, odbcabstraction::V_3, data_type); current_result_set_ = std::make_shared( sql_client_, call_options_, flight_info, transformer, diagnostics_, metadata_settings_); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc index 7cbd633bc1e64..49994eb1e95c4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.cc @@ -6,6 +6,7 @@ #include "flight_sql_statement_get_columns.h" #include +#include "flight_sql_connection.h" #include "flight_sql_get_tables_reader.h" #include "utils.h" #include @@ -68,7 +69,8 @@ std::shared_ptr GetColumns_V2_Schema() { Result> Transform_inner(const odbcabstraction::OdbcVersion odbc_version, const std::shared_ptr &original, - const optional &column_name_pattern) { + const optional &column_name_pattern, + const MetadataSettings& metadata_settings) { GetColumns_RecordBatchBuilder builder(odbc_version); GetColumns_RecordBatchBuilder::Data data; @@ -101,7 +103,7 @@ Transform_inner(const odbcabstraction::OdbcVersion odbc_version, } odbcabstraction::SqlDataType data_type_v3 = - GetDataTypeFromArrowField_V3(field); + GetDataTypeFromArrowField_V3(field, metadata_settings.use_wide_char_); ColumnMetadata metadata(field->metadata()); @@ -227,9 +229,11 @@ Status GetColumns_RecordBatchBuilder::Append( } GetColumns_Transformer::GetColumns_Transformer( + const MetadataSettings& metadata_settings, const odbcabstraction::OdbcVersion odbc_version, const std::string *column_name_pattern) - : odbc_version_(odbc_version), + : metadata_settings_(metadata_settings), + odbc_version_(odbc_version), column_name_pattern_( column_name_pattern ? make_optional(*column_name_pattern) : nullopt) { } @@ -237,7 +241,7 @@ GetColumns_Transformer::GetColumns_Transformer( std::shared_ptr GetColumns_Transformer::Transform( const std::shared_ptr &original) { const Result> &result = - Transform_inner(odbc_version_, original, column_name_pattern_); + Transform_inner(odbc_version_, original, column_name_pattern_, metadata_settings_); ThrowIfNotOK(result.status()); return result.ValueOrDie(); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.h index bc829af65467c..d5bbc47752689 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_columns.h @@ -14,6 +14,7 @@ namespace driver { namespace flight_sql { +using odbcabstraction::MetadataSettings; using arrow::util::optional; class GetColumns_RecordBatchBuilder { @@ -72,11 +73,13 @@ class GetColumns_RecordBatchBuilder { class GetColumns_Transformer : public RecordBatchTransformer { private: + const MetadataSettings& metadata_settings_; odbcabstraction::OdbcVersion odbc_version_; optional column_name_pattern_; public: - explicit GetColumns_Transformer(odbcabstraction::OdbcVersion odbc_version_, + explicit GetColumns_Transformer(const MetadataSettings& metadata_settings, + odbcabstraction::OdbcVersion odbc_version, const std::string *column_name_pattern); std::shared_ptr diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h index 57b5aecc60a12..80d4a4d1f22b1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_tables.h @@ -21,6 +21,7 @@ namespace flight_sql { using arrow::flight::FlightCallOptions; using arrow::flight::sql::FlightSqlClient; using odbcabstraction::ResultSet; +using odbcabstraction::MetadataSettings; typedef struct { std::string catalog_column; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc index b8b61bb779391..331caa1fc75ff 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc @@ -7,6 +7,7 @@ #include "flight_sql_statement_get_type_info.h" #include #include "flight_sql_get_type_info_reader.h" +#include "flight_sql_connection.h" #include "utils.h" #include @@ -65,14 +66,15 @@ std::shared_ptr GetTypeInfo_V2_Schema() { Result> Transform_inner(const odbcabstraction::OdbcVersion odbc_version, const std::shared_ptr &original, - int data_type) { + int data_type, + const MetadataSettings& metadata_settings_) { GetTypeInfo_RecordBatchBuilder builder(odbc_version); GetTypeInfo_RecordBatchBuilder::Data data; GetTypeInfoReader reader(original); while (reader.Next()) { - auto data_type_v3 = static_cast(reader.GetDataType()); + auto data_type_v3 = EnsureRightSqlCharType(static_cast(reader.GetDataType()), metadata_settings_.use_wide_char_); int16_t data_type_v2 = ConvertSqlDataTypeFromV3ToV2(data_type_v3); if (data_type != odbcabstraction::ALL_TYPES && data_type_v3 != data_type && data_type_v2 != data_type) { @@ -103,7 +105,7 @@ Transform_inner(const odbcabstraction::OdbcVersion odbc_version, data.local_type_name = reader.GetLocalTypeName(); data.minimum_scale = reader.GetMinimumScale(); data.maximum_scale = reader.GetMaximumScale(); - data.sql_data_type = static_cast(reader.GetSqlDataType()); + data.sql_data_type = EnsureRightSqlCharType(static_cast(reader.GetSqlDataType()), metadata_settings_.use_wide_char_); data.sql_datetime_sub = GetSqlDateTimeSubCode(static_cast(data.data_type)); data.num_prec_radix = reader.GetNumPrecRadix(); data.interval_precision = reader.GetIntervalPrecision(); @@ -196,16 +198,18 @@ Status GetTypeInfo_RecordBatchBuilder::Append( } GetTypeInfo_Transformer::GetTypeInfo_Transformer( + const MetadataSettings& metadata_settings, const odbcabstraction::OdbcVersion odbc_version, int data_type) - : odbc_version_(odbc_version), + : metadata_settings_(metadata_settings), + odbc_version_(odbc_version), data_type_(data_type) { } std::shared_ptr GetTypeInfo_Transformer::Transform( const std::shared_ptr &original) { const Result> &result = - Transform_inner(odbc_version_, original, data_type_); + Transform_inner(odbc_version_, original, data_type_, metadata_settings_); ThrowIfNotOK(result.status()); return result.ValueOrDie(); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.h index 1ada1bc22caa0..5b94c14319c3b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.h @@ -14,6 +14,7 @@ namespace driver { namespace flight_sql { +using odbcabstraction::MetadataSettings; using arrow::util::optional; class GetTypeInfo_RecordBatchBuilder { @@ -74,12 +75,14 @@ class GetTypeInfo_RecordBatchBuilder { class GetTypeInfo_Transformer : public RecordBatchTransformer { private: + const MetadataSettings& metadata_settings_; odbcabstraction::OdbcVersion odbc_version_; int data_type_; public: - explicit GetTypeInfo_Transformer(odbcabstraction::OdbcVersion odbc_version_, - int data_type_); + explicit GetTypeInfo_Transformer(const MetadataSettings& metadata_settings, + odbcabstraction::OdbcVersion odbc_version, + int data_type); std::shared_ptr Transform(const std::shared_ptr &original) override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 231f210150572..034f095e9956d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -200,10 +200,11 @@ int main() { driver.CreateConnection(driver::odbcabstraction::V_3); Connection::ConnPropertyMap properties = { - {FlightSqlConnection::HOST, std::string("0.0.0.0")}, + {FlightSqlConnection::HOST, std::string("automaster.drem.io")}, {FlightSqlConnection::PORT, std::string("32010")}, {FlightSqlConnection::USER, std::string("dremio")}, {FlightSqlConnection::PASSWORD, std::string("dremio123")}, + {FlightSqlConnection::USE_ENCRYPTION, std::string("false")}, }; std::vector missing_attr; connection->Connect(properties, missing_attr); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 00334162e5ad6..fa248b46be0fc 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -38,6 +38,17 @@ bool IsComplexType(arrow::Type::type type_id) { return false; } } + +odbcabstraction::SqlDataType GetDefaultSqlCharType(bool useWideChar) { + return useWideChar ? odbcabstraction::SqlDataType_WCHAR : odbcabstraction::SqlDataType_CHAR; +} +odbcabstraction::SqlDataType GetDefaultSqlVarcharType(bool useWideChar) { + return useWideChar ? odbcabstraction::SqlDataType_WVARCHAR : odbcabstraction::SqlDataType_VARCHAR; +} +odbcabstraction::CDataType GetDefaultCCharType(bool useWideChar) { + return useWideChar ? odbcabstraction::CDataType_WCHAR : odbcabstraction::CDataType_CHAR; +} + } using namespace odbcabstraction; @@ -50,7 +61,7 @@ using arrow::util::nullopt; /// \note use GetNonConciseDataType on the output to get the verbose type /// \note the concise and verbose types are the same for all but types relating to times and intervals SqlDataType -GetDataTypeFromArrowField_V3(const std::shared_ptr &field) { +GetDataTypeFromArrowField_V3(const std::shared_ptr &field, bool useWideChar) { const std::shared_ptr &type = field->type(); switch (type->id()) { @@ -79,7 +90,7 @@ GetDataTypeFromArrowField_V3(const std::shared_ptr &field) { return odbcabstraction::SqlDataType_BINARY; case arrow::Type::STRING: case arrow::Type::LARGE_STRING: - return odbcabstraction::SqlDataType_VARCHAR; + return GetDefaultSqlCharType(useWideChar); case arrow::Type::DATE32: case arrow::Type::DATE64: return odbcabstraction::SqlDataType_TYPE_DATE; @@ -112,7 +123,20 @@ GetDataTypeFromArrowField_V3(const std::shared_ptr &field) { break; } - return odbcabstraction::SqlDataType_VARCHAR; + return GetDefaultSqlCharType(useWideChar); +} + +SqlDataType EnsureRightSqlCharType(SqlDataType data_type, bool useWideChar) { + switch (data_type) { + case SqlDataType_CHAR: + case SqlDataType_WCHAR: + return GetDefaultSqlCharType(useWideChar); + case SqlDataType_VARCHAR: + case SqlDataType_WVARCHAR: + return GetDefaultSqlVarcharType(useWideChar); + default: + return data_type; + } } int16_t ConvertSqlDataTypeFromV3ToV2(int16_t data_type_v3) { @@ -751,10 +775,10 @@ ConvertCToArrowType(odbcabstraction::CDataType data_type) { } } -odbcabstraction::CDataType ConvertArrowTypeToC(arrow::Type::type type_id) { +odbcabstraction::CDataType ConvertArrowTypeToC(arrow::Type::type type_id, bool useWideChar) { switch (type_id) { case arrow::Type::STRING: - return odbcabstraction::CDataType_CHAR; + return GetDefaultCCharType(useWideChar); case arrow::Type::INT16: return odbcabstraction::CDataType_SSHORT; case arrow::Type::UINT16: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index 71f7f5ecff45b..b87da077341d1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -58,7 +58,9 @@ arrow::Status AppendToBuilder(BUILDER &builder, T value) { } odbcabstraction::SqlDataType -GetDataTypeFromArrowField_V3(const std::shared_ptr &field); +GetDataTypeFromArrowField_V3(const std::shared_ptr &field, bool useWideChar); + +odbcabstraction::SqlDataType EnsureRightSqlCharType(odbcabstraction::SqlDataType data_type, bool useWideChar); int16_t ConvertSqlDataTypeFromV3ToV2(int16_t data_type_v3); @@ -100,7 +102,7 @@ std::shared_ptr GetDefaultDataTypeForTypeId(arrow::Type::type t arrow::Type::type ConvertCToArrowType(odbcabstraction::CDataType data_type); -odbcabstraction::CDataType ConvertArrowTypeToC(arrow::Type::type type_id); +odbcabstraction::CDataType ConvertArrowTypeToC(arrow::Type::type type_id, bool useWideChar); std::shared_ptr CheckConversion(const arrow::Result &result); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 85de12d89badb..5aa815b606f55 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -164,6 +164,7 @@ enum RowStatus: uint16_t { struct MetadataSettings { int32_t string_column_length_{1024}; + bool use_wide_char_; }; } // namespace odbcabstraction From 77e27a360a1618e87c4c92cc68fb9367613566c3 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Fri, 24 Jun 2022 17:24:31 -0300 Subject: [PATCH 150/183] Try to get the CN from the ip - It adds a call to getaddrinfo, which tries to get the CN from the ip Change-Id: I403efd45f0397379ac6f78e82e02e44d9fb34d33 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 2 + .../flightsql-odbc/flight_sql/address_info.cc | 37 +++++++++++++++++++ .../flightsql-odbc/flight_sql/address_info.h | 30 +++++++++++++++ .../flight_sql/flight_sql_connection.cc | 18 ++++++++- .../include/odbcabstraction/platform.h | 5 ++- 5 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/address_info.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/address_info.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 584c9c95943e8..20e8f0fdd2da5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -157,6 +157,8 @@ set(ARROW_ODBC_SPI_SOURCES 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 diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/address_info.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/address_info.cc new file mode 100644 index 0000000000000..1a88dca0783e0 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/address_info.cc @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#include "address_info.h" + +namespace driver { + +bool AddressInfo::GetAddressInfo(const std::string &host, char *host_name_info, int64_t max_host) { + if (addrinfo_result_) { + freeaddrinfo(addrinfo_result_); + addrinfo_result_ = nullptr; + } + + int error; + error = getaddrinfo(host.c_str(), NULL, NULL, &addrinfo_result_); + + if (error != 0) { + return false; + } + + error = getnameinfo(addrinfo_result_->ai_addr, addrinfo_result_->ai_addrlen, host_name_info, + max_host, NULL, 0, 0); + return error == 0; +} + +AddressInfo::~AddressInfo() { + if (addrinfo_result_) { + freeaddrinfo(addrinfo_result_); + addrinfo_result_ = nullptr; + } +} + +AddressInfo::AddressInfo() : addrinfo_result_(nullptr) {} +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/address_info.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/address_info.h new file mode 100644 index 0000000000000..77d8b28e75c21 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/address_info.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#pragma once + +#include + +#include +#include +#if !_WIN32 +#include +#endif + +namespace driver { + +class AddressInfo { +private: + struct addrinfo * addrinfo_result_; + +public: + AddressInfo(); + + ~AddressInfo(); + + bool GetAddressInfo(const std::string &host, char *host_name_info, int64_t max_host); +}; +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 6c451f4715003..40b68328afac0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -11,6 +11,7 @@ #include #include +#include "address_info.h" #include "flight_sql_auth_method.h" #include "flight_sql_statement.h" #include "flight_sql_ssl_config.h" @@ -27,6 +28,10 @@ #include "system_trust_store.h" +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif + namespace driver { namespace flight_sql { @@ -41,6 +46,7 @@ using arrow::flight::sql::FlightSqlClient; using driver::odbcabstraction::AsBool; using driver::odbcabstraction::Connection; using driver::odbcabstraction::DriverException; +using driver::odbcabstraction::CommunicationException; using driver::odbcabstraction::OdbcVersion; using driver::odbcabstraction::Statement; @@ -316,7 +322,17 @@ FlightSqlConnection::BuildLocation(const ConnPropertyMap &properties, Location location; if (ssl_config->useEncryption()) { - ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); + AddressInfo address_info; + + char host_name_info[NI_MAXHOST] = ""; + bool operation_result = address_info.GetAddressInfo(host, host_name_info, + NI_MAXHOST); + + if (operation_result) { + ThrowIfNotOK(Location::ForGrpcTls(host_name_info, port, &location)); + } else { + ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); + } } else { ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h index 52affed1e4928..089ad5ff06f16 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/platform.h @@ -18,7 +18,10 @@ #endif #include - + + #include + #include + #include typedef SSIZE_T ssize_t; From 4a6d696b4961d00dd9662f6e4ed3e82413907b6d Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 28 Jun 2022 16:42:09 -0300 Subject: [PATCH 151/183] Fix utils' GetDataTypeFromArrowField_V3 wrong return for string types Change-Id: Ifc659e4ebfb380051279c13bf7380b532da3ef20 --- .../flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index fa248b46be0fc..84d8da51e3da6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -90,7 +90,7 @@ GetDataTypeFromArrowField_V3(const std::shared_ptr &field, bool us return odbcabstraction::SqlDataType_BINARY; case arrow::Type::STRING: case arrow::Type::LARGE_STRING: - return GetDefaultSqlCharType(useWideChar); + return GetDefaultSqlVarcharType(useWideChar); case arrow::Type::DATE32: case arrow::Type::DATE64: return odbcabstraction::SqlDataType_TYPE_DATE; @@ -123,7 +123,7 @@ GetDataTypeFromArrowField_V3(const std::shared_ptr &field, bool us break; } - return GetDefaultSqlCharType(useWideChar); + return GetDefaultSqlVarcharType(useWideChar); } SqlDataType EnsureRightSqlCharType(SqlDataType data_type, bool useWideChar) { From eeba546934e60d8fe28cddd2b1d258eee3c2b66f Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 28 Jun 2022 17:43:08 -0300 Subject: [PATCH 152/183] Allow setting SQL_DRIVER_VER externally Add a method to the Driver interface to set the driver version. This lets the consumer of the ODBC Abstraction layer override the version reported by SQLGetInfo(SQL_DRIVER_VER) Change-Id: I0146c99cef2ee1bc86663a4117337225cbd195c6 --- .../flightsql-odbc/flight_sql/flight_sql_connection.cc | 5 +++-- .../flightsql-odbc/flight_sql/flight_sql_connection.h | 2 +- .../flightsql-odbc/flight_sql/flight_sql_driver.cc | 9 +++++++-- .../flightsql-odbc/flight_sql/get_info_cache.cc | 6 +++--- .../flightsql-odbc/flight_sql/get_info_cache.h | 3 ++- .../flight_sql/include/flight_sql/flight_sql_driver.h | 3 +++ .../odbcabstraction/include/odbcabstraction/spi/driver.h | 3 +++ 7 files changed, 22 insertions(+), 9 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 40b68328afac0..9cb913e04e102 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -398,9 +398,9 @@ Connection::Info FlightSqlConnection::GetInfo(uint16_t info_type) { return result; } -FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version) +FlightSqlConnection::FlightSqlConnection(OdbcVersion odbc_version, const std::string &driver_version) : diagnostics_("Apache Arrow", "Flight SQL", odbc_version), - odbc_version_(odbc_version), info_(call_options_, sql_client_), + odbc_version_(odbc_version), info_(call_options_, sql_client_, driver_version), closed_(true) { attribute_[CONNECTION_DEAD] = static_cast(SQL_TRUE); attribute_[LOGIN_TIMEOUT] = static_cast(0); @@ -414,5 +414,6 @@ odbcabstraction::Diagnostics &FlightSqlConnection::GetDiagnostics() { void FlightSqlConnection::SetClosed(bool is_closed) { closed_ = is_closed; } + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index d2f7193a83aec..97d925d6dfe8b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -61,7 +61,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { static const std::string STRING_COLUMN_LENGTH; static const std::string USE_WIDE_CHAR; - explicit FlightSqlConnection(odbcabstraction::OdbcVersion odbc_version); + explicit FlightSqlConnection(odbcabstraction::OdbcVersion odbc_version, const std::string &driver_version = "0.9.0.0"); void Connect(const ConnPropertyMap &properties, std::vector &missing_attr) override; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index d9f16949e243d..8e731d3b4414f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -15,16 +15,21 @@ using odbcabstraction::Connection; using odbcabstraction::OdbcVersion; FlightSqlDriver::FlightSqlDriver() - : diagnostics_("Apache Arrow", "Flight SQL", OdbcVersion::V_3) + : diagnostics_("Apache Arrow", "Flight SQL", OdbcVersion::V_3), + version_("0.9.0.0") {} std::shared_ptr FlightSqlDriver::CreateConnection(OdbcVersion odbc_version) { - return std::make_shared(odbc_version); + return std::make_shared(odbc_version, version_); } odbcabstraction::Diagnostics &FlightSqlDriver::GetDiagnostics() { return diagnostics_; } + +void FlightSqlDriver::SetVersion(std::string version) { + version_ = std::move(version); +} } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc index 4443ea48dd4a2..0d08465a1575c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc @@ -194,11 +194,11 @@ using namespace arrow::flight; using namespace driver::odbcabstraction; GetInfoCache::GetInfoCache(FlightCallOptions &call_options, - std::unique_ptr &client) + std::unique_ptr &client, const std::string &driver_version) : call_options_(call_options), sql_client_(client), has_server_info_(false) { info_[SQL_DRIVER_NAME] = "Arrow Flight ODBC Driver"; - info_[SQL_DRIVER_VER] = ConvertToDBMSVer("0.9.0.0"); // This should be generated dynamically. + info_[SQL_DRIVER_VER] = ConvertToDBMSVer(driver_version); info_[SQL_GETDATA_EXTENSIONS] = static_cast(SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER); @@ -1191,7 +1191,7 @@ void GetInfoCache::LoadDefaultsForMissingEntries() { SetDefaultIfMissing(info_, SQL_DESCRIBE_PARAMETER, "N"); SetDefaultIfMissing(info_, SQL_DRIVER_NAME, "Arrow Flight SQL Driver"); SetDefaultIfMissing(info_, SQL_DRIVER_ODBC_VER, "03.80"); - SetDefaultIfMissing(info_, SQL_DRIVER_VER, "01.00.0000"); + SetDefaultIfMissing(info_, SQL_DRIVER_VER, "00.09.0000"); SetDefaultIfMissing(info_, SQL_DROP_ASSERTION, static_cast(0)); SetDefaultIfMissing(info_, SQL_DROP_CHARACTER_SET, static_cast(0)); SetDefaultIfMissing(info_, SQL_DROP_COLLATION, static_cast(0)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h index a859e9efdf3ff..20c2f47e11e6e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.h @@ -35,7 +35,8 @@ class GetInfoCache { public: GetInfoCache(arrow::flight::FlightCallOptions &call_options, - std::unique_ptr &client); + std::unique_ptr &client, + const std::string &driver_version); void SetProperty(uint16_t property, driver::odbcabstraction::Connection::Info value); driver::odbcabstraction::Connection::Info GetInfo(uint16_t info_type); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h index dec753970d7db..e55a7126c0359 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h @@ -15,6 +15,7 @@ namespace flight_sql { class FlightSqlDriver : public odbcabstraction::Driver { private: odbcabstraction::Diagnostics diagnostics_; + std::string version_; public: FlightSqlDriver(); @@ -23,6 +24,8 @@ class FlightSqlDriver : public odbcabstraction::Driver { CreateConnection(odbcabstraction::OdbcVersion odbc_version) override; odbcabstraction::Diagnostics &GetDiagnostics() override; + + void SetVersion(std::string version) override; }; }; // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h index 2a324a382807b..974704f7fbf3f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h @@ -32,6 +32,9 @@ class Driver { /// \brief Gets the diagnostics for this connection. /// \return the diagnostics virtual Diagnostics& GetDiagnostics() = 0; + + /// \brief Sets the driver version. + virtual void SetVersion(std::string version) = 0; }; } // namespace odbcabstraction From 38b33c4bc5760ebe967592f36887d0664ea97e62 Mon Sep 17 00:00:00 2001 From: James Duong Date: Wed, 29 Jun 2022 13:02:00 -0700 Subject: [PATCH 153/183] Fix crash when getting non-decimal data back as SQL_C_NUMERIC - Initialize a default precision when SQLBindCol with SQL_C_NUMERIC or when both the target is SQL_C_DEFAULT and the source type is decimal 128. - Use Arrow built-in functionality on decimal to determine the sign, rather than bit-shifting/masking. - The data in SQL_C_NUMERIC should always be unsigned in the array since the sign is a separate field. Convert Decimal128 to absolute values before writing to the SQL_C_NUMERIC array. This fixes handling negative numbers. Change-Id: I22b88b566790ad0bea5ff7bd237631596a89fb11 --- .../flight_sql/accessors/decimal_array_accessor.cc | 11 ++++++----- .../accessors/decimal_array_accessor_test.cc | 3 +++ .../flight_sql/flight_sql_result_set_column.cc | 7 +++++++ .../odbcabstraction/odbc_impl/ODBCDescriptor.cc | 6 ++++++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc index 4d82eabfb2b73..f850450f7e4c4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc @@ -42,14 +42,15 @@ RowStatus DecimalArrayFlightSqlAccessor::Mov throw DriverException("Decimal value doesn't fit in precision " + std::to_string(binding->precision)); } - uint8_t bytes[16]; - value.ToBytes(bytes); - memcpy(&result->val, bytes, 16); + result->sign = value.IsNegative() ? 0 : 1; + + // Take the absolute value since the ODBC SQL_NUMERIC_STRUCT holds + // a positive-only number. + Decimal128 abs_value = Decimal128::Abs(value); + abs_value.ToBytes(result->val); result->precision = static_cast(binding->precision); result->scale = static_cast(binding->scale); - // If the most significant bit is set this number is negative (sign = 1). - result->sign = (static_cast(result->val[15]) >> 7) == 1; result->precision = data_type_->precision(); if (binding->strlen_buffer) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc index c3d3f6a9660d3..3ee000717a616 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor_test.cc @@ -40,6 +40,9 @@ std::vector MakeDecimalVector(const std::vector &valu std::string ConvertNumericToString(NUMERIC_STRUCT &numeric) { auto v = reinterpret_cast(numeric.val); auto decimal = Decimal128(v[1], v[0]); + if (numeric.sign == 0) { + decimal.Negate(); + } const std::string &string = decimal.ToString(numeric.scale); return string; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index a8329f9b6db3c..adbdd04ab9e07 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -81,6 +81,13 @@ void FlightSqlResultSetColumn::SetBinding(ColumnBinding new_binding) { binding = new_binding; is_bound = true; + // Overwrite the binding if the caller is using SQL_C_NUMERIC and has used zero + // precision if it is zero (this is precision unset and will always fail). + if (binding.precision == 0 && + (binding.target_type == odbcabstraction::CDataType_NUMERIC) || + (binding.target_type == odbcabstraction::CDataType_DEFAULT && cached_original_array_->type_id() == arrow::Type::type::DECIMAL128)) { + binding.precision = arrow::Decimal128Type::kMaxPrecision; + } ResetAccessor(); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc index 2d1abcab6540a..5e0089f63c580 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc @@ -506,6 +506,12 @@ void ODBCDescriptor::BindCol(SQLSMALLINT recordNumber, SQLSMALLINT cType, SQLPOI record.m_type = cType; record.m_indicatorPtr = indicatorPtr; record.m_length = bufferLength; + + // Initialize default precision and scale for SQL_C_NUMERIC. + if (record.m_type == SQL_C_NUMERIC) { + record.m_precision = 38; + record.m_scale = 0; + } SetDataPtrOnRecord(dataPtr, recordNumber); } From fc7d48337d23dbc539bb89a937930ef1bf9d46c3 Mon Sep 17 00:00:00 2001 From: James Duong Date: Wed, 29 Jun 2022 15:22:51 -0700 Subject: [PATCH 154/183] Fix fractional seconds computation for SQL_C_TIMESTAMP Fix bug where the fractional seconds reported were in the units of the original arrow Timestamp/Time array rather than in terms of the ODBC SQL_NUMERIC_STRUCT (which are nanoseconds). Rename several functions to clarify what they do. Note: fractional second calculation for Micros and Millis is returns zero due to overflow issues. Change-Id: Id5c4e6a3f132519f3dd29d8d6fb0e2618bc4390e --- .../accessors/date_array_accessor.cc | 2 +- .../accessors/date_array_accessor_test.cc | 4 +- .../accessors/time_array_accessor.cc | 4 +- .../accessors/time_array_accessor_test.cc | 8 +-- .../accessors/timestamp_array_accessor.cc | 50 ++++++++++++++----- .../timestamp_array_accessor_test.cc | 21 ++++---- .../odbcabstraction/calendar_utils.cc | 4 +- .../include/odbcabstraction/calendar_utils.h | 2 +- 8 files changed, 62 insertions(+), 33 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc index e7312a8521644..47f7d9ea3f491 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc @@ -53,7 +53,7 @@ RowStatus DateArrayFlightSqlAccessor::MoveSingleCell_i auto value = convertDate(array->Value(cell_counter)); tm date{}; - GetTimeForMillisSinceEpoch(date, value); + GetTimeForSecondsSinceEpoch(date, value); buffer[cell_counter].year = 1900 + (date.tm_year); buffer[cell_counter].month = date.tm_mon + 1; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc index a590a13c91aee..13b9cada44df0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor_test.cc @@ -40,7 +40,7 @@ TEST(DateArrayAccessor, Test_Date32Array_CDataType_DATE) { tm date{}; int64_t converted_time = values[i] * 86400; - GetTimeForMillisSinceEpoch(date, converted_time); + GetTimeForSecondsSinceEpoch(date, converted_time); ASSERT_EQ((date.tm_year + 1900), buffer[i].year); ASSERT_EQ(date.tm_mon + 1, buffer[i].month); ASSERT_EQ(date.tm_mday, buffer[i].day); @@ -72,7 +72,7 @@ TEST(DateArrayAccessor, Test_Date64Array_CDataType_DATE) { tm date{}; int64_t converted_time = values[i] / 1000; - GetTimeForMillisSinceEpoch(date, converted_time); + GetTimeForSecondsSinceEpoch(date, converted_time); ASSERT_EQ((date.tm_year + 1900), buffer[i].year); ASSERT_EQ(date.tm_mon + 1, buffer[i].month); ASSERT_EQ(date.tm_mday, buffer[i].day); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc index a740463cac5e1..912b7b9a0feef 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc @@ -47,10 +47,10 @@ RowStatus TimeArrayFlightSqlAccessor::MoveSingleCell_i tm time{}; - auto converted_value = + auto converted_value_seconds = ConvertTimeValue(array->Value(cell_counter), time_unit); - GetTimeForMillisSinceEpoch(time, converted_value); + GetTimeForSecondsSinceEpoch(time, converted_value_seconds); buffer[cell_counter].hour = time.tm_hour; buffer[cell_counter].minute = time.tm_min; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc index 9633d94fbd6d1..884a29e545713 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc @@ -42,7 +42,7 @@ TEST(TEST_TIME32, TIME_WITH_SECONDS) { tm time{}; - GetTimeForMillisSinceEpoch(time, t32_values[i]); + GetTimeForSecondsSinceEpoch(time, t32_values[i]); ASSERT_EQ(buffer[i].hour, time.tm_hour); ASSERT_EQ(buffer[i].minute, time.tm_min); ASSERT_EQ(buffer[i].second, time.tm_sec); @@ -76,7 +76,7 @@ TEST(TEST_TIME32, TIME_WITH_MILLI) { tm time{}; auto convertedValue = t32_values[i] / MILLI_TO_SECONDS_DIVISOR; - GetTimeForMillisSinceEpoch(time, convertedValue); + GetTimeForSecondsSinceEpoch(time, convertedValue); ASSERT_EQ(buffer[i].hour, time.tm_hour); ASSERT_EQ(buffer[i].minute, time.tm_min); @@ -112,7 +112,7 @@ TEST(TEST_TIME64, TIME_WITH_MICRO) { tm time{}; const auto convertedValue = t64_values[i] / MICRO_TO_SECONDS_DIVISOR; - GetTimeForMillisSinceEpoch(time, convertedValue); + GetTimeForSecondsSinceEpoch(time, convertedValue); ASSERT_EQ(buffer[i].hour, time.tm_hour); ASSERT_EQ(buffer[i].minute, time.tm_min); @@ -148,7 +148,7 @@ TEST(TEST_TIME64, TIME_WITH_NANO) { tm time{}; const auto convertedValue = t64_values[i] / NANO_TO_SECONDS_DIVISOR; - GetTimeForMillisSinceEpoch(time, convertedValue); + GetTimeForSecondsSinceEpoch(time, convertedValue); ASSERT_EQ(buffer[i].hour, time.tm_hour); ASSERT_EQ(buffer[i].minute, time.tm_min); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc index 26432c7043674..f3e9a6c8d1316 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc @@ -10,23 +10,49 @@ using namespace arrow; namespace { -int64_t convertTimeStampBasedOnUnit(TimeUnit::type unit) { - int64_t converted_result; +int64_t GetConversionToSecondsDivisor(TimeUnit::type unit) { + int64_t divisor = 1; switch (unit) { case TimeUnit::SECOND: - converted_result = 1; + divisor = 1; break; case TimeUnit::MILLI: - converted_result = driver::flight_sql::MILLI_TO_SECONDS_DIVISOR; + divisor = driver::flight_sql::MILLI_TO_SECONDS_DIVISOR; break; case TimeUnit::MICRO: - converted_result = driver::flight_sql::MICRO_TO_SECONDS_DIVISOR; + divisor = driver::flight_sql::MICRO_TO_SECONDS_DIVISOR; break; case TimeUnit::NANO: - converted_result = driver::flight_sql::NANO_TO_SECONDS_DIVISOR; + divisor = driver::flight_sql::NANO_TO_SECONDS_DIVISOR; break; + default: + assert(false); + throw driver::odbcabstraction::DriverException("Unrecognized time unit value: " + std::to_string(unit)); } - return converted_result; + return divisor; +} + +uint32_t CalculateFraction(TimeUnit::type unit, uint64_t units_since_epoch) { + // Convert the given remainder and time unit to nanoseconds + // since the fraction field on TIMESTAMP_STRUCT is in nanoseconds. + switch (unit) { + case TimeUnit::SECOND: + return 0; + case TimeUnit::MILLI: + // 1000000 nanoseconds = 1 millisecond. + return (units_since_epoch % + driver::odbcabstraction::MILLI_TO_SECONDS_DIVISOR) * + 1000000; + case TimeUnit::MICRO: + // 1000 nanoseconds = 1 microsecond. + return (units_since_epoch % + driver::odbcabstraction::MICRO_TO_SECONDS_DIVISOR) * 1000; + case TimeUnit::NANO: + // 1000 nanoseconds = 1 microsecond. + return (units_since_epoch % + driver::odbcabstraction::NANO_TO_SECONDS_DIVISOR); + } + return 0; } } // namespace @@ -55,11 +81,11 @@ TimestampArrayFlightSqlAccessor::MoveSingleCell_impl(ColumnBinding auto *buffer = static_cast(binding->buffer); int64_t value = array->Value(cell_counter); - const auto divisor = convertTimeStampBasedOnUnit(timestamp_type_->unit()); - const auto converted_result = value / divisor; - tm timestamp{}; + const auto divisor = GetConversionToSecondsDivisor(timestamp_type_->unit()); + const auto converted_result_seconds = value / divisor; + tm timestamp = {0}; - GetTimeForMillisSinceEpoch(timestamp, converted_result); + GetTimeForSecondsSinceEpoch(timestamp, converted_result_seconds); buffer[cell_counter].year = 1900 + (timestamp.tm_year); buffer[cell_counter].month = timestamp.tm_mon + 1; @@ -67,7 +93,7 @@ TimestampArrayFlightSqlAccessor::MoveSingleCell_impl(ColumnBinding buffer[cell_counter].hour = timestamp.tm_hour; buffer[cell_counter].minute = timestamp.tm_min; buffer[cell_counter].second = timestamp.tm_sec; - buffer[cell_counter].fraction = value % divisor; + buffer[cell_counter].fraction = CalculateFraction(timestamp_type_->unit(), value); if (binding->strlen_buffer) { binding->strlen_buffer[cell_counter] = static_cast(GetCellLength_impl(binding)); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc index 93b860ae74a8e..079ab52132b6a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc @@ -16,7 +16,7 @@ namespace flight_sql { using namespace arrow; using namespace odbcabstraction; -TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MILI) { +TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MILLI) { std::vector values = {86400370, 172800000, 259200000, 1649793238110LL, 345600000, 432000000, 518400000}; @@ -43,7 +43,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MILI) { tm date{}; auto converted_time = values[i] / MILLI_TO_SECONDS_DIVISOR; - GetTimeForMillisSinceEpoch(date, converted_time); + GetTimeForSecondsSinceEpoch(date, converted_time); ASSERT_EQ(buffer[i].year, 1900 + (date.tm_year)); ASSERT_EQ(buffer[i].month, date.tm_mon + 1); @@ -51,7 +51,9 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MILI) { ASSERT_EQ(buffer[i].hour, date.tm_hour); ASSERT_EQ(buffer[i].minute, date.tm_min); ASSERT_EQ(buffer[i].second, date.tm_sec); - ASSERT_EQ(buffer[i].fraction, values[i] % MILLI_TO_SECONDS_DIVISOR); + + constexpr uint32_t NANOSECONDS_PER_MILLI = 1000000; + ASSERT_EQ(buffer[i].fraction, (values[i] % MILLI_TO_SECONDS_DIVISOR) * NANOSECONDS_PER_MILLI); } } @@ -82,7 +84,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_SECONDS) { tm date{}; auto converted_time = values[i]; - GetTimeForMillisSinceEpoch(date, converted_time); + GetTimeForSecondsSinceEpoch(date, converted_time); ASSERT_EQ(buffer[i].year, 1900 + (date.tm_year)); ASSERT_EQ(buffer[i].month, date.tm_mon + 1); @@ -90,7 +92,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_SECONDS) { ASSERT_EQ(buffer[i].hour, date.tm_hour); ASSERT_EQ(buffer[i].minute, date.tm_min); ASSERT_EQ(buffer[i].second, date.tm_sec); - ASSERT_EQ(buffer[i].fraction, values[i] % 1); + ASSERT_EQ(buffer[i].fraction, 0); } } @@ -121,7 +123,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MICRO) { tm date{}; auto converted_time = values[i] / MICRO_TO_SECONDS_DIVISOR; - GetTimeForMillisSinceEpoch(date, converted_time); + GetTimeForSecondsSinceEpoch(date, converted_time); ASSERT_EQ(buffer[i].year, 1900 + (date.tm_year)); ASSERT_EQ(buffer[i].month, date.tm_mon + 1); @@ -129,7 +131,8 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MICRO) { ASSERT_EQ(buffer[i].hour, date.tm_hour); ASSERT_EQ(buffer[i].minute, date.tm_min); ASSERT_EQ(buffer[i].second, date.tm_sec); - ASSERT_EQ(buffer[i].fraction, values[i] % MICRO_TO_SECONDS_DIVISOR); + constexpr uint32_t MICROS_PER_NANO = 1000; + ASSERT_EQ(buffer[i].fraction, (values[i] % MICRO_TO_SECONDS_DIVISOR) * MICROS_PER_NANO); } } @@ -159,7 +162,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_NANO) { tm date{}; auto converted_time = values[i] / NANO_TO_SECONDS_DIVISOR; - GetTimeForMillisSinceEpoch(date, converted_time); + GetTimeForSecondsSinceEpoch(date, converted_time); ASSERT_EQ(buffer[i].year, 1900 + (date.tm_year)); ASSERT_EQ(buffer[i].month, date.tm_mon + 1); @@ -167,7 +170,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_NANO) { ASSERT_EQ(buffer[i].hour, date.tm_hour); ASSERT_EQ(buffer[i].minute, date.tm_min); ASSERT_EQ(buffer[i].second, date.tm_sec); - ASSERT_EQ(buffer[i].fraction, values[i] % NANO_TO_SECONDS_DIVISOR); + ASSERT_EQ(buffer[i].fraction, (values[i] % NANO_TO_SECONDS_DIVISOR)); } } } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc index 566e0de37bfe7..5de958603f4da 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/calendar_utils.cc @@ -15,7 +15,7 @@ int64_t GetTodayTimeFromEpoch() { tm date{}; int64_t t = std::time(0); - GetTimeForMillisSinceEpoch(date, t); + GetTimeForSecondsSinceEpoch(date, t); date.tm_hour = 0; date.tm_min = 0; @@ -28,7 +28,7 @@ int64_t GetTodayTimeFromEpoch() { #endif } -void GetTimeForMillisSinceEpoch(tm& date, int64_t value) { +void GetTimeForSecondsSinceEpoch(tm& date, int64_t value) { #if defined(_WIN32) gmtime_s(&date, &value); #else diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h index bfd6362660041..768b2addb1081 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/calendar_utils.h @@ -13,6 +13,6 @@ namespace driver { namespace odbcabstraction { int64_t GetTodayTimeFromEpoch(); - void GetTimeForMillisSinceEpoch(tm& date, int64_t value); + void GetTimeForSecondsSinceEpoch(tm& date, int64_t value); } // namespace flight_sql } // namespace driver From a2e2abef5dcef6c5490e6717aa72ca14170fb9fb Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 5 Jul 2022 11:50:12 -0300 Subject: [PATCH 155/183] Fix SQLGetTypeInfo on ODBC v2 crashing This makes sure that SQLGetTypeInfo on ODBC v2 is able to correctly produce a RecordBatch. This fixes debug builds that crashes on SQLGetTypeInfo. Change-Id: I29f657eea29ba15b7706559cf47d9609da6fa300 --- .../flight_sql/flight_sql_statement_get_type_info.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc index 331caa1fc75ff..8679c6dc6945c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_statement_get_type_info.cc @@ -60,6 +60,10 @@ std::shared_ptr GetTypeInfo_V2_Schema() { field("LOCAL_TYPE_NAME", utf8()), field("MINIMUM_SCALE", int16()), field("MAXIMUM_SCALE", int16()), + field("SQL_DATA_TYPE", int16(), false), + field("SQL_DATETIME_SUB", int16()), + field("NUM_PREC_RADIX", int32()), + field("INTERVAL_PRECISION", int16()), }); } From 0545f0cd669b9fa8913f5ae743766fde5506edd4 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 5 Jul 2022 14:48:41 -0300 Subject: [PATCH 156/183] Make StringColumnLength property always override instead of being default This makes StringColumnLength have precedence over reported Flight SQL column precision for string columns. This is needed to make RazorSQL work as RazorSQL tries to fetch string data as SQL_C_BINARY if column length is too large, by setting StringColumnLength to a smaller value such as 1024 RazorSQL uses SQL_C_CHAR as expected. Change-Id: Ia94773823d72b1d57f81536d5f1e5f27f0917d54 --- .../flight_sql/flight_sql_connection.cc | 25 +++----- .../flight_sql/flight_sql_connection.h | 2 +- .../flight_sql/flight_sql_connection_test.cc | 5 +- .../flight_sql_result_set_metadata.cc | 14 +++-- .../flightsql-odbc/flight_sql/utils.cc | 57 ++++++++++++++++++- .../flightsql-odbc/flight_sql/utils.h | 3 + .../include/odbcabstraction/types.h | 3 +- .../include/odbcabstraction/utils.h | 22 +------ .../flightsql-odbc/odbcabstraction/utils.cc | 53 ++++++----------- 9 files changed, 101 insertions(+), 83 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 9cb913e04e102..720b87c23df75 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -143,9 +143,9 @@ TrackMissingRequiredProperty(const std::string &property, } // namespace std::shared_ptr LoadFlightSslConfigs(const Connection::ConnPropertyMap &connPropertyMap) { - bool use_encryption = AsBool(true, connPropertyMap, FlightSqlConnection::USE_ENCRYPTION); - bool disable_cert = AsBool(false, connPropertyMap, FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION); - bool use_system_trusted = AsBool(SYSTEM_TRUST_STORE_DEFAULT, connPropertyMap, FlightSqlConnection::USE_SYSTEM_TRUST_STORE); + bool use_encryption = AsBool(connPropertyMap, FlightSqlConnection::USE_ENCRYPTION).value_or(true); + bool disable_cert = AsBool(connPropertyMap, FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION).value_or(false); + bool use_system_trusted = AsBool(connPropertyMap, FlightSqlConnection::USE_SYSTEM_TRUST_STORE).value_or(SYSTEM_TRUST_STORE_DEFAULT); auto trusted_certs_iterator = connPropertyMap.find( FlightSqlConnection::TRUSTED_CERTS); @@ -202,28 +202,19 @@ void FlightSqlConnection::PopulateMetadataSettings(const Connection::ConnPropert metadata_settings_.use_wide_char_ = GetUseWideChar(conn_property_map); } -int32_t FlightSqlConnection::GetStringColumnLength(const Connection::ConnPropertyMap &conn_property_map) { - const int32_t default_string_column_length = 1024; +boost::optional FlightSqlConnection::GetStringColumnLength(const Connection::ConnPropertyMap &conn_property_map) { const int32_t min_string_column_length = 1; - int32_t string_column_length; try { - string_column_length = AsInt32( - default_string_column_length, - min_string_column_length, - conn_property_map, - FlightSqlConnection::STRING_COLUMN_LENGTH - ); + return AsInt32(min_string_column_length, conn_property_map, FlightSqlConnection::STRING_COLUMN_LENGTH); } catch (const std::exception& e) { diagnostics_.AddWarning( std::string("Invalid value for connection property " + FlightSqlConnection::STRING_COLUMN_LENGTH + - ". Please ensure it has a valid numeric value. Using default: " + - std::to_string(default_string_column_length) + ". Message: " + e.what()), + ". Please ensure it has a valid numeric value. Message: " + e.what()), "01000", odbcabstraction::ODBCErrorCodes_GENERAL_WARNING); - string_column_length = default_string_column_length; } - return string_column_length; + return boost::none; } bool FlightSqlConnection::GetUseWideChar(const ConnPropertyMap &connPropertyMap) { @@ -234,7 +225,7 @@ bool FlightSqlConnection::GetUseWideChar(const ConnPropertyMap &connPropertyMap) // Mac and Linux should not use wide chars by default bool default_value = false; #endif - return AsBool(default_value, connPropertyMap, FlightSqlConnection::USE_WIDE_CHAR); + return AsBool(connPropertyMap, FlightSqlConnection::USE_WIDE_CHAR).value_or(default_value); } const FlightCallOptions & diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 97d925d6dfe8b..e94e67fc03fcc 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -100,7 +100,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { /// \note Visible for testing void SetClosed(bool is_closed); - int32_t GetStringColumnLength(const ConnPropertyMap &connPropertyMap); + boost::optional GetStringColumnLength(const ConnPropertyMap &connPropertyMap); bool GetUseWideChar(const ConnPropertyMap &connPropertyMap); }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc index a68223f3789bd..9369f007e7c43 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection_test.cc @@ -66,9 +66,10 @@ TEST(MetadataSettingsTest, StringColumnLengthTest) { {FlightSqlConnection::STRING_COLUMN_LENGTH, std::to_string(expected_string_column_length)}, }; - const int32_t actual_string_column_length = connection.GetStringColumnLength(properties); + const boost::optional actual_string_column_length = connection.GetStringColumnLength(properties); - EXPECT_EQ(expected_string_column_length, actual_string_column_length); + EXPECT_TRUE(actual_string_column_length); + EXPECT_EQ(expected_string_column_length, *actual_string_column_length); connection.Close(); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc index 8ec50961a25d5..8188b36045f69 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_metadata.cc @@ -25,6 +25,10 @@ using arrow::util::nullopt; constexpr int32_t DefaultDecimalPrecision = 38; +// This indicates the column length used when the both property StringColumnLength is not specified and +// the server does not provide a length on column metadata. +constexpr int32_t DefaultLengthForVariableLengthColumns = 1024; + namespace { std::shared_ptr empty_metadata_map(new arrow::KeyValueMetadata); @@ -109,7 +113,7 @@ size_t FlightSqlResultSetMetadata::GetColumnDisplaySize( int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - int32_t column_size = GetFieldPrecision(field).ValueOrElse([this] { return metadata_settings_.string_column_length_; }); + int32_t column_size = metadata_settings_.string_column_length_.value_or(GetFieldPrecision(field).ValueOr(DefaultLengthForVariableLengthColumns)); SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field, metadata_settings_.use_wide_char_); return GetDisplaySize(data_type_v3, column_size).value_or(NO_TOTAL); @@ -134,10 +138,10 @@ uint16_t FlightSqlResultSetMetadata::GetConciseType(int column_position) { size_t FlightSqlResultSetMetadata::GetLength(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); - int32_t column_size = GetFieldPrecision(field).ValueOrElse([this] { return metadata_settings_.string_column_length_; }); + int32_t column_size = metadata_settings_.string_column_length_.value_or(GetFieldPrecision(field).ValueOr(DefaultLengthForVariableLengthColumns)); SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field, metadata_settings_.use_wide_char_); - return GetBufferLength(data_type_v3, column_size).value_or(metadata_settings_.string_column_length_); + return flight_sql::GetLength(data_type_v3, column_size).value_or(DefaultLengthForVariableLengthColumns); } std::string FlightSqlResultSetMetadata::GetLiteralPrefix(int column_position) { @@ -168,7 +172,7 @@ size_t FlightSqlResultSetMetadata::GetOctetLength(int column_position) { const std::shared_ptr &field = schema_->field(column_position - 1); arrow::flight::sql::ColumnMetadata metadata = GetMetadata(field); - arrow::Result column_size = GetFieldPrecision(field); + int32_t column_size = metadata_settings_.string_column_length_.value_or(GetFieldPrecision(field).ValueOr(DefaultLengthForVariableLengthColumns)); SqlDataType data_type_v3 = GetDataTypeFromArrowField_V3(field, metadata_settings_.use_wide_char_); // Workaround to get the precision for Decimal and Numeric types, since server doesn't return it currently. @@ -179,7 +183,7 @@ size_t FlightSqlResultSetMetadata::GetOctetLength(int column_position) { return GetCharOctetLength(data_type_v3, column_size, precision).value_or(DefaultDecimalPrecision+2); } - return GetCharOctetLength(data_type_v3, column_size).value_or(metadata_settings_.string_column_length_); + return GetCharOctetLength(data_type_v3, column_size).value_or(DefaultLengthForVariableLengthColumns); } std::string FlightSqlResultSetMetadata::GetTypeName(int column_position) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc index 84d8da51e3da6..c783a8934d57b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.cc @@ -499,7 +499,6 @@ optional GetBufferLength(SqlDataType data_type, case SqlDataType_LONGVARBINARY: return column_size; case SqlDataType_DECIMAL: - return 19; // The same as sizeof(SQL_NUMERIC_STRUCT) case SqlDataType_NUMERIC: return 19; // The same as sizeof(SQL_NUMERIC_STRUCT) case SqlDataType_BIT: @@ -543,6 +542,62 @@ optional GetBufferLength(SqlDataType data_type, } } +optional GetLength(SqlDataType data_type, const optional& column_size) { + switch (data_type) { + case SqlDataType_CHAR: + case SqlDataType_VARCHAR: + case SqlDataType_LONGVARCHAR: + case SqlDataType_WCHAR: + case SqlDataType_WVARCHAR: + case SqlDataType_WLONGVARCHAR: + case SqlDataType_BINARY: + case SqlDataType_VARBINARY: + case SqlDataType_LONGVARBINARY: + return column_size; + case SqlDataType_DECIMAL: + case SqlDataType_NUMERIC: + return 19; // The same as sizeof(SQL_NUMERIC_STRUCT) + case SqlDataType_BIT: + case SqlDataType_TINYINT: + return 1; + case SqlDataType_SMALLINT: + return 2; + case SqlDataType_INTEGER: + return 4; + case SqlDataType_BIGINT: + return 8; + case SqlDataType_REAL: + return 4; + case SqlDataType_FLOAT: + case SqlDataType_DOUBLE: + return 8; + case SqlDataType_TYPE_DATE: + return 10; // The same as sizeof(SQL_DATE_STRUCT) + case SqlDataType_TYPE_TIME: + return 12; // The same as sizeof(SQL_TIME_STRUCT) + case SqlDataType_TYPE_TIMESTAMP: + return 23; // The same as sizeof(SQL_TIME_STRUCT) + case SqlDataType_INTERVAL_MONTH: + case SqlDataType_INTERVAL_YEAR: + case SqlDataType_INTERVAL_YEAR_TO_MONTH: + case SqlDataType_INTERVAL_DAY: + case SqlDataType_INTERVAL_HOUR: + case SqlDataType_INTERVAL_MINUTE: + case SqlDataType_INTERVAL_SECOND: + case SqlDataType_INTERVAL_DAY_TO_HOUR: + case SqlDataType_INTERVAL_DAY_TO_MINUTE: + case SqlDataType_INTERVAL_DAY_TO_SECOND: + case SqlDataType_INTERVAL_HOUR_TO_MINUTE: + case SqlDataType_INTERVAL_HOUR_TO_SECOND: + case SqlDataType_INTERVAL_MINUTE_TO_SECOND: + return 28; // The same as sizeof(SQL_INTERVAL_STRUCT) + case SqlDataType_GUID: + return 16; + default: + return arrow::util::nullopt; + } +} + optional GetDisplaySize(SqlDataType data_type, const optional& column_size) { switch (data_type) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index b87da077341d1..5ac64536f38cc 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -82,6 +82,9 @@ optional GetCharOctetLength(odbcabstraction::SqlDataType data_type, optional GetBufferLength(odbcabstraction::SqlDataType data_type, const optional& column_size); +optional GetLength(odbcabstraction::SqlDataType data_type, + const optional& column_size); + optional GetTypeScale(odbcabstraction::SqlDataType data_type, const optional& type_scale); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index 5aa815b606f55..f6ed916b89f10 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -7,6 +7,7 @@ #pragma once #include +#include namespace driver { namespace odbcabstraction { @@ -163,7 +164,7 @@ enum RowStatus: uint16_t { }; struct MetadataSettings { - int32_t string_column_length_{1024}; + boost::optional string_column_length_{boost::none}; bool use_wide_char_; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h index 7e73e7d302d1b..d818dce63dc22 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h @@ -14,40 +14,22 @@ namespace odbcabstraction { using driver::odbcabstraction::Connection; -/// Parse a string value to a boolean. -/// \param value the value to be parsed. -/// \param default_value the default value in case the parse fails. -/// \return the parsed valued. -bool AsBool(const std::string& value, bool default_value); - /// Looks up for a value inside the ConnPropertyMap and then try to parse it. /// In case it does not find or it cannot parse, the default value will be returned. -/// \param default_value the default value to be parsed. /// \param connPropertyMap the map with the connection properties. /// \param property_name the name of the property that will be looked up. /// \return the parsed valued. -bool AsBool(bool default_value, const Connection::ConnPropertyMap& connPropertyMap, - const std::string& property_name); - -/// Parse a string value to an int32_t. -/// \param value the value to be parsed. -/// \param default_value the default value in case the parse fails. -/// \param min_value the minimum value to be parsed, else the default value is returned. -/// \return the parsed valued. -/// \exception std::invalid_argument exception from \link std::stoi \endlink -/// \exception std::out_of_range exception from \link std::stoi \endlink -int32_t AsInt32(const std::string& value, int32_t default_value, int32_t min_value); +boost::optional AsBool(const Connection::ConnPropertyMap& connPropertyMap, const std::string& property_name); /// Looks up for a value inside the ConnPropertyMap and then try to parse it. /// In case it does not find or it cannot parse, the default value will be returned. -/// \param default_value the default value to be parsed. /// \param min_value the minimum value to be parsed, else the default value is returned. /// \param connPropertyMap the map with the connection properties. /// \param property_name the name of the property that will be looked up. /// \return the parsed valued. /// \exception std::invalid_argument exception from \link std::stoi \endlink /// \exception std::out_of_range exception from \link std::stoi \endlink -int32_t AsInt32(int32_t default_value, int32_t min_value, const Connection::ConnPropertyMap& connPropertyMap, +boost::optional AsInt32(int32_t min_value, const Connection::ConnPropertyMap& connPropertyMap, const std::string& property_name); } // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc index 6ab21aec30791..bad97fa92a4e5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc @@ -11,52 +11,33 @@ namespace driver { namespace odbcabstraction { -bool AsBool(const std::string& value, bool default_value) { - if (boost::iequals(value, "true") || boost::iequals(value, "1")) { - return true; - } else if (boost::iequals(value, "false") || boost::iequals(value, "0")) { - return false; - } else { - return default_value; - } -} - -bool AsBool(bool default_value, const Connection::ConnPropertyMap& connPropertyMap, +boost::optional AsBool(const Connection::ConnPropertyMap& connPropertyMap, const std::string& property_name) { - - auto extracted_property = connPropertyMap.find( - property_name); + auto extracted_property = connPropertyMap.find(property_name); if (extracted_property != connPropertyMap.end()) { - return AsBool(extracted_property->second, default_value); + if (boost::iequals(extracted_property->second, "true") || boost::iequals(extracted_property->second, "1")) { + return true; + } else if (boost::iequals(extracted_property->second, "false") || boost::iequals(extracted_property->second, "0")) { + return false; + } } - else { - return default_value; - } -} - -int32_t AsInt32(const std::string& value, int32_t default_value, int32_t min_value) { - const int32_t string_column_length = std::stoi(value); - if (string_column_length >= min_value && string_column_length <= INT32_MAX) { - return string_column_length; - } else { - return default_value; - } + return boost::none; } -int32_t AsInt32(int32_t default_value, int32_t min_value, const Connection::ConnPropertyMap& connPropertyMap, - const std::string& property_name) { - - auto extracted_property = connPropertyMap.find( - property_name); +boost::optional AsInt32(int32_t min_value, const Connection::ConnPropertyMap& connPropertyMap, const std::string& property_name) { + auto extracted_property = connPropertyMap.find(property_name); if (extracted_property != connPropertyMap.end()) { - return AsInt32(extracted_property->second, default_value, min_value); - } - else { - return default_value; + const int32_t stringColumnLength = std::stoi(extracted_property->second); + + if (stringColumnLength >= min_value && stringColumnLength <= INT32_MAX) { + return stringColumnLength; + } } + return boost::none; } + } // namespace odbcabstraction } // namespace driver From 8ab39e703af1c48f735a450cf2f942efbc921f69 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Wed, 6 Jul 2022 15:01:40 -0300 Subject: [PATCH 157/183] Fix DSN configuration window build Recent modification on odbcabstraction/util broke build on Windows, this fixes the build. Change-Id: I545d1294f830a765ddbfd605b741c921d83a0c4d --- .../flight_sql/ui/dsn_configuration_window.cc | 6 +++--- .../include/odbcabstraction/utils.h | 5 +++++ .../flightsql-odbc/odbcabstraction/utils.cc | 16 +++++++++++----- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc index 817409c1dcef1..37503a07e7574 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/ui/dsn_configuration_window.cc @@ -218,7 +218,7 @@ int DsnConfigurationWindow::CreateEncryptionSettingsGroup(int posX, int posY, in const char* val = config.Get(FlightSqlConnection::USE_ENCRYPTION).c_str(); - const bool enableEncryption = driver::odbcabstraction::AsBool(val, true); + const bool enableEncryption = driver::odbcabstraction::AsBool(val).value_or(true); labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Use Encryption:", ChildId::ENABLE_ENCRYPTION_LABEL)); enableEncryptionCheckBox = CreateCheckBox(editPosX, rowPos - 2, editSizeX, ROW_HEIGHT, "", @@ -237,7 +237,7 @@ int DsnConfigurationWindow::CreateEncryptionSettingsGroup(int posX, int posY, in val = config.Get(FlightSqlConnection::USE_SYSTEM_TRUST_STORE).c_str(); - const bool useSystemCertStore = driver::odbcabstraction::AsBool(val, true); + const bool useSystemCertStore = driver::odbcabstraction::AsBool(val).value_or(true); labels.push_back(CreateLabel(labelPosX, rowPos, LABEL_WIDTH, 2 * ROW_HEIGHT, "Use System Certificate Store:", ChildId::USE_SYSTEM_CERT_STORE_LABEL)); useSystemCertStoreCheckBox = CreateCheckBox(editPosX, rowPos - 2, 20, 2 * ROW_HEIGHT, "", @@ -248,7 +248,7 @@ int DsnConfigurationWindow::CreateEncryptionSettingsGroup(int posX, int posY, in const int rightPosX = labelPosX + (sizeX - (2 * INTERVAL)) / 2; const int rightCheckPosX = rightPosX + (editPosX - labelPosX); - const bool disableCertVerification = driver::odbcabstraction::AsBool(val, false); + const bool disableCertVerification = driver::odbcabstraction::AsBool(val).value_or(false); labels.push_back(CreateLabel(rightPosX, rowPos, LABEL_WIDTH, 2 * ROW_HEIGHT, "Disable Certificate Verification:", ChildId::DISABLE_CERT_VERIFICATION_LABEL)); disableCertVerificationCheckBox = CreateCheckBox(rightCheckPosX, rowPos - 2, 20, 2 * ROW_HEIGHT, "", diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h index d818dce63dc22..a5617adac5036 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h @@ -14,6 +14,11 @@ namespace odbcabstraction { using driver::odbcabstraction::Connection; +/// Parse a string value to a boolean. +/// \param value the value to be parsed. +/// \return the parsed valued. +boost::optional AsBool(const std::string& value); + /// Looks up for a value inside the ConnPropertyMap and then try to parse it. /// In case it does not find or it cannot parse, the default value will be returned. /// \param connPropertyMap the map with the connection properties. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc index bad97fa92a4e5..8256cb230af40 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc @@ -11,16 +11,22 @@ namespace driver { namespace odbcabstraction { +boost::optional AsBool(const std::string& value) { + if (boost::iequals(value, "true") || boost::iequals(value, "1")) { + return true; + } else if (boost::iequals(value, "false") || boost::iequals(value, "0")) { + return false; + } else { + return boost::none; + } +} + boost::optional AsBool(const Connection::ConnPropertyMap& connPropertyMap, const std::string& property_name) { auto extracted_property = connPropertyMap.find(property_name); if (extracted_property != connPropertyMap.end()) { - if (boost::iequals(extracted_property->second, "true") || boost::iequals(extracted_property->second, "1")) { - return true; - } else if (boost::iequals(extracted_property->second, "false") || boost::iequals(extracted_property->second, "0")) { - return false; - } + return AsBool(extracted_property->second); } return boost::none; From 86fb07e6fe77583fb7bb0fc49503a52f7cc36b82 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 5 Jul 2022 16:37:04 -0300 Subject: [PATCH 158/183] Fix non-UTF8 characters on Windows This makes sure that when fetching data as SQL_C_CHAR on Windows it uses the default locale (C locale), when fetching as SQL_C_WCHAR it keeps using UTF-16 as before. This fixes bad data on RazorSQL when fetching string data as non UTF-8 characters. Change-Id: I63ac4d6b722d75e340ba736db2b19fd90983ad97 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 3 +++ .../accessors/string_array_accessor.cc | 27 +++++++++++++++++-- .../flightsql-odbc/vcpkg.json | 1 + 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 20e8f0fdd2da5..61cb3acd1dee0 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -236,6 +236,8 @@ else() ) endif() +find_package(Boost REQUIRED COMPONENTS locale) + set(ARROW_ODBC_SPI_THIRDPARTY_LIBS ${ARROW_LIBS} gRPC::grpc++ @@ -243,6 +245,7 @@ set(ARROW_ODBC_SPI_THIRDPARTY_LIBS ${Protobuf_LIBRARIES} ${OPENSSL_LIBRARIES} ${RapidJSON_LIBRARIES} + ${Boost_LIBRARIES} ) add_library(arrow_odbc_spi_impl ${ARROW_ODBC_SPI_SOURCES}) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc index f28b81a0c4e2b..098a12a49915e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -7,6 +7,7 @@ #include "string_array_accessor.h" #include +#include namespace driver { namespace flight_sql { @@ -16,6 +17,14 @@ using namespace odbcabstraction; namespace { +std::string utf8_to_clocale(const char *utf8str, int len) +{ + boost::locale::generator g; + g.locale_cache_enabled(true); + std::locale loc = g(boost::locale::util::get_system_locale()); + return boost::locale::conv::from_utf(utf8str, utf8str + len, loc); +} + template inline RowStatus MoveSingleCellToCharBuffer(CharToWStrConverter *converter, ColumnBinding *binding, @@ -25,17 +34,31 @@ inline RowStatus MoveSingleCellToCharBuffer(CharToWStrConverter *converter, odbcabstraction::Diagnostics &diagnostics) { RowStatus result = odbcabstraction::RowStatus_SUCCESS; + // Arrow strings come as UTF-8 const char *raw_value = array->Value(i).data(); + const size_t raw_value_length = array->value_length(i); const void *value; + size_t size_in_bytes; SqlWString wstr; + std::string clocale_str; if (sizeof(CHAR_TYPE) > sizeof(char)) { - wstr = converter->from_bytes(raw_value, raw_value + array->value_length(i)); + wstr = converter->from_bytes(raw_value, raw_value + raw_value_length); value = wstr.data(); size_in_bytes = wstr.size() * sizeof(CHAR_TYPE); } else { +#if defined _WIN32 || defined _WIN64 + // Convert to C locale string + clocale_str = utf8_to_clocale(raw_value, raw_value_length); + const char* clocale_data = clocale_str.data(); + size_t clocale_length = clocale_str.size(); + + value = clocale_data; + size_in_bytes = clocale_length; +#else value = raw_value; - size_in_bytes = array->value_length(i); + size_in_bytes = raw_value_length; +#endif } size_t remaining_length = static_cast(size_in_bytes - value_offset); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json index 596bd5f0e86d9..88edaa56773f3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json @@ -7,6 +7,7 @@ "boost-beast", "boost-crc", "boost-filesystem", + "boost-locale", "boost-multiprecision", "boost-optional", "boost-process", From 841ebde464ac9a3b8db3789b6ba5a3b724aa7c44 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Fri, 8 Jul 2022 14:41:00 -0300 Subject: [PATCH 159/183] Link boost libraries only on Windows Change-Id: I1beb12fbada9de3132102022441d96ceb485917c --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 8 +++++--- .../flight_sql/accessors/string_array_accessor.cc | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 61cb3acd1dee0..3019f62332bc3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -236,8 +236,6 @@ else() ) endif() -find_package(Boost REQUIRED COMPONENTS locale) - set(ARROW_ODBC_SPI_THIRDPARTY_LIBS ${ARROW_LIBS} gRPC::grpc++ @@ -245,9 +243,13 @@ set(ARROW_ODBC_SPI_THIRDPARTY_LIBS ${Protobuf_LIBRARIES} ${OPENSSL_LIBRARIES} ${RapidJSON_LIBRARIES} - ${Boost_LIBRARIES} ) +if (MSVC) + find_package(Boost REQUIRED COMPONENTS locale) + list(APPEND ARROW_ODBC_SPI_THIRDPARTY_LIBS ${Boost_LIBRARIES}) +endif() + add_library(arrow_odbc_spi_impl ${ARROW_ODBC_SPI_SOURCES}) add_dependencies(arrow_odbc_spi_impl ApacheArrow) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc index 098a12a49915e..24e87316ee084 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -17,6 +17,7 @@ using namespace odbcabstraction; namespace { +#if defined _WIN32 || defined _WIN64 std::string utf8_to_clocale(const char *utf8str, int len) { boost::locale::generator g; @@ -24,6 +25,7 @@ std::string utf8_to_clocale(const char *utf8str, int len) std::locale loc = g(boost::locale::util::get_system_locale()); return boost::locale::conv::from_utf(utf8str, utf8str + len, loc); } +#endif template inline RowStatus MoveSingleCellToCharBuffer(CharToWStrConverter *converter, From 9db3c080c375f714b7fc3a84da52bca81ee5d72c Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 14 Jul 2022 05:57:14 -0700 Subject: [PATCH 160/183] Minor optimizations for SQLFetch and SQLGetData - inline descriptor functions used by ODBCStatement::Fetch - inline and cache the diagnostics from the SPI statement to the ODBCStatement to avoid virtual function call overhead Change-Id: Ie08f6a3158218cae7316fb98fb10e3ed277fd1bc --- .../include/odbcabstraction/odbc_impl/ODBCDescriptor.h | 10 +++++++--- .../include/odbcabstraction/odbc_impl/ODBCStatement.h | 5 ++++- .../odbcabstraction/odbc_impl/ODBCDescriptor.cc | 4 ---- .../odbcabstraction/odbc_impl/ODBCStatement.cc | 6 +----- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h index 04006f64202da..41f2e3a02b575 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCDescriptor.h @@ -85,7 +85,11 @@ namespace ODBC void GetField(SQLSMALLINT recordNumber, SQLSMALLINT fieldIdentifier, SQLPOINTER value, SQLINTEGER bufferLength, SQLINTEGER* outputLength); SQLSMALLINT getAllocType() const; bool IsAppDescriptor() const; - bool HaveBindingsChanged() const; + + inline bool HaveBindingsChanged() const { + return m_hasBindingsChanged; + } + void RegisterToStatement(ODBCStatement* statement, bool isApd); void DetachFromStatement(ODBCStatement* statement, bool isApd); void ReleaseDescriptor(); @@ -122,11 +126,11 @@ namespace ODBC } } - void NotifyBindingsHavePropagated() { + inline void NotifyBindingsHavePropagated() { m_hasBindingsChanged = false; } - void NotifyBindingsHaveChanged() { + inline void NotifyBindingsHaveChanged() { m_hasBindingsChanged = true; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h index f2e9570ef761a..104b26baf59ba 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/ODBCStatement.h @@ -40,7 +40,9 @@ class ODBCStatement : public ODBCHandle { ~ODBCStatement() = default; - driver::odbcabstraction::Diagnostics& GetDiagnostics_Impl(); + inline driver::odbcabstraction::Diagnostics& GetDiagnostics_Impl() { + return *m_diagnostics; + } ODBCConnection &GetConnection(); @@ -96,6 +98,7 @@ class ODBCStatement : public ODBCHandle { ODBCConnection& m_connection; std::shared_ptr m_spiStatement; std::shared_ptr m_currenResult; + driver::odbcabstraction::Diagnostics* m_diagnostics; std::shared_ptr m_builtInArd; std::shared_ptr m_builtInApd; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc index 5e0089f63c580..72f619d8b8615 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCDescriptor.cc @@ -407,10 +407,6 @@ bool ODBCDescriptor::IsAppDescriptor() const { return m_isAppDescriptor; } -bool ODBCDescriptor::HaveBindingsChanged() const { - return m_hasBindingsChanged; -} - void ODBCDescriptor::RegisterToStatement(ODBCStatement* statement, bool isApd) { if (isApd) { m_registeredOnStatementsAsApd.push_back(statement); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc index 1b4ce061c914a..a6dc5be76bd85 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc @@ -192,6 +192,7 @@ ODBCStatement::ODBCStatement(ODBCConnection& connection, std::shared_ptr spiStatement) : m_connection(connection), m_spiStatement(std::move(spiStatement)), + m_diagnostics(&m_spiStatement->GetDiagnostics()), m_builtInArd(std::make_shared(m_spiStatement->GetDiagnostics(), nullptr, this, true, true, connection.IsOdbc2Connection())), m_builtInApd(std::make_shared(m_spiStatement->GetDiagnostics(), nullptr, this, true, true, connection.IsOdbc2Connection())), m_ipd(std::make_shared(m_spiStatement->GetDiagnostics(), nullptr, this, false, true, connection.IsOdbc2Connection())), @@ -205,10 +206,6 @@ ODBCStatement::ODBCStatement(ODBCConnection& connection, m_hasReachedEndOfResult(false) { } -Diagnostics &ODBCStatement::GetDiagnostics_Impl() { - return m_spiStatement->GetDiagnostics(); -} - ODBCConnection &ODBCStatement::GetConnection() { return m_connection; } @@ -293,7 +290,6 @@ bool ODBCStatement::Fetch(size_t rows) { // Wipe out all bindings in the ResultSet. // Note that the number of ARD records can both be more or less // than the number of columns. - SQLULEN bindOffset = m_currentArd->GetBindOffset(); for (size_t i = 0; i < m_ird->GetRecords().size(); i++) { if (i < m_currentArd->GetRecords().size() && m_currentArd->GetRecords()[i].m_isBound) { const DescriptorRecord& ardRecord = m_currentArd->GetRecords()[i]; From bb59a9d0cfa0fe6c6bb01f8101a241dd7ba4b6d7 Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 7 Jul 2022 02:39:13 -0700 Subject: [PATCH 161/183] Fix issues connecting to cloud infrastructure - Do not attempt to resolve the hostname from the HOST key if the the HOST was not an IP. - Avoid adding multiple cookie handlers. - Extend the lifetime of the FlightClientOptions, including the cookie handler to be the lifetime of the FlightSqlConnection Change-Id: I3e07abd494221b41a2fc9501cd8e9dcefec32d72 --- .../flight_sql/flight_sql_auth_method.cc | 17 ++++----- .../flight_sql/flight_sql_connection.cc | 35 +++++++++++++------ .../flight_sql/flight_sql_connection.h | 1 + 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc index 3cdaab8483b6e..ac4ae67eddfbe 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_auth_method.cc @@ -41,16 +41,17 @@ class NoOpAuthMethod : public FlightSqlAuthMethod { class NoOpClientAuthHandler : public arrow::flight::ClientAuthHandler { public: - NoOpClientAuthHandler() {} + NoOpClientAuthHandler() {} - arrow::Status Authenticate(arrow::flight::ClientAuthSender* outgoing, arrow::flight::ClientAuthReader* incoming) override { - return arrow::Status::OK(); - } + arrow::Status Authenticate(arrow::flight::ClientAuthSender* outgoing, arrow::flight::ClientAuthReader* incoming) override { + // Write a blank string. The server should ignore this and just accept any Handshake request. + return outgoing->Write(std::string()); + } - arrow::Status GetToken(std::string* token) override { - *token = ""; - return arrow::Status::OK(); - } + arrow::Status GetToken(std::string* token) override { + *token = std::string(); + return arrow::Status::OK(); + } }; class UserPasswordAuthMethod : public FlightSqlAuthMethod { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index 720b87c23df75..caa2aa3c95127 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -314,19 +315,33 @@ FlightSqlConnection::BuildLocation(const ConnPropertyMap &properties, Location location; if (ssl_config->useEncryption()) { AddressInfo address_info; - char host_name_info[NI_MAXHOST] = ""; - bool operation_result = address_info.GetAddressInfo(host, host_name_info, - NI_MAXHOST); - - if (operation_result) { - ThrowIfNotOK(Location::ForGrpcTls(host_name_info, port, &location)); - } else { - ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); + bool operation_result = false; + + try { + auto ip_address = boost::asio::ip::make_address(host); + // We should only attempt to resolve the hostname from the IP if the given + // HOST input is an IP address. + if (ip_address.is_v4() || ip_address.is_v6()) { + operation_result = address_info.GetAddressInfo(host, host_name_info, + NI_MAXHOST); + if (operation_result) { + ThrowIfNotOK(Location::ForGrpcTls(host_name_info, port, &location)); + return location; + } + // TODO: We should log that we could not convert an IP to hostname here. + } } - } else { - ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); + catch (...) { + // This is expected. The Host attribute can be an IP or name, but make_address will throw + // if it is not an IP. + } + + ThrowIfNotOK(Location::ForGrpcTls(host, port, &location)); + return location; } + + ThrowIfNotOK(Location::ForGrpcTcp(host, port, &location)); return location; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index e94e67fc03fcc..4311d63b0ab02 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -33,6 +33,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { private: odbcabstraction::MetadataSettings metadata_settings_; std::map attribute_; + arrow::flight::FlightClientOptions client_options_; arrow::flight::FlightCallOptions call_options_; std::unique_ptr sql_client_; GetInfoCache info_; From 18e927210a14bb8f7e383c46988eeee0bc4485de Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 14 Jul 2022 16:03:29 -0700 Subject: [PATCH 162/183] Optimize accessor caching Optimize checks on converter caching by: - Reducing creation of shared_ptrs for Arrow Arrays. - Reducing API calls to Arrow's RecordBatch, which is using locks. - We now assume that if a cached accessor and array are available, they can be reused for more data unless the application is explicitly using a different type than before (either by SQLBindCol or SQLGetData). Change-Id: I4d3a76a75dd1a15a475b32c3c15da72a7901a753 --- .../flight_sql/flight_sql_result_set.cc | 38 +++++------ .../flight_sql/flight_sql_result_set.h | 13 ---- .../flight_sql_result_set_column.cc | 67 ++++++------------- .../flight_sql/flight_sql_result_set_column.h | 47 +++++++++---- .../flightsql-odbc/flight_sql/utils.h | 2 +- 5 files changed, 69 insertions(+), 98 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index 99b4920b01eff..6b76bd68a66ed 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -48,12 +48,11 @@ FlightSqlResultSet::FlightSqlResultSet( diagnostics_(diagnostics), current_row_(0), num_binding_(0), reset_get_data_(false) { current_chunk_.data = nullptr; + ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema_)); - for (int i = 0; i < columns_.size(); ++i) { - columns_[i] = FlightSqlResultSetColumn(this, i + 1); + for (size_t i = 0; i < columns_.size(); ++i) { + columns_[i] = FlightSqlResultSetColumn(metadata_settings.use_wide_char_); } - - ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema_)); } size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, size_t bind_type, uint16_t *row_status_array) { @@ -68,6 +67,11 @@ size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, size_t bind_typ if (transformer_) { current_chunk_.data = transformer_->Transform(current_chunk_.data); } + + for (size_t column_num = 0; column_num < columns_.size(); ++column_num) { + columns_[column_num].SetArrowArray(current_chunk_.data->column(column_num)); + columns_[column_num].ResetAccessor(); + } } // Reset GetData value offsets. @@ -91,8 +95,9 @@ size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, size_t bind_typ current_chunk_.data = transformer_->Transform(current_chunk_.data); } - for (auto &column : columns_) { - column.ResetAccessor(); + for (size_t column_num = 0; column_num < columns_.size(); ++column_num) { + columns_[column_num].SetArrowArray(current_chunk_.data->column(column_num)); + columns_[column_num].ResetAccessor(); } current_row_ = 0; continue; @@ -100,11 +105,11 @@ size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, size_t bind_typ for (auto & column : columns_) { // There can be unbound columns. - if (!column.is_bound) + if (!column.is_bound_) continue; auto *accessor = column.GetAccessorForBinding(); - ColumnBinding shifted_binding = column.binding; + ColumnBinding shifted_binding = column.binding_; uint16_t *shifted_row_status_array = row_status_array ? &row_status_array[fetched_rows] : nullptr; if (shifted_row_status_array) { @@ -233,19 +238,6 @@ bool FlightSqlResultSet::GetData(int column_n, int16_t target_type, return diagnostics_.HasWarning(); } -std::shared_ptr -FlightSqlResultSet::GetArrayForColumn(int column) { - if (!current_chunk_.data) { - // This may happen if query is cancelled right after SQLFetch and before SQLGetData. - throw DriverException("No RecordBatch loaded.", "24000"); - } - - std::shared_ptr original_array = - current_chunk_.data->column(column - 1); - - return original_array; -} - std::shared_ptr FlightSqlResultSet::GetMetadata() { return metadata_; } @@ -256,14 +248,14 @@ void FlightSqlResultSet::BindColumn(int column_n, int16_t target_type, ssize_t *strlen_buffer) { auto &column = columns_[column_n - 1]; if (buffer == nullptr) { - if (column.is_bound) { + if (column.is_bound_) { num_binding_--; } column.ResetBinding(); return; } - if (!column.is_bound) { + if (!column.is_bound_) { num_binding_++; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index 0a96633388d53..21dc9d0b31340 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -6,14 +6,10 @@ #pragma once -#include "flight_sql_result_set_accessors.h" #include "flight_sql_stream_chunk_iterator.h" #include "record_batch_transformer.h" #include "utils.h" #include "odbcabstraction/types.h" -#include -#include -#include #include #include #include @@ -24,10 +20,7 @@ namespace driver { namespace flight_sql { -using arrow::Array; -using arrow::RecordBatch; using arrow::Schema; -using arrow::Status; using arrow::flight::FlightEndpoint; using arrow::flight::FlightInfo; using arrow::flight::FlightStreamChunk; @@ -76,17 +69,11 @@ class FlightSqlResultSet : public ResultSet { size_t Move(size_t rows, size_t bind_offset, size_t bind_type, uint16_t *row_status_array) override; - std::shared_ptr GetArrayForColumn(int column); - std::shared_ptr GetMetadata() override; void BindColumn(int column_n, int16_t target_type, int precision, int scale, void *buffer, size_t buffer_length, ssize_t *strlen_buffer) override; - - inline bool UseWideChar() { - return metadata_settings_.use_wide_char_; - } }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index adbdd04ab9e07..ad51b36f757c5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -6,7 +6,7 @@ #include "flight_sql_result_set_column.h" #include -#include "flight_sql_result_set.h" +#include "flight_sql_result_set_accessors.h" #include "utils.h" #include #include @@ -32,74 +32,47 @@ CastArray(const std::shared_ptr &original_array, std::unique_ptr FlightSqlResultSetColumn::CreateAccessor(CDataType target_type) { - const std::shared_ptr &original_array = - result_set_->GetArrayForColumn(column_n_); - cached_original_array_ = original_array.get(); - cached_casted_array_ = CastArray(original_array, target_type); + cached_casted_array_ = CastArray(original_array_, target_type); return flight_sql::CreateAccessor(cached_casted_array_.get(), target_type); } Accessor * FlightSqlResultSetColumn::GetAccessorForTargetType(CDataType target_type) { - const std::shared_ptr &original_array = - result_set_->GetArrayForColumn(column_n_); - + // Cast the original array to a type matching the target_type. if (target_type == odbcabstraction::CDataType_DEFAULT) { - target_type = ConvertArrowTypeToC(original_array->type_id(), result_set_->UseWideChar()); - } - - // TODO: Figure out if that's the best way of caching - if (cached_accessor_ && original_array.get() == cached_original_array_ && - cached_accessor_->target_type_ == target_type) { - return cached_accessor_.get(); + target_type = ConvertArrowTypeToC(original_array_->type_id(), use_wide_char_); } cached_accessor_ = CreateAccessor(target_type); - cached_original_array_ = original_array.get(); return cached_accessor_.get(); } -FlightSqlResultSetColumn::FlightSqlResultSetColumn() - : FlightSqlResultSetColumn(nullptr, 0) {} - -FlightSqlResultSetColumn::FlightSqlResultSetColumn( - FlightSqlResultSet *result_set, int column_n) - : result_set_(result_set), column_n_(column_n), - cached_original_array_(nullptr), is_bound(false) {} - -Accessor *FlightSqlResultSetColumn::GetAccessorForBinding() { - return GetAccessorForTargetType(binding.target_type); -} - -Accessor * -FlightSqlResultSetColumn::GetAccessorForGetData(CDataType target_type) { - return GetAccessorForTargetType(target_type); -} +FlightSqlResultSetColumn::FlightSqlResultSetColumn(bool use_wide_char) + : use_wide_char_(use_wide_char), + is_bound_(false) {} void FlightSqlResultSetColumn::SetBinding(ColumnBinding new_binding) { - binding = new_binding; - is_bound = true; + binding_ = new_binding; + is_bound_ = true; // Overwrite the binding if the caller is using SQL_C_NUMERIC and has used zero // precision if it is zero (this is precision unset and will always fail). - if (binding.precision == 0 && - (binding.target_type == odbcabstraction::CDataType_NUMERIC) || - (binding.target_type == odbcabstraction::CDataType_DEFAULT && cached_original_array_->type_id() == arrow::Type::type::DECIMAL128)) { - binding.precision = arrow::Decimal128Type::kMaxPrecision; + if (binding_.precision == 0 && + (binding_.target_type == odbcabstraction::CDataType_NUMERIC) || + (binding_.target_type == odbcabstraction::CDataType_DEFAULT && original_array_->type_id() == arrow::Type::type::DECIMAL128)) { + binding_.precision = arrow::Decimal128Type::kMaxPrecision; } - ResetAccessor(); -} -void FlightSqlResultSetColumn::ResetBinding() { - is_bound = false; - ResetAccessor(); + // Rebuild the accessor and casted array if the target type changed. + if (!cached_casted_array_ || cached_accessor_->target_type_ != binding_.target_type) { + cached_accessor_ = CreateAccessor(binding_.target_type); + } } -void FlightSqlResultSetColumn::ResetAccessor() { - // An improvement would be to have ResetAccessor take in a newly acquired array. - // Then the accessor itself should switch to the new array and reset internal - // state, rather than deleting the accessor. +void FlightSqlResultSetColumn::ResetBinding() { + is_bound_ = false; + cached_casted_array_.reset(); cached_accessor_.reset(); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h index be65238445bdc..2f40f7109b183 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h @@ -8,21 +8,16 @@ #include #include +#include "utils.h" namespace driver { namespace flight_sql { using arrow::Array; -class FlightSqlResultSet; - class FlightSqlResultSetColumn { private: - FlightSqlResultSet *result_set_; - int column_n_; - - // TODO: Figure out if that's the best way of caching - Array *cached_original_array_; + std::shared_ptr original_array_; std::shared_ptr cached_casted_array_; std::unique_ptr cached_accessor_; @@ -31,22 +26,46 @@ class FlightSqlResultSetColumn { Accessor *GetAccessorForTargetType(CDataType target_type); public: - FlightSqlResultSetColumn(); + FlightSqlResultSetColumn() = default; + explicit FlightSqlResultSetColumn(bool use_wide_char); - FlightSqlResultSetColumn(FlightSqlResultSet *result_set, int column_n); + ColumnBinding binding_; + bool use_wide_char_; + bool is_bound_; - ColumnBinding binding; - bool is_bound; + inline Accessor *GetAccessorForBinding() { + return cached_accessor_.get(); + } - Accessor *GetAccessorForBinding(); + inline Accessor *GetAccessorForGetData(CDataType target_type) { + if (target_type == odbcabstraction::CDataType_DEFAULT) { + target_type = ConvertArrowTypeToC(original_array_->type_id(), use_wide_char_); + } - Accessor *GetAccessorForGetData(CDataType target_type); + if (cached_accessor_ && cached_accessor_->target_type_ == target_type) { + return cached_accessor_.get(); + } + return GetAccessorForTargetType(target_type); + } void SetBinding(ColumnBinding new_binding); void ResetBinding(); - void ResetAccessor(); + inline void ResetAccessor() { + if (is_bound_) { + cached_accessor_ = CreateAccessor(cached_accessor_->target_type_); + } else if (cached_accessor_) { + cached_accessor_ = CreateAccessor(cached_accessor_->target_type_); + } else { + cached_casted_array_.reset(); + cached_accessor_.reset(); + } + } + + inline void SetArrowArray(std::shared_ptr array) { + original_array_ = std::move(array); + } }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index 5ac64536f38cc..a883c66c47435 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -17,7 +17,7 @@ namespace driver { namespace flight_sql { typedef std::function< - std::shared_ptr(std::shared_ptr)> + std::shared_ptr(const std::shared_ptr &)> ArrayConvertTask; using arrow::util::optional; From e1fd87fea142f9158d4208d73e2c1c4a255f3b8a Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 15 Jul 2022 08:03:04 -0700 Subject: [PATCH 163/183] Accessor optimization - Rework accessors to not use array slice. - Don't pass around and cast the array since the accessor already stores the array as a field - Optimize decimal accessor to avoid shared_ptr creation of a Scalar. - Optimize Time/Timestamp accessors to make the time unit a template parameter so that the compiler can treat it as a constant. Also avoid needing to retrieve it during the accessor. Change-Id: If3412c593d783d30ecc767088c482fbe3d5aa0a4 --- .../accessors/binary_array_accessor.cc | 13 +-- .../accessors/binary_array_accessor.h | 4 +- .../accessors/boolean_array_accessor.cc | 6 +- .../accessors/boolean_array_accessor.h | 6 +- .../flight_sql/accessors/common.h | 20 ++--- .../accessors/date_array_accessor.cc | 7 +- .../accessors/date_array_accessor.h | 2 +- .../accessors/decimal_array_accessor.cc | 20 +++-- .../accessors/decimal_array_accessor.h | 6 +- .../accessors/primitive_array_accessor.cc | 8 +- .../accessors/primitive_array_accessor.h | 7 +- .../accessors/string_array_accessor.cc | 26 +++--- .../accessors/string_array_accessor.h | 6 +- .../accessors/time_array_accessor.cc | 82 +++++++++++++++---- .../accessors/time_array_accessor.h | 8 +- .../accessors/time_array_accessor_test.cc | 8 +- .../accessors/timestamp_array_accessor.cc | 37 ++++----- .../accessors/timestamp_array_accessor.h | 9 +- .../timestamp_array_accessor_test.cc | 8 +- .../flight_sql/accessors/types.h | 50 ++++++----- .../flight_sql/flight_sql_result_set.cc | 1 - .../flight_sql_result_set_accessors.cc | 27 +++++- 22 files changed, 214 insertions(+), 147 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc index 4cbd3e97e771f..5b2a018498cc1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.cc @@ -19,12 +19,12 @@ using namespace odbcabstraction; namespace { inline RowStatus MoveSingleCellToBinaryBuffer(ColumnBinding *binding, - BinaryArray *array, int64_t i, + 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(i).data(); - size_t size_in_bytes = array->value_length(i); + 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_in_bytes - value_offset); size_t value_length = @@ -62,9 +62,10 @@ BinaryArrayFlightSqlAccessor::BinaryArrayFlightSqlAccessor( template <> RowStatus BinaryArrayFlightSqlAccessor::MoveSingleCell_impl( - ColumnBinding *binding, BinaryArray *array, int64_t i, - int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { - return MoveSingleCellToBinaryBuffer(binding, array, i, value_offset, update_value_offset, diagnostics); + 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 diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h index d76fb9506ebdb..b93c97860a637 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/binary_array_accessor.h @@ -23,8 +23,8 @@ class BinaryArrayFlightSqlAccessor public: explicit BinaryArrayFlightSqlAccessor(Array *array); - RowStatus MoveSingleCell_impl(ColumnBinding *binding, BinaryArray *array, - int64_t i, int64_t &value_offset, bool update_value_offset, + RowStatus MoveSingleCell_impl(ColumnBinding *binding, int64_t arrow_row, int64_t i, + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); size_t GetCellLength_impl(ColumnBinding *binding) const; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc index 12efc79f0eeb1..aee06882cf2f7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.cc @@ -20,10 +20,10 @@ BooleanArrayFlightSqlAccessor::BooleanArrayFlightSqlAccessor( template RowStatus BooleanArrayFlightSqlAccessor::MoveSingleCell_impl( - ColumnBinding *binding, BooleanArray *array, int64_t i, - int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { + ColumnBinding *binding, int64_t arrow_row, int64_t i, int64_t &value_offset, + bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { typedef unsigned char c_type; - bool value = array->Value(i); + bool value = this->GetArray()->Value(arrow_row); auto *buffer = static_cast(binding->buffer); buffer[i] = value ? 1 : 0; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h index ec719c28ce28c..afdd6bb794e3a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/boolean_array_accessor.h @@ -24,8 +24,10 @@ class BooleanArrayFlightSqlAccessor public: explicit BooleanArrayFlightSqlAccessor(Array *array); - RowStatus MoveSingleCell_impl(ColumnBinding *binding, BooleanArray *array, - int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); + RowStatus MoveSingleCell_impl(ColumnBinding *binding, int64_t arrow_row, + int64_t i, int64_t &value_offset, + bool update_value_offset, + odbcabstraction::Diagnostics &diagnostics); size_t GetCellLength_impl(ColumnBinding *binding) const; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h index 554dc46173c49..f79fbd3f6ca85 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/common.h @@ -21,15 +21,15 @@ using namespace arrow; using namespace odbcabstraction; template -inline size_t CopyFromArrayValuesToBinding(const std::shared_ptr &array, - ColumnBinding *binding) { - auto *typed_array = reinterpret_cast(array.get()); +inline size_t CopyFromArrayValuesToBinding(ARRAY_TYPE* array, + ColumnBinding *binding, + int64_t starting_row, int64_t cells) { constexpr ssize_t element_size = sizeof(typename ARRAY_TYPE::value_type); - int64_t length = array->length(); if (binding->strlen_buffer) { - for (int64_t i = 0; i < length; ++i) { - if (array->IsNull(i)) { + for (int64_t i = 0; i < cells; ++i) { + int64_t current_row = starting_row + i; + if (array->IsNull(current_row)) { binding->strlen_buffer[i] = NULL_DATA; } else { binding->strlen_buffer[i] = element_size; @@ -37,7 +37,7 @@ inline size_t CopyFromArrayValuesToBinding(const std::shared_ptr &array, } } else { // Duplicate this loop to avoid null checks within the loop. - for (int64_t i = 0; i < length; ++i) { + for (int64_t i = starting_row; i < starting_row + cells; ++i) { if (array->IsNull(i)) { throw odbcabstraction::NullWithoutIndicatorException(); } @@ -47,10 +47,10 @@ inline size_t CopyFromArrayValuesToBinding(const std::shared_ptr &array, // Copy the entire array to the bound ODBC buffers. // Note that the array should already have been sliced down to the same number // of elements in the ODBC data array by the point in which this function is called. - const auto *values = typed_array->raw_values(); - memcpy(binding->buffer, values, element_size * length); + const auto *values = array->raw_values(); + memcpy(binding->buffer, &values[starting_row], element_size * cells); - return length; + return cells; } } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc index 47f7d9ea3f491..2036c6d0f676b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.cc @@ -46,11 +46,10 @@ DateArrayFlightSqlAccessor< template RowStatus DateArrayFlightSqlAccessor::MoveSingleCell_impl( - ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, - int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { - typedef unsigned char c_type; + ColumnBinding *binding, int64_t arrow_row, int64_t cell_counter, int64_t &value_offset, + bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { auto *buffer = static_cast(binding->buffer); - auto value = convertDate(array->Value(cell_counter)); + auto value = convertDate(this->GetArray()->Value(arrow_row)); tm date{}; GetTimeForSecondsSinceEpoch(date, value); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h index 9dcdb33008897..a54d496030f4e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/date_array_accessor.h @@ -25,7 +25,7 @@ class DateArrayFlightSqlAccessor public: explicit DateArrayFlightSqlAccessor(Array *array); - RowStatus MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, + RowStatus MoveSingleCell_impl(ColumnBinding *binding, int64_t arrow_row, int64_t cell_counter, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc index f850450f7e4c4..aff630ff4debd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.cc @@ -20,20 +20,18 @@ DecimalArrayFlightSqlAccessor::DecimalArrayFlightSqlAc Array *array) : FlightSqlAccessor>(array), - data_type_(std::static_pointer_cast(array->type())) { + data_type_(static_cast(array->type().get())) { } template <> RowStatus DecimalArrayFlightSqlAccessor::MoveSingleCell_impl( - ColumnBinding *binding, Decimal128Array *array, int64_t i, - int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { + ColumnBinding *binding, int64_t arrow_row, int64_t i, int64_t &value_offset, + bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { auto result = &(static_cast(binding->buffer)[i]); int32_t original_scale = data_type_->scale(); - std::shared_ptr scalar; - ThrowIfNotOK(array->GetScalar(i).Value(&scalar)); - const auto &decimal_scalar = internal::checked_pointer_cast(scalar); - Decimal128 value = decimal_scalar->value; + const uint8_t* bytes = this->GetArray()->Value(arrow_row); + Decimal128 value(bytes); if (original_scale != binding->scale) { const Status &status = value.Rescale(original_scale, binding->scale).Value(&value); ThrowIfNotOK(status); @@ -46,8 +44,12 @@ RowStatus DecimalArrayFlightSqlAccessor::Mov // Take the absolute value since the ODBC SQL_NUMERIC_STRUCT holds // a positive-only number. - Decimal128 abs_value = Decimal128::Abs(value); - abs_value.ToBytes(result->val); + if (value.IsNegative()) { + Decimal128 abs_value = Decimal128::Abs(value); + abs_value.ToBytes(result->val); + } else { + value.ToBytes(result->val); + } result->precision = static_cast(binding->precision); result->scale = static_cast(binding->scale); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h index 751ce5ca5bba9..3b65eb3768b67 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/decimal_array_accessor.h @@ -25,14 +25,14 @@ class DecimalArrayFlightSqlAccessor public: explicit DecimalArrayFlightSqlAccessor(Array *array); - RowStatus MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, - int64_t i, int64_t &value_offset, bool update_value_offset, + RowStatus MoveSingleCell_impl(ColumnBinding *binding, int64_t arrow_row, int64_t i, + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); size_t GetCellLength_impl(ColumnBinding *binding) const; private: - std::shared_ptr data_type_; + Decimal128Type *data_type_; }; } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc index 25dd0210d5b4a..fc8543fc5a702 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.cc @@ -22,10 +22,10 @@ PrimitiveArrayFlightSqlAccessor< template size_t PrimitiveArrayFlightSqlAccessor::GetColumnarData_impl( - const std::shared_ptr &sliced_array, ColumnBinding *binding, - int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics, - uint16_t* row_status_array) { - return CopyFromArrayValuesToBinding(sliced_array, binding); + ColumnBinding *binding, int64_t starting_row, + int64_t cells, int64_t &value_offset, bool update_value_offset, + odbcabstraction::Diagnostics &diagnostics, uint16_t* row_status_array) { + return CopyFromArrayValuesToBinding(this->GetArray(), binding, starting_row, cells); } template diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h index 3d7fdfde921ff..eff7dbfd9b98d 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/primitive_array_accessor.h @@ -27,10 +27,9 @@ class PrimitiveArrayFlightSqlAccessor public: explicit PrimitiveArrayFlightSqlAccessor(Array *array); - size_t GetColumnarData_impl(const std::shared_ptr &sliced_array, - ColumnBinding *binding, int64_t &value_offset, - bool update_value_offset, odbcabstraction::Diagnostics &diagnostics, - uint16_t* row_status_array); + size_t GetColumnarData_impl(ColumnBinding *binding, int64_t starting_row, int64_t cells, + int64_t &value_offset, bool update_value_offset, + odbcabstraction::Diagnostics &diagnostics, uint16_t* row_status_array); size_t GetCellLength_impl(ColumnBinding *binding) const; }; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc index 24e87316ee084..b2cd1df1e5cc8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -30,20 +30,22 @@ std::string utf8_to_clocale(const char *utf8str, int len) template inline RowStatus MoveSingleCellToCharBuffer(CharToWStrConverter *converter, ColumnBinding *binding, - StringArray *array, int64_t i, + StringArray *array, int64_t arrow_row, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { RowStatus result = odbcabstraction::RowStatus_SUCCESS; // Arrow strings come as UTF-8 - const char *raw_value = array->Value(i).data(); - const size_t raw_value_length = array->value_length(i); + const char *raw_value = array->Value(arrow_row).data(); + const size_t raw_value_length = array->value_length(arrow_row); const void *value; size_t size_in_bytes; SqlWString wstr; +#if defined _WIN32 || defined _WIN64 std::string clocale_str; +#endif if (sizeof(CHAR_TYPE) > sizeof(char)) { wstr = converter->from_bytes(raw_value, raw_value + raw_value_length); value = wstr.data(); @@ -111,18 +113,20 @@ StringArrayFlightSqlAccessor::StringArrayFlightSqlAccessor( template <> RowStatus StringArrayFlightSqlAccessor::MoveSingleCell_impl( - ColumnBinding *binding, StringArray *array, int64_t i, - int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { - return MoveSingleCellToCharBuffer(&converter_, binding, array, i, - value_offset, update_value_offset, diagnostics); + ColumnBinding *binding, int64_t arrow_row, int64_t i, int64_t &value_offset, + bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { + return MoveSingleCellToCharBuffer( + &converter_, binding, this->GetArray(), arrow_row, i, + value_offset, update_value_offset, diagnostics); } template <> RowStatus StringArrayFlightSqlAccessor::MoveSingleCell_impl( - ColumnBinding *binding, StringArray *array, int64_t i, - int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { - return MoveSingleCellToCharBuffer(&converter_, binding, array, i, - value_offset, update_value_offset, diagnostics); + ColumnBinding *binding, int64_t arrow_row, int64_t i, int64_t &value_offset, + bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { + return MoveSingleCellToCharBuffer( + &converter_, binding, this->GetArray(), arrow_row, i, + value_offset, update_value_offset, diagnostics); } template diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h index bf3f7ce51703e..7964a2dbbfc37 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h @@ -25,9 +25,9 @@ class StringArrayFlightSqlAccessor public: explicit StringArrayFlightSqlAccessor(Array *array); - RowStatus MoveSingleCell_impl(ColumnBinding *binding, StringArray *array, - int64_t i, int64_t &value_offset, bool update_value_offset, - odbcabstraction::Diagnostics &diagnostics); + RowStatus MoveSingleCell_impl( + ColumnBinding *binding, int64_t arrow_row, int64_t i, int64_t &value_offset, + bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); size_t GetCellLength_impl(ColumnBinding *binding) const; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc index 912b7b9a0feef..5fd9a3d7c46b8 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.cc @@ -9,6 +9,47 @@ namespace driver { namespace flight_sql { + +Accessor* CreateTimeAccessor(arrow::Array *array, arrow::Type::type type) { + auto time_type = + arrow::internal::checked_pointer_cast(array->type()); + auto time_unit = time_type->unit(); + + if (type == arrow::Type::TIME32) { + switch (time_unit) { + case TimeUnit::SECOND: + return new TimeArrayFlightSqlAccessor(array); + case TimeUnit::MILLI: + return new TimeArrayFlightSqlAccessor(array); + case TimeUnit::MICRO: + return new TimeArrayFlightSqlAccessor(array); + case TimeUnit::NANO: + return new TimeArrayFlightSqlAccessor(array); + } + } else if (type == arrow::Type::TIME64) { + switch (time_unit) { + case TimeUnit::SECOND: + return new TimeArrayFlightSqlAccessor(array); + case TimeUnit::MILLI: + return new TimeArrayFlightSqlAccessor(array); + case TimeUnit::MICRO: + return new TimeArrayFlightSqlAccessor(array); + case TimeUnit::NANO: + return new TimeArrayFlightSqlAccessor(array); + } + } + assert(false); + throw DriverException("Unsupported input supplied to CreateTimeAccessor"); +} + namespace { template int64_t ConvertTimeValue(typename T::value_type value, TimeUnit::type unit) { @@ -27,28 +68,23 @@ int64_t ConvertTimeValue(int64_t value, TimeUnit::type unit) { } } // namespace -template +template TimeArrayFlightSqlAccessor< - TARGET_TYPE, ARROW_ARRAY>::TimeArrayFlightSqlAccessor(Array *array) + TARGET_TYPE, ARROW_ARRAY, UNIT>::TimeArrayFlightSqlAccessor(Array *array) : FlightSqlAccessor>( + TimeArrayFlightSqlAccessor>( array) {} -template -RowStatus TimeArrayFlightSqlAccessor::MoveSingleCell_impl( - ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, - int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostic) { - typedef unsigned char c_type; +template +RowStatus TimeArrayFlightSqlAccessor::MoveSingleCell_impl( + ColumnBinding *binding, int64_t arrow_row, int64_t cell_counter, int64_t &value_offset, + bool update_value_offset, odbcabstraction::Diagnostics &diagnostic) { auto *buffer = static_cast(binding->buffer); - auto time_type = - arrow::internal::checked_pointer_cast(array->type()); - auto time_unit = time_type->unit(); - tm time{}; auto converted_value_seconds = - ConvertTimeValue(array->Value(cell_counter), time_unit); + ConvertTimeValue(this->GetArray()->Value(arrow_row), UNIT); GetTimeForSecondsSinceEpoch(time, converted_value_seconds); @@ -62,15 +98,27 @@ RowStatus TimeArrayFlightSqlAccessor::MoveSingleCell_i return odbcabstraction::RowStatus_SUCCESS; } -template -size_t TimeArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { +template +size_t TimeArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { return sizeof(TIME_STRUCT); } template class TimeArrayFlightSqlAccessor; + Time32Array, TimeUnit::SECOND>; +template class TimeArrayFlightSqlAccessor; +template class TimeArrayFlightSqlAccessor; +template class TimeArrayFlightSqlAccessor; +template class TimeArrayFlightSqlAccessor; +template class TimeArrayFlightSqlAccessor; +template class TimeArrayFlightSqlAccessor; template class TimeArrayFlightSqlAccessor; + Time64Array, TimeUnit::NANO>; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h index 8b511a8c1bb37..6f21be5ca2a45 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor.h @@ -16,16 +16,18 @@ namespace flight_sql { using namespace arrow; using namespace odbcabstraction; -template +Accessor* CreateTimeAccessor(arrow::Array *array, arrow::Type::type type); + +template class TimeArrayFlightSqlAccessor : public FlightSqlAccessor< ARROW_ARRAY, TARGET_TYPE, - TimeArrayFlightSqlAccessor> { + TimeArrayFlightSqlAccessor> { public: explicit TimeArrayFlightSqlAccessor(Array *array); - RowStatus MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, int64_t cell_counter, + RowStatus MoveSingleCell_impl(ColumnBinding *binding, int64_t arrow_row, int64_t cell_counter, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostic); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc index 884a29e545713..6e44affac98a4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/time_array_accessor_test.cc @@ -25,7 +25,7 @@ TEST(TEST_TIME32, TIME_WITH_SECONDS) { ArrayFromVector(value_field->type(), t32_values, &time32_array); - TimeArrayFlightSqlAccessor accessor(time32_array.get()); + TimeArrayFlightSqlAccessor accessor(time32_array.get()); std::vector buffer(t32_values.size()); std::vector strlen_buffer(t32_values.size()); @@ -58,7 +58,7 @@ TEST(TEST_TIME32, TIME_WITH_MILLI) { ArrayFromVector(value_field->type(), t32_values, &time32_array); - TimeArrayFlightSqlAccessor accessor(time32_array.get()); + TimeArrayFlightSqlAccessor accessor(time32_array.get()); std::vector buffer(t32_values.size()); std::vector strlen_buffer(t32_values.size()); @@ -94,7 +94,7 @@ TEST(TEST_TIME64, TIME_WITH_MICRO) { ArrayFromVector(value_field->type(), t64_values, &time64_array); - TimeArrayFlightSqlAccessor accessor(time64_array.get()); + TimeArrayFlightSqlAccessor accessor(time64_array.get()); std::vector buffer(t64_values.size()); std::vector strlen_buffer(t64_values.size()); @@ -129,7 +129,7 @@ TEST(TEST_TIME64, TIME_WITH_NANO) { ArrayFromVector(value_field->type(), t64_values, &time64_array); - TimeArrayFlightSqlAccessor accessor( + TimeArrayFlightSqlAccessor accessor( time64_array.get()); std::vector buffer(t64_values.size()); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc index f3e9a6c8d1316..b74f3889316ee 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.cc @@ -61,27 +61,21 @@ namespace flight_sql { using namespace odbcabstraction; -template -TimestampArrayFlightSqlAccessor::TimestampArrayFlightSqlAccessor(Array *array) +template +TimestampArrayFlightSqlAccessor::TimestampArrayFlightSqlAccessor(Array *array) : FlightSqlAccessor>(array), - timestamp_type_( - arrow::internal::checked_pointer_cast( - array->type())) {} + TimestampArrayFlightSqlAccessor>(array) {} -template +template RowStatus -TimestampArrayFlightSqlAccessor::MoveSingleCell_impl(ColumnBinding *binding, - TimestampArray *array, - int64_t cell_counter, - int64_t &value_offset, - bool update_value_offset, - odbcabstraction::Diagnostics &diagnostics) { - typedef unsigned char c_type; +TimestampArrayFlightSqlAccessor::MoveSingleCell_impl( + ColumnBinding *binding, int64_t arrow_row, int64_t cell_counter, + int64_t &value_offset, bool update_value_offset, + odbcabstraction::Diagnostics &diagnostics) { auto *buffer = static_cast(binding->buffer); - int64_t value = array->Value(cell_counter); - const auto divisor = GetConversionToSecondsDivisor(timestamp_type_->unit()); + int64_t value = this->GetArray()->Value(arrow_row); + const auto divisor = GetConversionToSecondsDivisor(UNIT); const auto converted_result_seconds = value / divisor; tm timestamp = {0}; @@ -93,7 +87,7 @@ TimestampArrayFlightSqlAccessor::MoveSingleCell_impl(ColumnBinding buffer[cell_counter].hour = timestamp.tm_hour; buffer[cell_counter].minute = timestamp.tm_min; buffer[cell_counter].second = timestamp.tm_sec; - buffer[cell_counter].fraction = CalculateFraction(timestamp_type_->unit(), value); + buffer[cell_counter].fraction = CalculateFraction(UNIT, value); if (binding->strlen_buffer) { binding->strlen_buffer[cell_counter] = static_cast(GetCellLength_impl(binding)); @@ -102,12 +96,15 @@ TimestampArrayFlightSqlAccessor::MoveSingleCell_impl(ColumnBinding return odbcabstraction::RowStatus_SUCCESS; } -template -size_t TimestampArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { +template +size_t TimestampArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { return sizeof(TIMESTAMP_STRUCT); } -template class TimestampArrayFlightSqlAccessor; +template class TimestampArrayFlightSqlAccessor; +template class TimestampArrayFlightSqlAccessor; +template class TimestampArrayFlightSqlAccessor; +template class TimestampArrayFlightSqlAccessor; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h index e7daba00eea8f..de0fcfb23bcd5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor.h @@ -16,22 +16,19 @@ namespace flight_sql { using namespace arrow; using namespace odbcabstraction; -template +template class TimestampArrayFlightSqlAccessor : public FlightSqlAccessor> { + TimestampArrayFlightSqlAccessor> { public: explicit TimestampArrayFlightSqlAccessor(Array *array); - RowStatus MoveSingleCell_impl(ColumnBinding *binding, TimestampArray *array, int64_t cell_counter, + RowStatus MoveSingleCell_impl(ColumnBinding *binding, int64_t arrow_row, int64_t cell_counter, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics); size_t GetCellLength_impl(ColumnBinding *binding) const; - -private: - std::shared_ptr timestamp_type_; }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc index 079ab52132b6a..5486799ddd7c9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/timestamp_array_accessor_test.cc @@ -26,7 +26,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MILLI) { ArrayFromVector(timestamp_field->type(), values, ×tamp_array); - TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); + TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); std::vector buffer(values.size()); std::vector strlen_buffer(values.size()); @@ -67,7 +67,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_SECONDS) { ArrayFromVector(timestamp_field->type(), values, ×tamp_array); - TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); + TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); std::vector buffer(values.size()); std::vector strlen_buffer(values.size()); @@ -105,7 +105,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_MICRO) { ArrayFromVector(timestamp_field->type(), values, ×tamp_array); - TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); + TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); std::vector buffer(values.size()); std::vector strlen_buffer(values.size()); @@ -145,7 +145,7 @@ TEST(TEST_TIMESTAMP, TIMESTAMP_WITH_NANO) { ArrayFromVector(timestamp_field->type(), values, ×tamp_array); - TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); + TimestampArrayFlightSqlAccessor accessor(timestamp_array.get()); std::vector buffer(values.size()); std::vector strlen_buffer(values.size()); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h index 192770c99675d..dacd74fdd2e39 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/types.h @@ -69,34 +69,22 @@ class FlightSqlAccessor : public Accessor { size_t GetColumnarData(ColumnBinding *binding, int64_t starting_row, size_t cells, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics, uint16_t* row_status_array) override { - const std::shared_ptr &array = - array_->Slice(starting_row, static_cast(cells)); - - return GetColumnarData( - arrow::internal::checked_pointer_cast(array), binding, - value_offset, update_value_offset, diagnostics, row_status_array); + return static_cast(this)->GetColumnarData_impl( + binding, starting_row, cells, value_offset, update_value_offset, + diagnostics, row_status_array); } size_t GetCellLength(ColumnBinding *binding) const override { return static_cast(this)->GetCellLength_impl(binding); } -private: - ARROW_ARRAY *array_; - - size_t GetColumnarData(const std::shared_ptr &sliced_array, - ColumnBinding *binding, int64_t &value_offset, bool update_value_offset, - odbcabstraction::Diagnostics &diagnostics, uint16_t* row_status_array) { - return static_cast(this)->GetColumnarData_impl( - sliced_array, binding, value_offset, update_value_offset, diagnostics, row_status_array); - } - - size_t GetColumnarData_impl(const std::shared_ptr &sliced_array, - ColumnBinding *binding, int64_t &value_offset, bool update_value_offset, +protected: + size_t GetColumnarData_impl(ColumnBinding *binding, int64_t starting_row, int64_t cells, + int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics, uint16_t* row_status_array) { - int64_t length = sliced_array->length(); - for (int64_t i = 0; i < length; ++i) { - if (sliced_array->IsNull(i)) { + for (int64_t i = 0; i < cells; ++i) { + int64_t current_arrow_row = starting_row + i; + if (array_->IsNull(current_arrow_row)) { if (binding->strlen_buffer) { binding->strlen_buffer[i] = odbcabstraction::NULL_DATA; } else { @@ -105,25 +93,33 @@ class FlightSqlAccessor : public Accessor { } else { // TODO: Optimize this by creating different versions of MoveSingleCell // depending on if strlen_buffer is null. - auto row_status = MoveSingleCell(binding, sliced_array.get(), i, value_offset, update_value_offset, - diagnostics); + auto row_status = MoveSingleCell( + binding, current_arrow_row, i, value_offset, update_value_offset, + diagnostics); if (row_status_array) { row_status_array[i] = row_status; } } } - return length; + return static_cast(cells); + } + + inline ARROW_ARRAY *GetArray() { + return array_; } - odbcabstraction::RowStatus MoveSingleCell(ColumnBinding *binding, ARROW_ARRAY *array, int64_t i, +private: + ARROW_ARRAY *array_; + + odbcabstraction::RowStatus MoveSingleCell(ColumnBinding *binding, int64_t arrow_row, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { - return static_cast(this)->MoveSingleCell_impl(binding, array, i, + return static_cast(this)->MoveSingleCell_impl(binding, arrow_row, i, value_offset, update_value_offset, diagnostics); } - odbcabstraction::RowStatus MoveSingleCell_impl(ColumnBinding *binding, ARROW_ARRAY *array, + odbcabstraction::RowStatus MoveSingleCell_impl(ColumnBinding *binding, int64_t arrow_row, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { std::stringstream ss; ss << "Unknown type conversion from StringArray to target C type " diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index 6b76bd68a66ed..f902280fe150b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -231,7 +231,6 @@ bool FlightSqlResultSet::GetData(int column_n, int16_t target_type, // Note: current_row_ is always positioned at the index _after_ the one we are // on after calling Move(). So if we want to get data from the _last_ row // fetched, we need to subtract one from the current row. - // TODO: Should GetData update row status array? accessor->GetColumnarData(&binding, current_row_ - 1, 1, value_offset, true, diagnostics_, nullptr); // If there was truncation, the converter would have reported it to the diagnostics. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index ef9b8384d9631..85ee548618e2a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -100,15 +100,36 @@ const std::unordered_map(array); + auto time_type = + arrow::internal::checked_pointer_cast(array->type()); + auto time_unit = time_type->unit(); + Accessor* result; + switch (time_unit) { + case TimeUnit::SECOND: + result = new TimestampArrayFlightSqlAccessor(array); + break; + case TimeUnit::MILLI: + result = new TimestampArrayFlightSqlAccessor(array); + break; + case TimeUnit::MICRO: + result = new TimestampArrayFlightSqlAccessor(array); + break; + case TimeUnit::NANO: + result = new TimestampArrayFlightSqlAccessor(array); + break; + default: + assert(false); + throw DriverException("Unrecognized time unit " + std::to_string(time_unit)); + } + return result; }}, {SourceAndTargetPair(arrow::Type::type::TIME32, CDataType_TIME), [](arrow::Array *array) { - return new TimeArrayFlightSqlAccessor(array); + return CreateTimeAccessor(array, arrow::Type::type::TIME32); }}, {SourceAndTargetPair(arrow::Type::type::TIME64, CDataType_TIME), [](arrow::Array *array) { - return new TimeArrayFlightSqlAccessor(array); + return CreateTimeAccessor(array, arrow::Type::type::TIME64); }}, {SourceAndTargetPair(arrow::Type::type::DECIMAL128, CDataType_NUMERIC), [](arrow::Array *array) { From f0d6242c85461baf0ca03286bc15975ee3eea434 Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 18 Jul 2022 08:39:03 -0700 Subject: [PATCH 164/183] Avoid trying to create accessors without an array Fix bug in the accessor caching optimizations when the array was not yet set. Change-Id: Iee4e668066af211ceac0fbaddc75707a9f724cc9 --- .../flightsql-odbc/flight_sql/flight_sql_result_set_column.cc | 4 ++-- .../flightsql-odbc/flight_sql/flight_sql_result_set_column.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index ad51b36f757c5..2c5b7829d64a1 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -52,7 +52,7 @@ FlightSqlResultSetColumn::FlightSqlResultSetColumn(bool use_wide_char) : use_wide_char_(use_wide_char), is_bound_(false) {} -void FlightSqlResultSetColumn::SetBinding(ColumnBinding new_binding) { +void FlightSqlResultSetColumn::SetBinding(const ColumnBinding& new_binding) { binding_ = new_binding; is_bound_ = true; @@ -65,7 +65,7 @@ void FlightSqlResultSetColumn::SetBinding(ColumnBinding new_binding) { } // Rebuild the accessor and casted array if the target type changed. - if (!cached_casted_array_ || cached_accessor_->target_type_ != binding_.target_type) { + if (original_array_ && (!cached_casted_array_ || cached_accessor_->target_type_ != binding_.target_type)) { cached_accessor_ = CreateAccessor(binding_.target_type); } } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h index 2f40f7109b183..291f9232d547a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h @@ -48,7 +48,7 @@ class FlightSqlResultSetColumn { return GetAccessorForTargetType(target_type); } - void SetBinding(ColumnBinding new_binding); + void SetBinding(const ColumnBinding& new_binding); void ResetBinding(); From 6d3b9cd94bdc07db780387943fc4ef38c6f1ac6a Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 18 Jul 2022 09:05:12 -0700 Subject: [PATCH 165/183] Fix accessor caching when binding SQL_C_DEFAULT The accessor caching optimizations previously relied on the data array to determine the arrow type to resolve SQL_C_DEFAULT, however SQLBindCol can be called before this array has been retrieved. Instead determine the arrow type using the schema. Change-Id: I418f84ac26b456a068ec162531363aa58cf4a68c --- .../flight_sql/flight_sql_result_set.cc | 8 +++----- .../flight_sql/flight_sql_result_set_column.cc | 4 ++-- .../flight_sql/flight_sql_result_set_column.h | 15 ++++++--------- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index f902280fe150b..b26c44332bfdf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -69,8 +69,7 @@ size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, size_t bind_typ } for (size_t column_num = 0; column_num < columns_.size(); ++column_num) { - columns_[column_num].SetArrowArray(current_chunk_.data->column(column_num)); - columns_[column_num].ResetAccessor(); + columns_[column_num].ResetAccessor(current_chunk_.data->column(column_num)); } } @@ -96,8 +95,7 @@ size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, size_t bind_typ } for (size_t column_num = 0; column_num < columns_.size(); ++column_num) { - columns_[column_num].SetArrowArray(current_chunk_.data->column(column_num)); - columns_[column_num].ResetAccessor(); + columns_[column_num].ResetAccessor(current_chunk_.data->column(column_num)); } current_row_ = 0; continue; @@ -260,7 +258,7 @@ void FlightSqlResultSet::BindColumn(int column_n, int16_t target_type, ColumnBinding binding(ConvertCDataTypeFromV2ToV3(target_type), precision, scale, buffer, buffer_length, strlen_buffer); - column.SetBinding(binding); + column.SetBinding(binding, schema_->field(column_n - 1)->type()->id()); } FlightSqlResultSet::~FlightSqlResultSet() = default; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index 2c5b7829d64a1..41cb8f39542bc 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -52,7 +52,7 @@ FlightSqlResultSetColumn::FlightSqlResultSetColumn(bool use_wide_char) : use_wide_char_(use_wide_char), is_bound_(false) {} -void FlightSqlResultSetColumn::SetBinding(const ColumnBinding& new_binding) { +void FlightSqlResultSetColumn::SetBinding(const ColumnBinding& new_binding, arrow::Type::type arrow_type) { binding_ = new_binding; is_bound_ = true; @@ -60,7 +60,7 @@ void FlightSqlResultSetColumn::SetBinding(const ColumnBinding& new_binding) { // precision if it is zero (this is precision unset and will always fail). if (binding_.precision == 0 && (binding_.target_type == odbcabstraction::CDataType_NUMERIC) || - (binding_.target_type == odbcabstraction::CDataType_DEFAULT && original_array_->type_id() == arrow::Type::type::DECIMAL128)) { + (binding_.target_type == odbcabstraction::CDataType_DEFAULT && arrow_type == arrow::Type::type::DECIMAL128)) { binding_.precision = arrow::Decimal128Type::kMaxPrecision; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h index 291f9232d547a..0001679c8d572 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.h @@ -48,24 +48,21 @@ class FlightSqlResultSetColumn { return GetAccessorForTargetType(target_type); } - void SetBinding(const ColumnBinding& new_binding); + void SetBinding(const ColumnBinding& new_binding, arrow::Type::type arrow_type); void ResetBinding(); - inline void ResetAccessor() { - if (is_bound_) { - cached_accessor_ = CreateAccessor(cached_accessor_->target_type_); - } else if (cached_accessor_) { + inline void ResetAccessor(std::shared_ptr array) { + original_array_ = std::move(array); + if (cached_accessor_) { cached_accessor_ = CreateAccessor(cached_accessor_->target_type_); + } else if (is_bound_) { + cached_accessor_ = CreateAccessor(binding_.target_type); } else { cached_casted_array_.reset(); cached_accessor_.reset(); } } - - inline void SetArrowArray(std::shared_ptr array) { - original_array_ = std::move(array); - } }; } // namespace flight_sql } // namespace driver From e8fe0b44d5c11cda3f3631d79640cd5dd21d922e Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Mon, 11 Jul 2022 14:49:28 -0300 Subject: [PATCH 166/183] Allow setting the size of WCHAR This allows WCHAR size to be set in runtime, enabling the driver to work well with unixODBC and iODBC, which have different definitions for SQLWCHAR. Change-Id: I20d4492072bfd4b6f9847cfdb2258846ecd9c3a5 --- .../accessors/string_array_accessor.cc | 57 +++----- .../accessors/string_array_accessor.h | 19 ++- .../accessors/string_array_accessor_test.cc | 55 ++++--- .../flight_sql_result_set_accessors.cc | 6 +- .../flightsql-odbc/flight_sql/utils.cc | 7 +- .../flightsql-odbc/flight_sql/utils.h | 10 -- .../include/odbcabstraction/encoding.h | 136 ++++++++++++++++++ .../odbc_impl/AttributeUtils.h | 15 +- .../odbcabstraction/odbc_impl/EncodingUtils.h | 62 +++----- 9 files changed, 241 insertions(+), 126 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc index b2cd1df1e5cc8..bf64c0a97b6b7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -8,6 +8,7 @@ #include #include +#include namespace driver { namespace flight_sql { @@ -28,12 +29,12 @@ std::string utf8_to_clocale(const char *utf8str, int len) #endif template -inline RowStatus MoveSingleCellToCharBuffer(CharToWStrConverter *converter, - ColumnBinding *binding, - StringArray *array, int64_t arrow_row, int64_t i, - int64_t &value_offset, - bool update_value_offset, - odbcabstraction::Diagnostics &diagnostics) { +inline RowStatus MoveSingleCellToCharBuffer(std::vector &buffer, + ColumnBinding *binding, + StringArray *array, int64_t arrow_row, int64_t i, + int64_t &value_offset, + bool update_value_offset, + odbcabstraction::Diagnostics &diagnostics) { RowStatus result = odbcabstraction::RowStatus_SUCCESS; // Arrow strings come as UTF-8 @@ -42,14 +43,13 @@ inline RowStatus MoveSingleCellToCharBuffer(CharToWStrConverter *converter, const void *value; size_t size_in_bytes; - SqlWString wstr; #if defined _WIN32 || defined _WIN64 std::string clocale_str; #endif if (sizeof(CHAR_TYPE) > sizeof(char)) { - wstr = converter->from_bytes(raw_value, raw_value + raw_value_length); - value = wstr.data(); - size_in_bytes = wstr.size() * sizeof(CHAR_TYPE); + Utf8ToWcs(raw_value, raw_value_length, &buffer); + value = buffer.data(); + size_in_bytes = buffer.size(); } else { #if defined _WIN32 || defined _WIN64 // Convert to C locale string @@ -104,38 +104,27 @@ inline RowStatus MoveSingleCellToCharBuffer(CharToWStrConverter *converter, } // namespace -template -StringArrayFlightSqlAccessor::StringArrayFlightSqlAccessor( +template +StringArrayFlightSqlAccessor::StringArrayFlightSqlAccessor( Array *array) : FlightSqlAccessor>(array), - converter_() {} - -template <> -RowStatus StringArrayFlightSqlAccessor::MoveSingleCell_impl( - ColumnBinding *binding, int64_t arrow_row, int64_t i, int64_t &value_offset, - bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { - return MoveSingleCellToCharBuffer( - &converter_, binding, this->GetArray(), arrow_row, i, - value_offset, update_value_offset, diagnostics); -} + StringArrayFlightSqlAccessor>(array) {} -template <> -RowStatus StringArrayFlightSqlAccessor::MoveSingleCell_impl( - ColumnBinding *binding, int64_t arrow_row, int64_t i, int64_t &value_offset, - bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { - return MoveSingleCellToCharBuffer( - &converter_, binding, this->GetArray(), arrow_row, i, - value_offset, update_value_offset, diagnostics); +template +RowStatus StringArrayFlightSqlAccessor::MoveSingleCell_impl( + ColumnBinding *binding, int64_t arrow_row, int64_t i, int64_t &value_offset, + bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { + return MoveSingleCellToCharBuffer(buffer_, binding, this->GetArray(), arrow_row, i, value_offset, update_value_offset, diagnostics); } -template -size_t StringArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { +template +size_t StringArrayFlightSqlAccessor::GetCellLength_impl(ColumnBinding *binding) const { return binding->buffer_length; } -template class StringArrayFlightSqlAccessor; -template class StringArrayFlightSqlAccessor; +template class StringArrayFlightSqlAccessor; +template class StringArrayFlightSqlAccessor; +template class StringArrayFlightSqlAccessor; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h index 7964a2dbbfc37..a99a1bb0039c5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h @@ -11,6 +11,7 @@ #include "utils.h" #include #include +#include namespace driver { namespace flight_sql { @@ -18,10 +19,10 @@ namespace flight_sql { using namespace arrow; using namespace odbcabstraction; -template +template class StringArrayFlightSqlAccessor : public FlightSqlAccessor> { + StringArrayFlightSqlAccessor> { public: explicit StringArrayFlightSqlAccessor(Array *array); @@ -32,8 +33,20 @@ class StringArrayFlightSqlAccessor size_t GetCellLength_impl(ColumnBinding *binding) const; private: - CharToWStrConverter converter_; + std::vector buffer_; }; +inline Accessor* CreateWCharStringArrayAccessor(arrow::Array *array) { + switch(GetSqlWCharSize()) { + case sizeof(char16_t): + return new StringArrayFlightSqlAccessor(array); + case sizeof(char32_t): + return new StringArrayFlightSqlAccessor(array); + default: + assert(false); + throw DriverException("Encoding is unsupported, SQLWCHAR size: " + std::to_string(GetSqlWCharSize())); + } +} + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc index 2fe23f3123064..a8f5891aae676 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor_test.cc @@ -7,6 +7,7 @@ #include "arrow/testing/builder.h" #include "string_array_accessor.h" #include "gtest/gtest.h" +#include "odbcabstraction/encoding.h" namespace driver { namespace flight_sql { @@ -19,7 +20,7 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Basic) { std::shared_ptr array; ArrayFromVector(values, &array); - StringArrayFlightSqlAccessor accessor(array.get()); + StringArrayFlightSqlAccessor accessor(array.get()); size_t max_strlen = 64; std::vector buffer(values.size() * max_strlen); @@ -45,7 +46,7 @@ TEST(StringArrayAccessor, Test_CDataType_CHAR_Truncation) { std::shared_ptr array; ArrayFromVector(values, &array); - StringArrayFlightSqlAccessor accessor(array.get()); + StringArrayFlightSqlAccessor accessor(array.get()); size_t max_strlen = 8; std::vector buffer(values.size() * max_strlen); @@ -77,10 +78,10 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Basic) { std::shared_ptr array; ArrayFromVector(values, &array); - StringArrayFlightSqlAccessor accessor(array.get()); + auto accessor = CreateWCharStringArrayAccessor(array.get()); size_t max_strlen = 64; - std::vector buffer(values.size() * max_strlen); + std::vector buffer(values.size() * max_strlen); std::vector strlen_buffer(values.size()); ColumnBinding binding(CDataType_WCHAR, 0, 0, buffer.data(), max_strlen, @@ -89,49 +90,59 @@ TEST(StringArrayAccessor, Test_CDataType_WCHAR_Basic) { int64_t value_offset = 0; odbcabstraction::Diagnostics diagnostics("Foo", "Foo", OdbcVersion::V_3); ASSERT_EQ(values.size(), - accessor.GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); + accessor->GetColumnarData(&binding, 0, values.size(), value_offset, false, diagnostics, nullptr)); for (int i = 0; i < values.size(); ++i) { - ASSERT_EQ(values[i].length() * sizeof(SqlWChar), strlen_buffer[i]); - auto expected = CharToWStrConverter().from_bytes(values[i].c_str()); - auto actual = SqlWString(buffer.data() + i * max_strlen / sizeof(SqlWChar)); - ASSERT_EQ(0, expected.compare(actual)); + ASSERT_EQ(values[i].length() * GetSqlWCharSize(), strlen_buffer[i]); + std::vector expected; + Utf8ToWcs(values[i].c_str(), &expected); + uint8_t *start = buffer.data() + i * max_strlen; + auto actual = std::vector(start, start + strlen_buffer[i]); + ASSERT_EQ(expected, actual); } } TEST(StringArrayAccessor, Test_CDataType_WCHAR_Truncation) { std::vector values = { - "ABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEF"}; + "ABCDEFA"}; std::shared_ptr array; ArrayFromVector(values, &array); - StringArrayFlightSqlAccessor accessor(array.get()); + auto accessor = CreateWCharStringArrayAccessor(array.get()); size_t max_strlen = 8; - std::vector buffer(values.size() * max_strlen); + std::vector buffer(values.size() * max_strlen); std::vector strlen_buffer(values.size()); ColumnBinding binding(CDataType_WCHAR, 0, 0, buffer.data(), - max_strlen * sizeof(SqlWChar), strlen_buffer.data()); + max_strlen, strlen_buffer.data()); - std::basic_stringstream ss; + std::basic_stringstream ss; int64_t value_offset = 0; // Construct the whole string by concatenating smaller chunks from // GetColumnarData - std::basic_string finalStr; + std::vector finalStr; driver::odbcabstraction::Diagnostics diagnostics("Dummy", "Dummy", odbcabstraction::V_3); do { int64_t original_value_offset = value_offset; - ASSERT_EQ(1, accessor.GetColumnarData(&binding, 0, 1, value_offset, true, diagnostics, nullptr)); - ASSERT_EQ(values[0].length() * sizeof(SqlWChar) - original_value_offset, strlen_buffer[0]); + ASSERT_EQ(1, accessor->GetColumnarData(&binding, 0, 1, value_offset, true, diagnostics, nullptr)); + ASSERT_EQ(values[0].length() * GetSqlWCharSize() - original_value_offset, strlen_buffer[0]); + + size_t length = value_offset - original_value_offset; + if (value_offset == -1) { + length = buffer.size(); + } + finalStr.insert(finalStr.end(), buffer.data(), buffer.data() + length); + + } while (value_offset < values[0].length() * GetSqlWCharSize() && value_offset != -1); - finalStr += std::basic_string(buffer.data()); - } while (value_offset < values[0].length() * sizeof(SqlWChar) && value_offset != -1); + // Trim final null bytes + finalStr.resize(values[0].length() * GetSqlWCharSize()); - auto expected = CharToWStrConverter().from_bytes(values[0].c_str()); - auto actual = finalStr; - ASSERT_EQ(0, expected.compare(actual)); + std::vector expected; + Utf8ToWcs(values[0].c_str(), &expected); + ASSERT_EQ(expected, finalStr); } } // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index 85ee548618e2a..dda3c61cc78ab 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -24,12 +24,10 @@ const std::unordered_map(array); + return new StringArrayFlightSqlAccessor(array); }}, {SourceAndTargetPair(arrow::Type::type::STRING, CDataType_WCHAR), - [](arrow::Array *array) { - return new StringArrayFlightSqlAccessor(array); - }}, + CreateWCharStringArrayAccessor}, {SourceAndTargetPair(arrow::Type::type::DOUBLE, CDataType_DOUBLE), [](arrow::Array *array) { return new PrimitiveArrayFlightSqlAccessor +#include #include #include @@ -359,7 +360,7 @@ optional GetCharOctetLength(SqlDataType data_type, case SqlDataType_WVARCHAR: case SqlDataType_WLONGVARCHAR: if (column_size.ok()) { - return column_size.ValueOrDie() * sizeof(SqlWChar); + return column_size.ValueOrDie() * GetSqlWCharSize(); } else { return arrow::util::nullopt; } @@ -431,7 +432,7 @@ optional GetColumnSize(SqlDataType data_type, case SqlDataType_WCHAR: case SqlDataType_WVARCHAR: case SqlDataType_WLONGVARCHAR: - return column_size.has_value() ? arrow::util::make_optional(column_size.value() * sizeof(SqlWChar)) + return column_size.has_value() ? arrow::util::make_optional(column_size.value() * GetSqlWCharSize()) : arrow::util::nullopt; case SqlDataType_BINARY: case SqlDataType_VARBINARY: @@ -492,7 +493,7 @@ optional GetBufferLength(SqlDataType data_type, case SqlDataType_WCHAR: case SqlDataType_WVARCHAR: case SqlDataType_WLONGVARCHAR: - return column_size.has_value() ? arrow::util::make_optional(column_size.value() * sizeof(SqlWChar)) + return column_size.has_value() ? arrow::util::make_optional(column_size.value() * GetSqlWCharSize()) : arrow::util::nullopt; case SqlDataType_BINARY: case SqlDataType_VARBINARY: diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h index a883c66c47435..374c3064ee946 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/utils.h @@ -22,16 +22,6 @@ typedef std::function< using arrow::util::optional; -#ifdef WITH_IODBC -using SqlWChar = char32_t; -using SqlWString = std::u32string; -#else -using SqlWChar = char16_t; -using SqlWString = std::u16string; -#endif -using CharToWStrConverter = - std::wstring_convert, SqlWChar>; - inline void ThrowIfNotOK(const arrow::Status &status) { if (!status.ok()) { throw odbcabstraction::DriverException(status.message()); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h new file mode 100644 index 0000000000000..e67a06f3a5264 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace driver { +namespace odbcabstraction { + +#if defined(__APPLE__) +namespace { +static std::mutex SqlWCharSizeMutex; +static std::atomic SqlWCharSize{0}; +} + +// TODO: I think this should be set from warpdrive somehow +inline size_t GetSqlWCharSize() { + if (SqlWCharSize == 0) { + std::unique_lock lock(SqlWCharSizeMutex); + if (SqlWCharSize == 0) { // double-checked locking + + // TODO: Detect driver manager + const char *env_p = std::getenv("WCHAR_ENCODING"); + if (env_p) { + if (boost::iequals(env_p, "UTF-16")) { + SqlWCharSize = sizeof(char16_t); + } else if (boost::iequals(env_p, "UTF-32")) { + SqlWCharSize = sizeof(char32_t); + } + } else { + // Default to UTF32 on Mac + SqlWCharSize = sizeof(char32_t); + } + } + } + + return SqlWCharSize; +} +#else +constexpr inline size_t GetSqlWCharSize() { + return sizeof(char16_t); +} +#endif + +namespace { + +template +inline size_t wcsstrlen(const void *wcs_string) { + size_t len; + for (len = 0; ((CHAR_TYPE *) wcs_string)[len]; len++); + return len; +} + +inline size_t wcsstrlen(const void *wcs_string) { + switch (GetSqlWCharSize()) { + case sizeof(char16_t): + return wcsstrlen(wcs_string); + case sizeof(char32_t): + return wcsstrlen(wcs_string); + default: + assert(false); + throw DriverException("Encoding is unsupported, SQLWCHAR size: " + std::to_string(GetSqlWCharSize())); + } +} + +} + +template +inline void Utf8ToWcs(const char *utf8_string, size_t length, std::vector *result) { + thread_local std::wstring_convert, CHAR_TYPE> converter; + auto string = converter.from_bytes(utf8_string, utf8_string + length); + + unsigned long length_in_bytes = string.size() * GetSqlWCharSize(); + const uint8_t *data = (uint8_t*) string.data(); + + result->reserve(length_in_bytes); + result->assign(data, data + length_in_bytes); +} + +inline void Utf8ToWcs(const char *utf8_string, size_t length, std::vector *result) { + switch (GetSqlWCharSize()) { + case sizeof(char16_t): + return Utf8ToWcs(utf8_string, length, result); + case sizeof(char32_t): + return Utf8ToWcs(utf8_string, length, result); + default: + assert(false); + throw DriverException("Encoding is unsupported, SQLWCHAR size: " + std::to_string(GetSqlWCharSize())); + } +} + +inline void Utf8ToWcs(const char *utf8_string, std::vector *result) { + return Utf8ToWcs(utf8_string, strlen(utf8_string), result); +} + +template +inline void WcsToUtf8(const void *wcs_string, size_t length_in_code_units, std::vector *result) { + thread_local std::wstring_convert, CHAR_TYPE> converter; + auto byte_string = converter.to_bytes((CHAR_TYPE*) wcs_string, (CHAR_TYPE*) wcs_string + length_in_code_units * GetSqlWCharSize()); + + unsigned long length_in_bytes = byte_string.size(); + const uint8_t *data = (uint8_t*) byte_string.data(); + + result->reserve(length_in_bytes); + result->assign(data, data + length_in_bytes); +} + +inline void WcsToUtf8(const void *wcs_string, size_t length_in_code_units, std::vector *result) { + switch (GetSqlWCharSize()) { + case sizeof(char16_t): + return WcsToUtf8(wcs_string, length_in_code_units, result); + case sizeof(char32_t): + return WcsToUtf8(wcs_string, length_in_code_units, result); + default: + assert(false); + throw DriverException("Encoding is unsupported, SQLWCHAR size: " + std::to_string(GetSqlWCharSize())); + } +} + +inline void WcsToUtf8(const void *wcs_string, std::vector *result) { + return WcsToUtf8(wcs_string, wcsstrlen(wcs_string), result); +} + +} +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/AttributeUtils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/AttributeUtils.h index d77044e32029c..5028d8a777d5e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/AttributeUtils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/AttributeUtils.h @@ -66,13 +66,13 @@ inline SQLRETURN GetAttributeSQLWCHAR(const std::string &attributeValue, bool is SQLPOINTER output, O outputSize, O *outputLenPtr) { size_t result = ConvertToSqlWChar( - attributeValue, reinterpret_cast(output), isLengthInBytes ? outputSize : outputSize * sizeof(SQLWCHAR)); + attributeValue, reinterpret_cast(output), isLengthInBytes ? outputSize : outputSize * GetSqlWCharSize()); if (outputLenPtr) { - *outputLenPtr = static_cast(isLengthInBytes ? result : result / sizeof(SQLWCHAR)); + *outputLenPtr = static_cast(isLengthInBytes ? result : result / GetSqlWCharSize()); } - if (output && outputSize < result + (isLengthInBytes ? sizeof(SQLWCHAR) : 1)) { + if (output && outputSize < result + (isLengthInBytes ? GetSqlWCharSize() : 1)) { return SQL_SUCCESS_WITH_INFO; } return SQL_SUCCESS; @@ -128,14 +128,13 @@ inline void SetAttributeUTF8(SQLPOINTER newValue, SQLINTEGER inputLength, inline void SetAttributeSQLWCHAR(SQLPOINTER newValue, SQLINTEGER inputLengthInBytes, std::string &attributeToWrite) { - SqlWString wstr; + thread_local std::vector utf8_str; if (inputLengthInBytes == SQL_NTS) { - wstr.assign(reinterpret_cast(newValue)); + WcsToUtf8(newValue, &utf8_str); } else { - wstr.assign(reinterpret_cast(newValue), - inputLengthInBytes / sizeof(SqlWChar)); + WcsToUtf8(newValue, inputLengthInBytes / GetSqlWCharSize(), &utf8_str); } - attributeToWrite = CharToWStrConverter().to_bytes(wstr.c_str()); + attributeToWrite.assign((char *) utf8_str.data()); } template diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h index 6c68f92e65161..0ec18f3f2f0fd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -19,64 +20,41 @@ #define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING namespace ODBC { - #ifdef WITH_IODBC - typedef char32_t SqlWChar; - typedef std::u32string SqlWString; - typedef std::wstring_convert, char32_t> CharToWStrConverter; - #else - typedef char16_t SqlWChar; - typedef std::u16string SqlWString; - typedef std::wstring_convert, char16_t> CharToWStrConverter; - #endif + using namespace driver::odbcabstraction; // Return the number of bytes required for the conversion. + template inline size_t ConvertToSqlWChar(const std::string& str, SQLWCHAR* buffer, SQLLEN bufferSizeInBytes) { - SqlWString wstr = CharToWStrConverter().from_bytes(str); - SQLLEN valueLengthInBytes = wstr.size() * sizeof(SqlWChar); + thread_local std::vector wstr; + Utf8ToWcs(str.data(), &wstr); + SQLLEN valueLengthInBytes = wstr.size(); if (buffer) { - memcpy(buffer, wstr.data(), std::min(static_cast(wstr.size() * sizeof(SqlWChar)), bufferSizeInBytes)); + memcpy(buffer, wstr.data(), std::min(static_cast(wstr.size()), bufferSizeInBytes)); // Write a NUL terminator - if (bufferSizeInBytes >= valueLengthInBytes + sizeof(SqlWChar)) { - reinterpret_cast(buffer)[wstr.size()] = '\0'; + if (bufferSizeInBytes >= valueLengthInBytes + GetSqlWCharSize()) { + reinterpret_cast(buffer)[wstr.size()] = '\0'; } else { - SQLLEN numCharsWritten = bufferSizeInBytes / sizeof(SqlWChar); + SQLLEN numCharsWritten = bufferSizeInBytes / GetSqlWCharSize(); // If we failed to even write one char, the buffer is too small to hold a NUL-terminator. if (numCharsWritten > 0) { - reinterpret_cast(buffer)[numCharsWritten-1] = '\0'; + reinterpret_cast(buffer)[numCharsWritten-1] = '\0'; } } } return valueLengthInBytes; } - // Return the number of bytes required for the conversion. - inline size_t ConvertToSqlWChar(const SQLCHAR* str, SQLLEN numChars, SQLWCHAR* buffer, SQLLEN bufferSizeInBytes) { - if (numChars != SQL_NTS) { - return ConvertToSqlWChar(std::string(reinterpret_cast(str), numChars), buffer, bufferSizeInBytes); - } - return ConvertToSqlWChar(std::string(reinterpret_cast(str)), buffer, bufferSizeInBytes); - } - - // Return the number of bytes required for the conversion. - inline size_t ConvertToSqlChar(const SQLWCHAR* str, SQLLEN numChars, SQLCHAR* buffer, SQLLEN bufferSizeInBytes) { - SqlWString wstr; - if (numChars != SQL_NTS) { - wstr = SqlWString(reinterpret_cast(str), numChars); - } else { - wstr = SqlWString(reinterpret_cast(str)); - } - - std::string converted = CharToWStrConverter().to_bytes(wstr.c_str()); - if (buffer) { - memcpy(buffer, converted.c_str(), std::min(bufferSizeInBytes, static_cast(converted.size()))); - if (bufferSizeInBytes >= converted.size() + 1) { - buffer[converted.size()] = '\0'; - } else if (bufferSizeInBytes > 0){ - buffer[bufferSizeInBytes - 1] = '\0'; - } + inline size_t ConvertToSqlWChar(const std::string& str, SQLWCHAR* buffer, SQLLEN bufferSizeInBytes) { + switch (GetSqlWCharSize()) { + case sizeof(char16_t): + return ConvertToSqlWChar(str, buffer, bufferSizeInBytes); + case sizeof(char32_t): + return ConvertToSqlWChar(str, buffer, bufferSizeInBytes); + default: + assert(false); + throw DriverException("Encoding is unsupported, SQLWCHAR size: " + std::to_string(GetSqlWCharSize())); } - return converted.size(); } } From bc0b27223541d79d6aef7708cc32f8ca6a3437cf Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 18 Jul 2022 13:36:21 -0700 Subject: [PATCH 167/183] Fix errors with SQL_C_DEFAULT - Evaluate the type corresponding to the arrow type at bind time instead of from the accessor, since the accessor may not have been constructed. - Fix use of ARD records when the ARD has too few records Change-Id: I5f5795890c6d30be4f667a011edfe8b229238352 --- .../flight_sql/flight_sql_result_set_column.cc | 7 +++++-- .../odbcabstraction/odbc_impl/ODBCStatement.cc | 14 +++++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc index 41cb8f39542bc..bd0a2e145cde4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_column.cc @@ -56,11 +56,14 @@ void FlightSqlResultSetColumn::SetBinding(const ColumnBinding& new_binding, arro binding_ = new_binding; is_bound_ = true; + if (binding_.target_type == odbcabstraction::CDataType_DEFAULT) { + binding_.target_type = ConvertArrowTypeToC(arrow_type, use_wide_char_); + } + // Overwrite the binding if the caller is using SQL_C_NUMERIC and has used zero // precision if it is zero (this is precision unset and will always fail). if (binding_.precision == 0 && - (binding_.target_type == odbcabstraction::CDataType_NUMERIC) || - (binding_.target_type == odbcabstraction::CDataType_DEFAULT && arrow_type == arrow::Type::type::DECIMAL128)) { + binding_.target_type == odbcabstraction::CDataType_NUMERIC) { binding_.precision = arrow::Decimal128Type::kMaxPrecision; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc index a6dc5be76bd85..20524f7e7cdf9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/odbc_impl/ODBCStatement.cc @@ -650,8 +650,9 @@ bool ODBCStatement::GetData(SQLSMALLINT recordNumber, SQLSMALLINT cType, SQLPOIN int scale = 0; if (cType == SQL_ARD_TYPE) { - // DM should validate the ARD size. - assert(m_currentArd->GetRecords().size() <= recordNumber); + if (recordNumber > m_currentArd->GetRecords().size()) { + throw DriverException("Invalid column index: " + std::to_string(recordNumber), "07009"); + } const DescriptorRecord& record = m_currentArd->GetRecords()[recordNumber-1]; evaluatedCType = record.m_conciseType; precision = record.m_precision; @@ -660,9 +661,12 @@ bool ODBCStatement::GetData(SQLSMALLINT recordNumber, SQLSMALLINT cType, SQLPOIN // Note: this is intentionally not an else if, since the type can be SQL_C_DEFAULT in the ARD. if (evaluatedCType == SQL_C_DEFAULT) { - const DescriptorRecord& ardRecord = m_currentArd->GetRecords()[recordNumber-1]; - precision = ardRecord.m_precision; - scale = ardRecord.m_scale; + if (recordNumber <= m_currentArd->GetRecords().size()) { + const DescriptorRecord &ardRecord = + m_currentArd->GetRecords()[recordNumber - 1]; + precision = ardRecord.m_precision; + scale = ardRecord.m_scale; + } const DescriptorRecord& irdRecord = m_ird->GetRecords()[recordNumber-1]; evaluatedCType = getCTypeForSQLType(irdRecord); From 4e0415d30b0bbd1867dad39f2eaf25ad22b89fa2 Mon Sep 17 00:00:00 2001 From: James Duong Date: Mon, 18 Jul 2022 14:11:00 -0700 Subject: [PATCH 168/183] Explicitly initialize and uninitialize grpc Run grpc_init() and grpc_shutdown() directly as part of starting and stopping the driver based on https://github.com/grpc/grpc/issues/25020 Change-Id: I54799cd0c217cc8038fc07d0d9cf791a12a062e1 --- .../flightsql-odbc/flight_sql/flight_sql_driver.cc | 11 +++++++++-- .../flight_sql/include/flight_sql/flight_sql_driver.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index 8e731d3b4414f..cb59ccac78c55 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -8,6 +8,8 @@ #include #include +#include + namespace driver { namespace flight_sql { @@ -16,8 +18,13 @@ using odbcabstraction::OdbcVersion; FlightSqlDriver::FlightSqlDriver() : diagnostics_("Apache Arrow", "Flight SQL", OdbcVersion::V_3), - version_("0.9.0.0") -{} + version_("0.9.0.0") { + grpc_init(); +} + +FlightSqlDriver::~FlightSqlDriver() { + grpc_shutdown_blocking(); +} std::shared_ptr FlightSqlDriver::CreateConnection(OdbcVersion odbc_version) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h index e55a7126c0359..f63da27ab3f31 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h @@ -19,6 +19,7 @@ class FlightSqlDriver : public odbcabstraction::Driver { public: FlightSqlDriver(); + ~FlightSqlDriver() override; std::shared_ptr CreateConnection(odbcabstraction::OdbcVersion odbc_version) override; From b1291b7920ccddd51859690ac3dcc9c8ff94d439 Mon Sep 17 00:00:00 2001 From: James Duong Date: Tue, 19 Jul 2022 10:30:51 -0700 Subject: [PATCH 169/183] Fix crash when using SQLBindCol with synthesized catalog columns Fix crash when using SQLBindCol to get the type of a synthetic column. The code was incorrectly using the schema directly from Arrow rather than using the transformed schema from the RecordBatchTransformer. Change-Id: I0d28a827ac4bb81359e5dd42a62108312d2c1266 --- .../flightsql-odbc/flight_sql/flight_sql_result_set.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index b26c44332bfdf..a293b4bf91de6 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -48,7 +48,11 @@ FlightSqlResultSet::FlightSqlResultSet( diagnostics_(diagnostics), current_row_(0), num_binding_(0), reset_get_data_(false) { current_chunk_.data = nullptr; - ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema_)); + if (transformer_) { + schema_ = transformer_->GetTransformedSchema(); + } else { + ThrowIfNotOK(flight_info->GetSchema(nullptr, &schema_)); + } for (size_t i = 0; i < columns_.size(); ++i) { columns_[i] = FlightSqlResultSetColumn(metadata_settings.use_wide_char_); From d0f569c168861f3f55f0bc42628110ea16036af6 Mon Sep 17 00:00:00 2001 From: James Duong Date: Tue, 19 Jul 2022 11:47:43 -0700 Subject: [PATCH 170/183] Fix crash when retrieving data as timestamp Fix a bad cast when retrieving timestamps. Change-Id: I9badcb88db0a0bdcbf23b632a1c11fa6fd6fef17 --- .../flight_sql/flight_sql_result_set_accessors.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc index dda3c61cc78ab..4fedfc8c5bacf 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set_accessors.cc @@ -99,7 +99,7 @@ const std::unordered_map(array->type()); + arrow::internal::checked_pointer_cast(array->type()); auto time_unit = time_type->unit(); Accessor* result; switch (time_unit) { From b178670abf635a67bdd8954f31bdf54c57d7cb24 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 19 Jul 2022 14:36:56 -0300 Subject: [PATCH 171/183] Set SQLWCHAR size depending on driver manager This allows the driver to be used on Mac with both unixODBC and iODBC driver manager without needing to set any environment variables. This is done by detecting which driver manager us being used and adjusting the encoding used for SQLWCHAR. Change-Id: Ica3a593861e9eed6f330e900111a716a799638c1 --- .../include/odbcabstraction/encoding.h | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h index e67a06f3a5264..94d04c6806505 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h @@ -12,9 +12,13 @@ #include #include #include -#include #include +#if defined(__APPLE__) +#include +#include +#endif + namespace driver { namespace odbcabstraction { @@ -22,26 +26,35 @@ namespace odbcabstraction { namespace { static std::mutex SqlWCharSizeMutex; static std::atomic SqlWCharSize{0}; + +bool IsUsingIODBC() { + // Detects iODBC by looking up by symbol iodbc_version + void* handle = dlsym(RTLD_DEFAULT, "iodbc_version"); + bool using_iodbc = handle != nullptr; + dlclose(handle); + + return using_iodbc; +} } -// TODO: I think this should be set from warpdrive somehow inline size_t GetSqlWCharSize() { if (SqlWCharSize == 0) { std::unique_lock lock(SqlWCharSizeMutex); if (SqlWCharSize == 0) { // double-checked locking - // TODO: Detect driver manager const char *env_p = std::getenv("WCHAR_ENCODING"); if (env_p) { if (boost::iequals(env_p, "UTF-16")) { SqlWCharSize = sizeof(char16_t); + return SqlWCharSize; } else if (boost::iequals(env_p, "UTF-32")) { SqlWCharSize = sizeof(char32_t); + return SqlWCharSize; } - } else { - // Default to UTF32 on Mac - SqlWCharSize = sizeof(char32_t); } + + bool using_iodbc = IsUsingIODBC(); + SqlWCharSize = using_iodbc ? sizeof(char32_t) : sizeof(char16_t); } } From a4a226b8d63cd941b6c672926fcd0f5026c2716b Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Tue, 19 Jul 2022 19:36:17 -0300 Subject: [PATCH 172/183] Rework GetSqlWCharSize for Mac Change-Id: I2a933fbb9406411ef0129be518e2b80acd707c02 --- .../odbcabstraction/CMakeLists.txt | 1 + .../odbcabstraction/encoding.cc | 52 +++++++++++++++++++ .../include/odbcabstraction/encoding.h | 34 ++---------- 3 files changed, 56 insertions(+), 31 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/encoding.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index d53a7997d5867..0ffd493a201e7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -30,6 +30,7 @@ add_library(odbcabstraction include/odbcabstraction/spi/statement.h calendar_utils.cc diagnostics.cc + encoding.cc exceptions.cc utils.cc odbc_impl/ODBCConnection.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/encoding.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/encoding.cc new file mode 100644 index 0000000000000..799ff6c47357b --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/encoding.cc @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#include + +#if defined(__APPLE__) +#include +#include +#include +#endif + +namespace driver { +namespace odbcabstraction { + +#if defined(__APPLE__) +namespace { +std::mutex SqlWCharSizeMutex; + +bool IsUsingIODBC() { + // Detects iODBC by looking up by symbol iodbc_version + void* handle = dlsym(RTLD_DEFAULT, "iodbc_version"); + bool using_iodbc = handle != nullptr; + dlclose(handle); + + return using_iodbc; +} +} + +void ComputeSqlWCharSize() { + std::unique_lock lock(SqlWCharSizeMutex); + if (SqlWCharSize != 0) return; // double-checked locking + + const char *env_p = std::getenv("WCHAR_ENCODING"); + if (env_p) { + if (boost::iequals(env_p, "UTF-16")) { + SqlWCharSize = sizeof(char16_t); + return; + } else if (boost::iequals(env_p, "UTF-32")) { + SqlWCharSize = sizeof(char32_t); + return; + } + } + + SqlWCharSize = IsUsingIODBC() ? sizeof(char32_t) : sizeof(char16_t); +} +#endif + +} // namespace odbcabstraction +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h index 94d04c6806505..ef9ff75ca9a8f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h @@ -6,7 +6,6 @@ #pragma once -#include #include #include #include @@ -15,47 +14,20 @@ #include #if defined(__APPLE__) -#include -#include +#include #endif namespace driver { namespace odbcabstraction { #if defined(__APPLE__) -namespace { -static std::mutex SqlWCharSizeMutex; static std::atomic SqlWCharSize{0}; -bool IsUsingIODBC() { - // Detects iODBC by looking up by symbol iodbc_version - void* handle = dlsym(RTLD_DEFAULT, "iodbc_version"); - bool using_iodbc = handle != nullptr; - dlclose(handle); - - return using_iodbc; -} -} +void ComputeSqlWCharSize(); inline size_t GetSqlWCharSize() { if (SqlWCharSize == 0) { - std::unique_lock lock(SqlWCharSizeMutex); - if (SqlWCharSize == 0) { // double-checked locking - - const char *env_p = std::getenv("WCHAR_ENCODING"); - if (env_p) { - if (boost::iequals(env_p, "UTF-16")) { - SqlWCharSize = sizeof(char16_t); - return SqlWCharSize; - } else if (boost::iequals(env_p, "UTF-32")) { - SqlWCharSize = sizeof(char32_t); - return SqlWCharSize; - } - } - - bool using_iodbc = IsUsingIODBC(); - SqlWCharSize = using_iodbc ? sizeof(char32_t) : sizeof(char16_t); - } + ComputeSqlWCharSize(); } return SqlWCharSize; From 9aec433a092aab5e51b49bb32f94e67dbd31ae68 Mon Sep 17 00:00:00 2001 From: James Duong Date: Wed, 20 Jul 2022 14:55:57 -0700 Subject: [PATCH 173/183] Fix error recording the detected encoding on Mac When static (non-class) variables are defined in headers they are just copied into each compilation unit instead of shared. Instead define it the recorded encoding to be extern. Change-Id: I197bedd8367b3b631459b42fc51878af57598066 --- .../flightsql-odbc/odbcabstraction/encoding.cc | 2 ++ .../odbcabstraction/include/odbcabstraction/encoding.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/encoding.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/encoding.cc index 799ff6c47357b..4952db80f2ff3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/encoding.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/encoding.cc @@ -16,6 +16,8 @@ namespace driver { namespace odbcabstraction { #if defined(__APPLE__) +std::atomic SqlWCharSize{0}; + namespace { std::mutex SqlWCharSizeMutex; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h index ef9ff75ca9a8f..70375fb126852 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h @@ -21,7 +21,7 @@ namespace driver { namespace odbcabstraction { #if defined(__APPLE__) -static std::atomic SqlWCharSize{0}; +extern std::atomic SqlWCharSize; void ComputeSqlWCharSize(); From 6ec395dccc9e8e62a72a02f8ac84c4305ddb6ca2 Mon Sep 17 00:00:00 2001 From: James Duong Date: Wed, 20 Jul 2022 15:05:48 -0700 Subject: [PATCH 174/183] Fix crash with null scalar fields Fix a crash if a scalar field had a null value. Check for nullity and explicitly write a null value if the scalar value is null. Also explicitly define NDEBUG when using release builds to prevent rapidjson from assert failing in release. Change-Id: I29f4bac18acdcee98988f08cd713692d780303b1 --- .../flightsql-odbc/CMakeLists.txt | 4 ++++ .../flightsql-odbc/flight_sql/json_converter.cc | 15 +++++++++------ .../flight_sql/json_converter_test.cc | 8 ++++++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index 94d1891a1e1d2..cd7966fac61d7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -21,6 +21,10 @@ else() endif() include_directories(${ODBC_INCLUDE_DIRS}) +if(CMAKE_BUILD_TYPE STREQUAL "Release") + add_compile_definitions(NDEBUG) +endif() + # Fetch and include GTest # Adapted from Google's documentation: https://google.github.io/googletest/quickstart-cmake.html#set-up-a-project include(FetchContent) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc index d2e68bfae95b7..fbe59f91dd3ea 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter.cc @@ -245,15 +245,18 @@ class ScalarToJson : public arrow::ScalarVisitor { const std::shared_ptr &data_type = std::static_pointer_cast(scalar.type); for (int i = 0; i < data_type->num_fields(); ++i) { - writer_.Key(data_type->field(i)->name().c_str()); - - const auto &result = scalar.field(i); + const auto& result = scalar.field(i); ThrowIfNotOK(result.status()); - ThrowIfNotOK(result.ValueOrDie()->Accept(this)); + const auto& value = result.ValueOrDie(); + writer_.Key(data_type->field(i)->name().c_str()); + if (value->is_valid) { + ThrowIfNotOK(value->Accept(this)); + } + else { + writer_.Null(); + } } - writer_.EndObject(); - return Status::OK(); } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc index 40b88e8649244..60c05be3e1114 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/json_converter_test.cc @@ -9,6 +9,7 @@ #include "gtest/gtest.h" #include "arrow/testing/builder.h" #include +#include namespace driver { namespace flight_sql { @@ -175,8 +176,11 @@ TEST(ConvertToJson, Struct) { auto i32 = MakeScalar(1); auto f64 = MakeScalar(2.5); auto str = MakeScalar("yo"); - ASSERT_OK_AND_ASSIGN(auto scalar, StructScalar::Make({i32, f64, str}, {"i", "f", "s"})); - ASSERT_EQ("{\"i\":1,\"f\":2.5,\"s\":\"yo\"}", ConvertToJson(*scalar)); + ASSERT_OK_AND_ASSIGN(auto scalar, + StructScalar::Make({i32, f64, str, + MakeNullScalar(std::shared_ptr(new arrow::Date32Type()))}, + {"i", "f", "s", "null"})); + ASSERT_EQ("{\"i\":1,\"f\":2.5,\"s\":\"yo\",\"null\":null}", ConvertToJson(*scalar)); } } // namespace flight_sql From 5899d5ebc08b0c70c05f3594901bb6925a86bdee Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 21 Jul 2022 06:25:48 -0700 Subject: [PATCH 175/183] Revert "Explicitly initialize and uninitialize grpc" This reverts commit 4e0415d30b0bbd1867dad39f2eaf25ad22b89fa2. Change-Id: I11a483a56d77a8b9454e4ea6be4726f9b1e12066 --- .../flightsql-odbc/flight_sql/flight_sql_driver.cc | 11 ++--------- .../flight_sql/include/flight_sql/flight_sql_driver.h | 1 - 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index cb59ccac78c55..8e731d3b4414f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -8,8 +8,6 @@ #include #include -#include - namespace driver { namespace flight_sql { @@ -18,13 +16,8 @@ using odbcabstraction::OdbcVersion; FlightSqlDriver::FlightSqlDriver() : diagnostics_("Apache Arrow", "Flight SQL", OdbcVersion::V_3), - version_("0.9.0.0") { - grpc_init(); -} - -FlightSqlDriver::~FlightSqlDriver() { - grpc_shutdown_blocking(); -} + version_("0.9.0.0") +{} std::shared_ptr FlightSqlDriver::CreateConnection(OdbcVersion odbc_version) { diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h index f63da27ab3f31..e55a7126c0359 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h @@ -19,7 +19,6 @@ class FlightSqlDriver : public odbcabstraction::Driver { public: FlightSqlDriver(); - ~FlightSqlDriver() override; std::shared_ptr CreateConnection(odbcabstraction::OdbcVersion odbc_version) override; From a90bb883ce7c3bf3c955a688da12b3921fc10535 Mon Sep 17 00:00:00 2001 From: James Duong Date: Tue, 19 Jul 2022 11:42:40 -0700 Subject: [PATCH 176/183] Avoid duplicate conversion of string cells when retrieving partials Avoid re-converting a string cell if it has already been partially using SQLGetData and getting the data back as SQL_C_WCHAR or SQL_C_CHAR. Change-Id: I53370dd9fc0ffb58969c6cc35b65b893204d12f4 --- .../accessors/string_array_accessor.cc | 31 ++++++++++++++----- .../accessors/string_array_accessor.h | 4 +++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc index bf64c0a97b6b7..a634848f9643b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -21,7 +21,7 @@ namespace { #if defined _WIN32 || defined _WIN64 std::string utf8_to_clocale(const char *utf8str, int len) { - boost::locale::generator g; + thread_local boost::locale::generator g; g.locale_cache_enabled(true); std::locale loc = g(boost::locale::util::get_system_locale()); return boost::locale::conv::from_utf(utf8str, utf8str + len, loc); @@ -30,6 +30,10 @@ std::string utf8_to_clocale(const char *utf8str, int len) template inline RowStatus MoveSingleCellToCharBuffer(std::vector &buffer, + int64_t& last_retrieved_arrow_row, +#if defined _WIN32 || defined _WIN64 + std::string &clocale_string, +#endif ColumnBinding *binding, StringArray *array, int64_t arrow_row, int64_t i, int64_t &value_offset, @@ -43,17 +47,20 @@ inline RowStatus MoveSingleCellToCharBuffer(std::vector &buffer, const void *value; size_t size_in_bytes; -#if defined _WIN32 || defined _WIN64 - std::string clocale_str; -#endif if (sizeof(CHAR_TYPE) > sizeof(char)) { - Utf8ToWcs(raw_value, raw_value_length, &buffer); + if (last_retrieved_arrow_row != arrow_row) { + Utf8ToWcs(raw_value, raw_value_length, &buffer); + last_retrieved_arrow_row = arrow_row; + } value = buffer.data(); size_in_bytes = buffer.size(); } else { #if defined _WIN32 || defined _WIN64 // Convert to C locale string - clocale_str = utf8_to_clocale(raw_value, raw_value_length); + if (last_retrieved_arrow_row != arrow_row) { + clocale_str = utf8_to_clocale(raw_value, raw_value_length); + last_retrieved_arrow_row = arrow_row; + } const char* clocale_data = clocale_str.data(); size_t clocale_length = clocale_str.size(); @@ -77,8 +84,10 @@ inline RowStatus MoveSingleCellToCharBuffer(std::vector &buffer, // Write a NUL terminator if (binding->buffer_length >= remaining_length + sizeof(CHAR_TYPE)) { + // The entire remainder of the data was consumed. char_buffer[remaining_length / sizeof(CHAR_TYPE)] = '\0'; if (update_value_offset) { + // Mark that there's no data remaining. value_offset = -1; } } else { @@ -108,13 +117,19 @@ template StringArrayFlightSqlAccessor::StringArrayFlightSqlAccessor( Array *array) : FlightSqlAccessor>(array) {} + StringArrayFlightSqlAccessor>(array), + last_arrow_row_(-1){} template RowStatus StringArrayFlightSqlAccessor::MoveSingleCell_impl( ColumnBinding *binding, int64_t arrow_row, int64_t i, int64_t &value_offset, bool update_value_offset, odbcabstraction::Diagnostics &diagnostics) { - return MoveSingleCellToCharBuffer(buffer_, binding, this->GetArray(), arrow_row, i, value_offset, update_value_offset, diagnostics); + return MoveSingleCellToCharBuffer(buffer_, last_arrow_row_, +#if defined _WIN32 || defined _WIN64 + clocale_str_, +#endif + binding, + this->GetArray(), arrow_row, i, value_offset, update_value_offset, diagnostics); } template diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h index a99a1bb0039c5..f46fa0aab100b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.h @@ -34,6 +34,10 @@ class StringArrayFlightSqlAccessor private: std::vector buffer_; +#if defined _WIN32 || defined _WIN64 + std::string clocale_str_; +#endif + int64_t last_arrow_row_; }; inline Accessor* CreateWCharStringArrayAccessor(arrow::Array *array) { From 848116d352cc55243f9a8d99502591661bc6cd8f Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 21 Jul 2022 09:17:10 -0700 Subject: [PATCH 177/183] Fix typo causing windows build issue Change-Id: I5f78d41d5301584dfc8c83ae43c3cc1e0b26862d --- .../flight_sql/accessors/string_array_accessor.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc index a634848f9643b..71e5a0ca5250e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/accessors/string_array_accessor.cc @@ -32,7 +32,7 @@ template inline RowStatus MoveSingleCellToCharBuffer(std::vector &buffer, int64_t& last_retrieved_arrow_row, #if defined _WIN32 || defined _WIN64 - std::string &clocale_string, + std::string &clocale_str, #endif ColumnBinding *binding, StringArray *array, int64_t arrow_row, int64_t i, From 591b83e2cd9338feedb145f823ec7e2b36ff00c2 Mon Sep 17 00:00:00 2001 From: James Duong Date: Sat, 23 Jul 2022 07:45:31 -0700 Subject: [PATCH 178/183] Fix crash with SQLGetInfo on string attributes Fix buffer overruns in encoding changes. This allows Full Connect in ODBCTest on Windows to work again. Also fix a performance bug where we called strlen() on a std::string. Change-Id: I0e60287958c1aebe49db0753ba930d7ccd0cb316 --- .../odbcabstraction/include/odbcabstraction/encoding.h | 2 +- .../include/odbcabstraction/odbc_impl/EncodingUtils.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h index 70375fb126852..6442382743e09 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/encoding.h @@ -92,7 +92,7 @@ inline void Utf8ToWcs(const char *utf8_string, std::vector *result) { template inline void WcsToUtf8(const void *wcs_string, size_t length_in_code_units, std::vector *result) { thread_local std::wstring_convert, CHAR_TYPE> converter; - auto byte_string = converter.to_bytes((CHAR_TYPE*) wcs_string, (CHAR_TYPE*) wcs_string + length_in_code_units * GetSqlWCharSize()); + auto byte_string = converter.to_bytes((CHAR_TYPE*) wcs_string, (CHAR_TYPE*) wcs_string + length_in_code_units); unsigned long length_in_bytes = byte_string.size(); const uint8_t *data = (uint8_t*) byte_string.data(); diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h index 0ec18f3f2f0fd..b2538f49ad9d4 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/odbc_impl/EncodingUtils.h @@ -26,7 +26,7 @@ namespace ODBC { template inline size_t ConvertToSqlWChar(const std::string& str, SQLWCHAR* buffer, SQLLEN bufferSizeInBytes) { thread_local std::vector wstr; - Utf8ToWcs(str.data(), &wstr); + Utf8ToWcs(str.data(), str.size(), &wstr); SQLLEN valueLengthInBytes = wstr.size(); if (buffer) { @@ -34,7 +34,7 @@ namespace ODBC { // Write a NUL terminator if (bufferSizeInBytes >= valueLengthInBytes + GetSqlWCharSize()) { - reinterpret_cast(buffer)[wstr.size()] = '\0'; + reinterpret_cast(buffer)[valueLengthInBytes / GetSqlWCharSize()] = '\0'; } else { SQLLEN numCharsWritten = bufferSizeInBytes / GetSqlWCharSize(); // If we failed to even write one char, the buffer is too small to hold a NUL-terminator. From 60dd060e7570d9435e17037a6e93f2609bbff264 Mon Sep 17 00:00:00 2001 From: Jose Almeida Date: Tue, 12 Jul 2022 17:11:57 -0300 Subject: [PATCH 179/183] Implement logger interface - Add an interface for logger - Define Macro for each log level in the interface - Add an implementation from the logger interface - Add the spdlog dependency to the CMakeLists.txt Change-Id: Ibf1426c86e6e28903619cba328bd6998d4c4f74d --- .../flightsql-odbc/CMakeLists.txt | 22 + .../flight_sql/flight_sql_driver.cc | 74 ++ .../include/flight_sql/flight_sql_driver.h | 2 + .../odbcabstraction/CMakeLists.txt | 9 + .../include/odbcabstraction/logger.h | 52 ++ .../include/odbcabstraction/spd_logger.h | 44 + .../include/odbcabstraction/spi/driver.h | 3 + .../include/odbcabstraction/utils.h | 7 + .../flightsql-odbc/odbcabstraction/logger.cc | 24 + .../odbcabstraction/spd_logger.cc | 146 ++++ .../flightsql-odbc/odbcabstraction/utils.cc | 49 ++ .../odbcabstraction/whereami.cc | 804 ++++++++++++++++++ .../flightsql-odbc/odbcabstraction/whereami.h | 67 ++ .../flightsql-odbc/vcpkg.json | 1 + 14 files changed, 1304 insertions(+) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/logger.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spd_logger.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/logger.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/spd_logger.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index cd7966fac61d7..aea59e469344a 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -25,6 +25,28 @@ if(CMAKE_BUILD_TYPE STREQUAL "Release") add_compile_definitions(NDEBUG) endif() +add_compile_definitions(FMT_HEADER_ONLY) + +include(ExternalProject) + +message("Using spdlog from https://github.com/gabime/spdlog on tag v1.10.0") +ExternalProject_Add( + dep_spdlog + GIT_REPOSITORY "https://github.com/gabime/spdlog" + GIT_TAG "v1.10.0" + GIT_SHALLOW 1 + UPDATE_COMMAND "" + PATCH_COMMAND "" + CMAKE_ARGS + -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/dep_spdlog-prefix/src/dep_spdlog-install + -DSPDLOG_BUILD_EXAMPLES=OFF + -DSPDLOG_BUILD_BENCH=OFF + -DSPDLOG_BUILD_TESTS=OFF + TEST_COMMAND "" +) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}/dep_spdlog-prefix/src/dep_spdlog/include) + # Fetch and include GTest # Adapted from Google's documentation: https://google.github.io/googletest/quickstart-cmake.html#set-up-a-project include(FetchContent) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index 8e731d3b4414f..5cabfe79454db 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -5,14 +5,41 @@ */ #include "flight_sql_connection.h" +#include "odbcabstraction/utils.h" +#include #include +#include #include + +#define DEFAULT_MAXIMUM_FILE_SIZE 16777216 + namespace driver { namespace flight_sql { using odbcabstraction::Connection; using odbcabstraction::OdbcVersion; +using odbcabstraction::LogLevel; +using odbcabstraction::SPDLogger; + +namespace { + LogLevel ToLogLevel(int64_t level) { + switch (level) { + case 0: + return LogLevel::TRACE; + case 1: + return LogLevel::DEBUG; + case 2: + return LogLevel::INFO; + case 3: + return LogLevel::WARN; + case 4: + return LogLevel::ERROR; + default: + return LogLevel::OFF; + } + } +} FlightSqlDriver::FlightSqlDriver() : diagnostics_("Apache Arrow", "Flight SQL", OdbcVersion::V_3), @@ -31,5 +58,52 @@ odbcabstraction::Diagnostics &FlightSqlDriver::GetDiagnostics() { void FlightSqlDriver::SetVersion(std::string version) { version_ = std::move(version); } + +void FlightSqlDriver::RegisterLog(const std::string &configFileName) { + odbcabstraction::PropertyMap propertyMap; + driver::odbcabstraction::ReadConfigFile(propertyMap, configFileName); + + auto log_enable_iterator = propertyMap.find(SPDLogger::LOG_ENABLED); + + auto log_enabled = log_enable_iterator != propertyMap.end() ? + odbcabstraction::AsBool(log_enable_iterator->second) : false; + + auto log_path_iterator = propertyMap.find(SPDLogger::LOG_PATH); + + auto log_path = + log_path_iterator != propertyMap.end() ? log_path_iterator->second : ""; + + if (*log_enabled && !log_path.empty()) { + auto log_level_iterator = propertyMap.find(SPDLogger::LOG_LEVEL); + + auto log_level = + log_level_iterator != propertyMap.end() ? std::stoi(log_level_iterator->second) : 1; + + auto maximum_file_size_iterator = propertyMap.find(SPDLogger::MAXIMUM_FILE_SIZE); + + auto maximum_file_size = maximum_file_size_iterator != propertyMap.end() ? + std::stoi(maximum_file_size_iterator->second) : DEFAULT_MAXIMUM_FILE_SIZE; + + auto maximum_file_quantity_iterator = propertyMap. + find(SPDLogger::FILE_QUANTITY); + + auto maximum_file_quantity = + maximum_file_quantity_iterator != propertyMap.end() ? std::stoi( + maximum_file_quantity_iterator->second) : 1; + + std::unique_ptr logger (new odbcabstraction::SPDLogger()); + + logger->init(maximum_file_quantity, maximum_file_size, + log_path, ToLogLevel(log_level)); + odbcabstraction::Logger::SetInstance(std::move(logger)); + } else { + std::unique_ptr logger (new odbcabstraction::SPDLogger()); + + logger->init(1, 1, + log_path, LogLevel::OFF); + odbcabstraction::Logger::SetInstance(std::move(logger)); + } +} + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h index e55a7126c0359..52078d5721623 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h @@ -26,6 +26,8 @@ class FlightSqlDriver : public odbcabstraction::Driver { odbcabstraction::Diagnostics &GetDiagnostics() override; void SetVersion(std::string version) override; + + void RegisterLog(const std::string &configFileName) override; }; }; // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index 0ffd493a201e7..85a250533cae9 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -12,7 +12,9 @@ add_library(odbcabstraction include/odbcabstraction/diagnostics.h include/odbcabstraction/error_codes.h include/odbcabstraction/exceptions.h + include/odbcabstraction/logger.h include/odbcabstraction/platform.h + include/odbcabstraction/spd_logger.h include/odbcabstraction/types.h include/odbcabstraction/utils.h include/odbcabstraction/odbc_impl/AttributeUtils.h @@ -32,7 +34,11 @@ add_library(odbcabstraction diagnostics.cc encoding.cc exceptions.cc + logger.cc + spd_logger.cc utils.cc + whereami.h + whereami.cc odbc_impl/ODBCConnection.cc odbc_impl/ODBCDescriptor.cc odbc_impl/ODBCEnvironment.cc @@ -45,4 +51,7 @@ set_target_properties(odbcabstraction LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib ) + +add_dependencies(odbcabstraction dep_spdlog) + target_link_libraries(odbcabstraction) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/logger.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/logger.h new file mode 100644 index 0000000000000..aac286334494d --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/logger.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#pragma once + +#include +#include +#include + +#include +#include + +#include + +#define LOG_DEBUG(...) driver::odbcabstraction::Logger::GetInstance()->log(driver::odbcabstraction::LogLevel::DEBUG, __VA_ARGS__); +#define LOG_INFO(...) driver::odbcabstraction::Logger::GetInstance()->log(driver::odbcabstraction::LogLevel::INFO, __VA_ARGS__); +#define LOG_ERROR(...) driver::odbcabstraction::Logger::GetInstance()->log(driver::odbcabstraction::LogLevel::ERROR, __VA_ARGS__); +#define LOG_TRACE(...) driver::odbcabstraction::Logger::GetInstance()->log(driver::odbcabstraction::LogLevel::TRACE, __VA_ARGS__); +#define LOG_WARN(...) driver::odbcabstraction::Logger::GetInstance()->log(driver::odbcabstraction::LogLevel::WARN, __VA_ARGS__); + +namespace driver { +namespace odbcabstraction { + +enum LogLevel { TRACE, DEBUG, INFO, WARN, ERROR, OFF }; + +class Logger { +protected: + Logger() = default; + +public: + static Logger *GetInstance(); + static void SetInstance(std::unique_ptr logger); + + virtual ~Logger() = default; + + virtual void log(LogLevel level, const std::string &message) = 0; + + virtual bool checkLogLevel(LogLevel called) = 0; + + template + void log(LogLevel level, fmt::format_string fmt, Args &&... args) { + if(checkLogLevel(level)) { + log(level, fmt::format(fmt, args...)); + } + }; +}; + +} // namespace odbcabstraction +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spd_logger.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spd_logger.h new file mode 100644 index 0000000000000..2d4a3e75b364a --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spd_logger.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#pragma once + +#include "odbcabstraction/logger.h" + +#include +#include + +#include + +namespace driver { +namespace odbcabstraction { + +class SPDLogger : public Logger { +protected: + std::shared_ptr logger_; + +public: + static const std::string LOG_LEVEL; + static const std::string LOG_PATH; + static const std::string MAXIMUM_FILE_SIZE; + static const std::string FILE_QUANTITY; + static const std::string LOG_ENABLED; + + SPDLogger() = default; + ~SPDLogger(); + SPDLogger(SPDLogger &other) = delete; + + void operator=(const SPDLogger &) = delete; + void init(int64_t fileQuantity, int64_t maxFileSize, + const std::string &fileNamePrefix, LogLevel level); + + void log(LogLevel level, const std::string &message) override; + + bool checkLogLevel(LogLevel called) override; +}; + +} // namespace odbcabstraction +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h index 974704f7fbf3f..b5968d302c255 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h @@ -35,6 +35,9 @@ class Driver { /// \brief Sets the driver version. virtual void SetVersion(std::string version) = 0; + + /// \brief Register a log to be used by the system. + virtual void RegisterLog(const std::string &configFileName) = 0; }; } // namespace odbcabstraction diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h index a5617adac5036..a3f19c963693b 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h @@ -7,11 +7,15 @@ #pragma once #include +#include #include namespace driver { namespace odbcabstraction { +typedef std::map + PropertyMap; + using driver::odbcabstraction::Connection; /// Parse a string value to a boolean. @@ -36,5 +40,8 @@ boost::optional AsBool(const Connection::ConnPropertyMap& connPropertyMap, /// \exception std::out_of_range exception from \link std::stoi \endlink boost::optional AsInt32(int32_t min_value, const Connection::ConnPropertyMap& connPropertyMap, const std::string& property_name); + + +void ReadConfigFile(PropertyMap &properties, const std::string &configFileName); } // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/logger.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/logger.cc new file mode 100644 index 0000000000000..16ac682df7aec --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/logger.cc @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + + +#include + +namespace driver { +namespace odbcabstraction { + +static std::unique_ptr odbc_logger_ = nullptr; + +Logger *Logger::GetInstance() { + return odbc_logger_.get(); +} + +void Logger::SetInstance(std::unique_ptrlogger) { + odbc_logger_ = std::move(logger); +} + +} +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/spd_logger.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/spd_logger.cc new file mode 100644 index 0000000000000..8fcf1ac0489b4 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/spd_logger.cc @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#include "odbcabstraction/spd_logger.h" + +#include "odbcabstraction/logger.h" + +#include +#include +#include + +#include +#include + +namespace driver { +namespace odbcabstraction { + +const std::string SPDLogger::LOG_LEVEL = "LogLevel"; +const std::string SPDLogger::LOG_PATH= "LogPath"; +const std::string SPDLogger::MAXIMUM_FILE_SIZE= "MaximumFileSize"; +const std::string SPDLogger::FILE_QUANTITY= "FileQuantity"; +const std::string SPDLogger::LOG_ENABLED= "LogEnabled"; + +namespace { +std::function shutdown_handler; +void signal_handler(int signal) { + shutdown_handler(signal); +} + +typedef void (*Handler)(int signum); + +Handler old_sigint_handler = SIG_IGN; +Handler old_sigsegv_handler = SIG_IGN; +Handler old_sigabrt_handler = SIG_IGN; +Handler old_sigkill_handler = SIG_IGN; + +Handler GetHandlerFromSignal(int signum) { + switch (signum) { + case(SIGINT): + return old_sigint_handler; + case(SIGSEGV): + return old_sigsegv_handler; + case(SIGABRT): + return old_sigabrt_handler; + case(SIGKILL): + return old_sigkill_handler; + } +} + +void SetSignalHandler(int signum) { + Handler old = signal(signum, SIG_IGN); + if (old != SIG_IGN) { + auto old_handler = GetHandlerFromSignal(signum); + old_handler = old; + } + signal(signum, signal_handler); +} + +void ResetSignalHandler(int signum) { + Handler actual_handler = signal(signum, SIG_IGN); + if (actual_handler == signal_handler) { + signal(signum, GetHandlerFromSignal(signum)); + } +} + + +spdlog::level::level_enum ToSpdLogLevel(LogLevel level) { + switch (level) { + case TRACE: + return spdlog::level::trace; + case DEBUG: + return spdlog::level::debug; + case INFO: + return spdlog::level::info; + case WARN: + return spdlog::level::warn; + case ERROR: + return spdlog::level::err; + default: + return spdlog::level::off; + } +} +} // namespace + +void SPDLogger::init(int64_t fileQuantity, int64_t maxFileSize, + const std::string &fileNamePrefix, LogLevel level) { + logger_ = spdlog::rotating_logger_mt( + "ODBC Logger", fileNamePrefix, maxFileSize, fileQuantity); + + logger_->set_level(ToSpdLogLevel(level)); + + if (level != LogLevel::OFF) { + SetSignalHandler(SIGINT); + SetSignalHandler(SIGSEGV); + SetSignalHandler(SIGABRT); + SetSignalHandler(SIGKILL); + shutdown_handler = [&](int signal) { + logger_->flush(); + spdlog::shutdown(); + auto handler = GetHandlerFromSignal(signal); + handler(signal); + }; + } +} + +void SPDLogger::log(LogLevel level, const std::string &message) { + switch (level) { + case DEBUG: + logger_->debug(message); + break; + case TRACE: + logger_->trace(message); + break; + case INFO: + logger_->info(message); + break; + case WARN: + logger_->warn(message); + break; + case ERROR: + logger_->error(message); + break; + } +} + +SPDLogger::~SPDLogger() { + ResetSignalHandler(SIGINT); + ResetSignalHandler(SIGSEGV); + ResetSignalHandler(SIGABRT); + ResetSignalHandler(SIGKILL); +} + +bool SPDLogger::checkLogLevel(LogLevel called) { + auto set = logger_->level(); + if (set == spdlog::level::off) { + return false; + } else { + return set <= ToSpdLogLevel(called); + } +} + +} // namespace odbcabstraction +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc index 8256cb230af40..831c63c2eeadd 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc @@ -5,8 +5,16 @@ */ #include +#include "whereami.h" + +#include +#include #include +#include +#include + +#define CONFIG_LOG_NAME "/arrow-odbc.ini" namespace driver { namespace odbcabstraction { @@ -45,5 +53,46 @@ boost::optional AsInt32(int32_t min_value, const Connection::ConnProper return boost::none; } +std::string GetModulePath() { + std::vector path; + int length, dirname_length; + length = wai_getModulePath(NULL, 0, &dirname_length); + + if (length != 0) { + path.resize(length); + wai_getModulePath(path.data(), length, &dirname_length); + } else { + throw DriverException("Could not find module path."); + } + + return std::string(path.begin(), path.begin() + dirname_length); +} + +void ReadConfigFile(PropertyMap &properties, const std::string &configFileName) { + auto config_path = GetModulePath(); + + std::ifstream myfile; + myfile.open(config_path + "/" + configFileName); + + if (myfile.fail()) { + throw DriverException("Could not read the driver config file."); + } + + std::string temp_config; + + boost::char_separator separator("="); + while(myfile.good()) { + myfile >> temp_config; + boost::tokenizer< boost::char_separator> tokenizer(temp_config, separator); + + auto iterator = tokenizer.begin(); + + std::string key = *iterator; + std::string value = *++iterator; + + properties[key] = std::move(value); + } +} + } // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.cc new file mode 100644 index 0000000000000..39324d16e2cb8 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.cc @@ -0,0 +1,804 @@ +// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses +// without any warranty. +// by Gregory Pakosz (@gpakosz) +// https://github.com/gpakosz/whereami + +// in case you want to #include "whereami.c" in a larger compilation unit +#if !defined(WHEREAMI_H) +#include "whereami.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__linux__) || defined(__CYGWIN__) +#undef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#elif defined(__APPLE__) +#undef _DARWIN_C_SOURCE +#define _DARWIN_C_SOURCE +#define _DARWIN_BETTER_REALPATH +#endif + +#if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC) +#include +#endif + +#if !defined(WAI_MALLOC) +#define WAI_MALLOC(size) malloc(size) +#endif + +#if !defined(WAI_FREE) +#define WAI_FREE(p) free(p) +#endif + +#if !defined(WAI_REALLOC) +#define WAI_REALLOC(p, size) realloc(p, size) +#endif + +#ifndef WAI_NOINLINE +#if defined(_MSC_VER) +#define WAI_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) +#define WAI_NOINLINE __attribute__((noinline)) +#else +#error unsupported compiler +#endif +#endif + +#if defined(_MSC_VER) +#define WAI_RETURN_ADDRESS() _ReturnAddress() +#elif defined(__GNUC__) +#define WAI_RETURN_ADDRESS() __builtin_extract_return_addr(__builtin_return_address(0)) +#else +#error unsupported compiler +#endif + +#if defined(_WIN32) + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#if defined(_MSC_VER) +#pragma warning(push, 3) +#endif +#include +#include +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +#include + +static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length) +{ + wchar_t buffer1[MAX_PATH]; + wchar_t buffer2[MAX_PATH]; + wchar_t* path = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + DWORD size; + int length_, length__; + + size = GetModuleFileNameW(module, buffer1, sizeof(buffer1) / sizeof(buffer1[0])); + + if (size == 0) + break; + else if (size == (DWORD)(sizeof(buffer1) / sizeof(buffer1[0]))) + { + DWORD size_ = size; + do + { + wchar_t* path_; + + path_ = (wchar_t*)WAI_REALLOC(path, sizeof(wchar_t) * size_ * 2); + if (!path_) + break; + size_ *= 2; + path = path_; + size = GetModuleFileNameW(module, path, size_); + } + while (size == size_); + + if (size == size_) + break; + } + else + path = buffer1; + + if (!_wfullpath(buffer2, path, MAX_PATH)) + break; + length_ = (int)wcslen(buffer2); + length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_ , out, capacity, NULL, NULL); + + if (length__ == 0) + length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_, NULL, 0, NULL, NULL); + if (length__ == 0) + break; + + if (length__ <= capacity && dirname_length) + { + int i; + + for (i = length__ - 1; i >= 0; --i) + { + if (out[i] == '\\') + { + *dirname_length = i; + break; + } + } + } + + length = length__; + } + + if (path != buffer1) + WAI_FREE(path); + + return ok ? length : -1; +} + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + return WAI_PREFIX(getModulePath_)(NULL, out, capacity, dirname_length); +} + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + HMODULE module; + int length = -1; + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable: 4054) +#endif + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)WAI_RETURN_ADDRESS(), &module)) +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + { + length = WAI_PREFIX(getModulePath_)(module, out, capacity, dirname_length); + } + + return length; +} + +#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) || defined(WAI_USE_PROC_SELF_EXE) + +#include +#include +#include +#if defined(__linux__) +#include +#else +#include +#endif +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#include +#include + +#if !defined(WAI_PROC_SELF_EXE) +#if defined(__sun) +#define WAI_PROC_SELF_EXE "/proc/self/path/a.out" +#else +#define WAI_PROC_SELF_EXE "/proc/self/exe" +#endif +#endif + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + resolved = realpath(WAI_PROC_SELF_EXE, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + return ok ? length : -1; +} + +#if !defined(WAI_PROC_SELF_MAPS_RETRY) +#define WAI_PROC_SELF_MAPS_RETRY 5 +#endif + +#if !defined(WAI_PROC_SELF_MAPS) +#if defined(__sun) +#define WAI_PROC_SELF_MAPS "/proc/self/map" +#else +#define WAI_PROC_SELF_MAPS "/proc/self/maps" +#endif +#endif + +#if defined(__ANDROID__) || defined(ANDROID) +#include +#include +#include +#endif +#include + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + int length = -1; + FILE* maps = NULL; + + for (int r = 0; r < WAI_PROC_SELF_MAPS_RETRY; ++r) + { + maps = fopen(WAI_PROC_SELF_MAPS, "r"); + if (!maps) + break; + + for (;;) + { + char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX]; + uint64_t low, high; + char perms[5]; + uint64_t offset; + uint32_t major, minor; + char path[PATH_MAX]; + uint32_t inode; + + if (!fgets(buffer, sizeof(buffer), maps)) + break; + + if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8) + { + uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS(); + if (low <= addr && addr <= high) + { + char* resolved; + + resolved = realpath(path, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); +#if defined(__ANDROID__) || defined(ANDROID) + if (length > 4 + &&buffer[length - 1] == 'k' + &&buffer[length - 2] == 'p' + &&buffer[length - 3] == 'a' + &&buffer[length - 4] == '.') + { + int fd = open(path, O_RDONLY); + if (fd == -1) + { + length = -1; // retry + break; + } + + char* begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0); + if (begin == MAP_FAILED) + { + close(fd); + length = -1; // retry + break; + } + + char* p = begin + offset - 30; // minimum size of local file header + while (p >= begin) // scan backwards + { + if (*((uint32_t*)p) == 0x04034b50UL) // local file header signature found + { + uint16_t length_ = *((uint16_t*)(p + 26)); + + if (length + 2 + length_ < (int)sizeof(buffer)) + { + memcpy(&buffer[length], "!/", 2); + memcpy(&buffer[length + 2], p + 30, length_); + length += 2 + length_; + } + + break; + } + + --p; + } + + munmap(begin, offset); + close(fd); + } +#endif + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + + break; + } + } + } + + fclose(maps); + maps = NULL; + + if (length != -1) + break; + } + + return length; +} + +#elif defined(__APPLE__) + +#include +#include +#include +#include +#include +#include + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* path = buffer1; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + uint32_t size = (uint32_t)sizeof(buffer1); + if (_NSGetExecutablePath(path, &size) == -1) + { + path = (char*)WAI_MALLOC(size); + if (!_NSGetExecutablePath(path, &size)) + break; + } + + resolved = realpath(path, buffer2); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + if (path != buffer1) + WAI_FREE(path); + + return ok ? length : -1; +} + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + break; + } + + return length; +} + +#elif defined(__QNXNTO__) + +#include +#include +#include +#include +#include +#include + +#if !defined(WAI_PROC_SELF_EXE) +#define WAI_PROC_SELF_EXE "/proc/self/exefile" +#endif + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* resolved = NULL; + FILE* self_exe = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + self_exe = fopen(WAI_PROC_SELF_EXE, "r"); + if (!self_exe) + break; + + if (!fgets(buffer1, sizeof(buffer1), self_exe)) + break; + + resolved = realpath(buffer1, buffer2); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + fclose(self_exe); + + return ok ? length : -1; +} + +WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + break; + } + + return length; +} + +#elif defined(__DragonFly__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) + +#include +#include +#include +#include +#include +#include +#include + +#if defined(__OpenBSD__) + +#include + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[4096]; + char buffer2[PATH_MAX]; + char buffer3[PATH_MAX]; + char** argv = (char**)buffer1; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; + size_t size; + + if (sysctl(mib, 4, NULL, &size, NULL, 0) != 0) + break; + + if (size > sizeof(buffer1)) + { + argv = (char**)WAI_MALLOC(size); + if (!argv) + break; + } + + if (sysctl(mib, 4, argv, &size, NULL, 0) != 0) + break; + + if (strchr(argv[0], '/')) + { + resolved = realpath(argv[0], buffer2); + if (!resolved) + break; + } + else + { + const char* PATH = getenv("PATH"); + if (!PATH) + break; + + size_t argv0_length = strlen(argv[0]); + + const char* begin = PATH; + while (1) + { + const char* separator = strchr(begin, ':'); + const char* end = separator ? separator : begin + strlen(begin); + + if (end - begin > 0) + { + if (*(end -1) == '/') + --end; + + if (((end - begin) + 1 + argv0_length + 1) <= sizeof(buffer2)) + { + memcpy(buffer2, begin, end - begin); + buffer2[end - begin] = '/'; + memcpy(buffer2 + (end - begin) + 1, argv[0], argv0_length + 1); + + resolved = realpath(buffer2, buffer3); + if (resolved) + break; + } + } + + if (!separator) + break; + + begin = ++separator; + } + + if (!resolved) + break; + } + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + if (argv != (char**)buffer1) + WAI_FREE(argv); + + return ok ? length : -1; +} + +#else + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* path = buffer1; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { +#if defined(__NetBSD__) + int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; +#else + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; +#endif + size_t size = sizeof(buffer1); + + if (sysctl(mib, 4, path, &size, NULL, 0) != 0) + break; + + resolved = realpath(path, buffer2); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + return ok ? length : -1; +} + +#endif + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + break; + } + + return length; +} + +#else + +#error unsupported platform + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.h new file mode 100644 index 0000000000000..ca62d674cd2d1 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.h @@ -0,0 +1,67 @@ +// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses +// without any warranty. +// by Gregory Pakosz (@gpakosz) +// https://github.com/gpakosz/whereami + +#ifndef WHEREAMI_H +#define WHEREAMI_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef WAI_FUNCSPEC +#define WAI_FUNCSPEC +#endif +#ifndef WAI_PREFIX +#define WAI_PREFIX(function) wai_##function +#endif + +/** + * Returns the path to the current executable. + * + * Usage: + * - first call `int length = wai_getExecutablePath(NULL, 0, NULL);` to + * retrieve the length of the path + * - allocate the destination buffer with `path = (char*)malloc(length + 1);` + * - call `wai_getExecutablePath(path, length, NULL)` again to retrieve the + * path + * - add a terminal NUL character with `path[length] = '\0';` + * + * @param out destination buffer, optional + * @param capacity destination buffer capacity + * @param dirname_length optional recipient for the length of the dirname part + * of the path. + * + * @return the length of the executable path on success (without a terminal NUL + * character), otherwise `-1` + */ +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length); + +/** + * Returns the path to the current module + * + * Usage: + * - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve + * the length of the path + * - allocate the destination buffer with `path = (char*)malloc(length + 1);` + * - call `wai_getModulePath(path, length, NULL)` again to retrieve the path + * - add a terminal NUL character with `path[length] = '\0';` + * + * @param out destination buffer, optional + * @param capacity destination buffer capacity + * @param dirname_length optional recipient for the length of the dirname part + * of the path. + * + * @return the length of the module path on success (without a terminal NUL + * character), otherwise `-1` + */ +WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length); + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef WHEREAMI_H diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json index 88edaa56773f3..519d6441bec61 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json @@ -20,6 +20,7 @@ "protobuf", "zlib", "re2", + "spdlog", "grpc", "utf8proc", "zlib", From 293addd5a77ceab52c679376abec846f4ecbcfe2 Mon Sep 17 00:00:00 2001 From: Vinicius Fraga Date: Thu, 7 Jul 2022 15:09:17 -0300 Subject: [PATCH 180/183] Profiling Framework for ODBC Change-Id: I594ba8b77ff6e69c13bd597efd2a020db3cf5670 --- .../odbc_perf_testing/.gitignore | 160 ++++++++++++++++++ .../odbc_perf_testing/README.md | 73 ++++++++ .../odbc_perf_testing/environment.yml | 8 + .../flightsql-odbc/odbc_perf_testing/main.py | 125 ++++++++++++++ .../odbc_perf_testing/requirements.txt | 2 + .../odbc_perf_testing/test_cases/__init__.py | 4 + .../test_cases/test_data_types.py | 42 +++++ .../test_cases/test_fetch_all.py | 16 ++ .../test_strategy/__init__.py | 4 + .../test_strategy/base_strategy.py | 70 ++++++++ .../test_strategy/execution_details.py | 47 +++++ .../test_strategy/pyodbc_strategy.py | 73 ++++++++ .../test_strategy/turbodbc_strategy.py | 78 +++++++++ 13 files changed, 702 insertions(+) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/.gitignore create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/README.md create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/environment.yml create mode 100755 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/main.py create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/requirements.txt create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_cases/__init__.py create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_cases/test_data_types.py create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_cases/test_fetch_all.py create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/__init__.py create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/base_strategy.py create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/execution_details.py create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/pyodbc_strategy.py create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/turbodbc_strategy.py diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/.gitignore b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/.gitignore new file mode 100644 index 0000000000000..6769e21d99a63 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/.gitignore @@ -0,0 +1,160 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/README.md b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/README.md new file mode 100644 index 0000000000000..ee26887aea768 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/README.md @@ -0,0 +1,73 @@ +# ODBC Perf Testing Tool + +--- + +## Examples: + +### test_case=test-fetch-all + +``` +./main.py --sql_query="SELECT * FROM table_name" py --driver /home/user/odbc_driver/_build/release/libarrow-odbc.so --host localhost --port 32010 --user username --password password123 pyodbc test-fetch-all +``` + +### test_case=test-sql-type-** + +``` +./main.py --driver /home/user/odbc_driver/_build/release/libarrow-odbc.so --host localhost --port 32010 --user username --password password123 pyodbc test-sql-type-all +``` + +#### Available data types: boolean, float, double, decimal, int, bigint, date, time, timestamp, intervalday (day to seconds), intervalyear (year to month), varchar, struct, list, all + +--- + +### Script usage help: + +``` +usage: main.py [-h] [--user_connection_string USER_CONNECTION_STRING] [--driver DRIVER] [--dsn DSN] [--host HOST] [--port PORT] [--user USER] + [--password PASSWORD] [--token TOKEN] [--use_encryption USE_ENCRYPTION] [--trusted_certs TRUSTED_CERTS] + [--use_system_trust_store USE_SYSTEM_TRUST_STORE] [--disable_certificate_verification DISABLE_CERTIFICATE_VERIFICATION] + [--sql_query SQL_QUERY] [--library_options LIBRARY_OPTIONS] + odbc_library test_case + +Create test scenarios for profiling in other tools. + +positional arguments: + odbc_library Which ODBC Library to use ['pyodbc', 'turbodbc'] + test_case Which test case to run ['test-fetch-all', 'test-sql-type-{type_name}'] + +optional arguments: + -h, --help show this help message and exit + --user_connection_string USER_CONNECTION_STRING The ODBC Driver Path + --driver DRIVER The ODBC Driver Path + --dsn DSN The ODBC Driver Data Source Name + --host HOST The host to connect + --port PORT The port to connect + --user USER The user to authenticate + --password PASSWORD The password to authenticate + --token TOKEN Defines the token for Token Authentication + --use_encryption USE_ENCRYPTION Use SSL Connections + --trusted_certs TRUSTED_CERTS Defines the certificates path + --use_system_trust_store USE_SYSTEM_TRUST_STORE Tells whether the driver should use the system's Trust Store + --disable_certificate_verification DISABLE_CERTIFICATE_VERIFICATION Tells the driver to ignore certificate verification. + --sql_query SQL_QUERY The SQL Query to run (only affects "test-fetch-all") + --library_options LIBRARY_OPTIONS Extra library-specific connection options in JSON format '{k: v}' + +``` + +#### You can connect with either a connection string `--user_connection_string`, your DSN `--dsn`, or provide it via arguments. + +##### Note you can't override your DSN configuration using the optional arguments. + +--- + +#### Example for `--library_options`: + +``` +--library_options "{\"library_specific_option_1\": true, \"library_specific_option_2\": 100000}" +``` + +##### Those options will be passed as kwargs to the `connect` method of each library, make sure they're written correctly. + +##### _NOTE: It might also override connection string parameters dependending on the library's implementation._ + +--- diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/environment.yml b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/environment.yml new file mode 100644 index 0000000000000..621f00f741534 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/environment.yml @@ -0,0 +1,8 @@ +name: odbc_perf_testing +channels: + - conda-forge + - defaults +dependencies: + - python=3.9.* + - pyodbc=4.0.* + - turbodbc=4.5.* diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/main.py b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/main.py new file mode 100755 index 0000000000000..eabe4985e3428 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/main.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020-2022 Dremio Corporation +# +# See "LICENSE" for license information. + +import argparse +import json +from typing import Dict, List + +from test_cases import test_fetch_all, test_data_types +from test_strategy.base_strategy import BaseStrategy +from test_strategy.execution_details import ExecutionDetails, ConnectionDetails, TestDetails +from test_strategy.pyodbc_strategy import PyOdbcStrategy +from test_strategy.turbodbc_strategy import TurbodbcStrategy + +VALID_TEST_CASES: List[str] = ['test-fetch-all', 'test-sql-type-{typename}'] +VALID_ODBC_LIBRARIES: List[str] = ['pyodbc', 'turbodbc'] + + +def start_new_test_process( + test_case_name: str, + strategy: BaseStrategy) -> None: + test_case_all_lower: str = test_case_name.lower() + if 'test-fetch-all' in test_case_all_lower: + test_fetch_all.run( + test_name=test_case_all_lower, + strategy=strategy + ) + elif 'test-sql-type-' in test_case_all_lower: + type_name: str = test_case_all_lower.split('-')[-1] # Get type name in the end of the test case name + test_data_types.run( + type_name=type_name, + test_name=test_case_all_lower, + strategy=strategy) + else: + raise_for_invalid_value('test_case', VALID_TEST_CASES) + + +def raise_for_invalid_value(key_for_wrong_value: str, valid_options: List[str]) -> ValueError: + raise ValueError(f'Received an invalid value for "{key_for_wrong_value}". Valid options are: {valid_options}') + + +def parse_bool(input_string: str) -> bool: + return input_string and input_string.lower().strip() in ('true', '1') + + +def run(execution_details: ExecutionDetails) -> None: + test_details: TestDetails = execution_details.test_details + + odbc_library_lower = test_details.odbc_library.strip().lower() + if odbc_library_lower == 'pyodbc': + start_new_test_process( + test_case_name=f'{odbc_library_lower}-{test_details.test_case}', + strategy=PyOdbcStrategy(execution_details=execution_details) + ) + elif odbc_library_lower == 'turbodbc': + start_new_test_process( + test_case_name=f'{odbc_library_lower}-{test_details.test_case}', + strategy=TurbodbcStrategy(execution_details=execution_details) + ) + else: + raise_for_invalid_value('odbc-library', VALID_ODBC_LIBRARIES) + + +if __name__ == '__main__': + parser: argparse.ArgumentParser = argparse.ArgumentParser( + description='Create test scenarios for profiling in other tools.' + ) + + # required + parser.add_argument('odbc_library', help=f'Which ODBC Library to use {VALID_ODBC_LIBRARIES}') + parser.add_argument('test_case', help=f'Which test case to run {VALID_TEST_CASES}') + + # optional + parser.add_argument('--user_connection_string', default='', help='The ODBC Driver Path') + parser.add_argument('--driver', default='', help='The ODBC Driver Path') + parser.add_argument('--dsn', default='', help='The ODBC Driver Data Source Name') + parser.add_argument('--host', default='', help='The host to connect') + parser.add_argument('--port', default='', help='The port to connect') + parser.add_argument('--user', default='', help='The user to authenticate') + parser.add_argument('--password', default='', help='The password to authenticate') + parser.add_argument('--token', default='', help='Defines the token for Token Authentication') + parser.add_argument('--use_encryption', default='false', help='Use SSL Connections') + parser.add_argument('--trusted_certs', default='', help='Defines the certificates path') + parser.add_argument( + '--use_system_trust_store', + default='true', + help='Tells whether the driver should use the system\'s Trust Store') + parser.add_argument( + '--disable_certificate_verification', + default='false', + help='Tells the driver to ignore certificate verification.') + parser.add_argument('--sql_query', default='', help='The SQL Query to run (only affects "test-fetch-all")') + parser.add_argument( + '--library_options', default='{}', help='Extra library-specific connection options in JSON format "{K: v}"') + + args: Dict[str, str] = vars(parser.parse_args()) + + connection_detail: ConnectionDetails = ConnectionDetails( + dsn=args['dsn'], + host=args['host'], + user=args['user'], + token=args['token'], + driver=args['driver'], + port=int(args['port']), + password=args['password'], + trusted_certs=args['trusted_certs'], + use_encryption=parse_bool(args['use_encryption']), + library_options=json.loads(args['library_options']), + user_connection_string=args['user_connection_string'], + use_system_trust_store=parse_bool(args['use_system_trust_store']), + disable_certificate_verification=parse_bool(args['disable_certificate_verification']), + ) + test_detail: TestDetails = TestDetails( + odbc_library=args['odbc_library'], + sql_query=args['sql_query'], + test_case=args['test_case'] + ) + execution_detail: ExecutionDetails = ExecutionDetails( + connection_details=connection_detail, + test_details=test_detail + ) + + run(execution_details=execution_detail) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/requirements.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/requirements.txt new file mode 100644 index 0000000000000..0e95807986a15 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/requirements.txt @@ -0,0 +1,2 @@ +pyodbc~=4.0.32 +turbodbc~=4.5.3 \ No newline at end of file diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_cases/__init__.py b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_cases/__init__.py new file mode 100644 index 0000000000000..216620a11025e --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_cases/__init__.py @@ -0,0 +1,4 @@ +# +# Copyright (C) 2020-2022 Dremio Corporation +# +# See "LICENSE" for license information. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_cases/test_data_types.py b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_cases/test_data_types.py new file mode 100644 index 0000000000000..9ba7ad1e9a202 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_cases/test_data_types.py @@ -0,0 +1,42 @@ +# +# Copyright (C) 2020-2022 Dremio Corporation +# +# See "LICENSE" for license information. + +from typing import Dict + +from test_cases import test_fetch_all +from test_strategy.base_strategy import BaseStrategy + +SCHEMA: str = 'nas' +TABLE: str = '"data_1000000_rows.parquet"' + +DATA_TYPE_QUERIES: Dict[str, str] = { + 'BOOLEAN': f'SELECT booleancol FROM {SCHEMA}.{TABLE}', + 'FLOAT': f'SELECT floatcol FROM {SCHEMA}.{TABLE}', + 'DOUBLE': f'SELECT doublecol FROM {SCHEMA}.{TABLE}', + 'DECIMAL': f'SELECT decimalcol FROM {SCHEMA}.{TABLE}', + 'INT': f'SELECT intcol FROM {SCHEMA}.{TABLE}', + 'BIGINT': f'SELECT bigintcol FROM {SCHEMA}.{TABLE}', + 'DATE': f'SELECT datecol FROM {SCHEMA}.{TABLE}', + 'TIME': f'SELECT timecol FROM {SCHEMA}.{TABLE}', + 'TIMESTAMP': f'SELECT timestampcol FROM {SCHEMA}.{TABLE}', + 'INTERVALDAY': f'SELECT interval_day_to_secondscol FROM {SCHEMA}.{TABLE}', + 'INTERVALYEAR': f'SELECT interval_year_to_monthscol FROM {SCHEMA}.{TABLE}', + 'VARCHAR': f'SELECT varcharcol FROM {SCHEMA}.{TABLE}', + 'STRUCT': f'SELECT structcol FROM {SCHEMA}.{TABLE}', + 'LIST': f'SELECT listcol FROM {SCHEMA}.{TABLE}', + 'ALL': f'SELECT * FROM {SCHEMA}.{TABLE}', +} + + +def run(type_name: str, test_name: str, strategy: BaseStrategy) -> None: + type_name_upper: str = type_name.strip().upper() + if type_name_upper in DATA_TYPE_QUERIES: + strategy.set_sql_query(DATA_TYPE_QUERIES.get(type_name_upper)) + test_fetch_all.run(test_name=test_name, strategy=strategy) + else: + raise AttributeError( + f'Please select a valid data type for this test. ' + f'Expected one of: {DATA_TYPE_QUERIES.keys()} ' + f'But instead got: {type_name}') diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_cases/test_fetch_all.py b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_cases/test_fetch_all.py new file mode 100644 index 0000000000000..f3b8077757c4b --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_cases/test_fetch_all.py @@ -0,0 +1,16 @@ +# +# Copyright (C) 2020-2022 Dremio Corporation +# +# See "LICENSE" for license information. + +from time import perf_counter + +from test_strategy.base_strategy import BaseStrategy + + +def run(test_name: str, strategy: BaseStrategy) -> None: + print(f'{test_name} starting...') + start: float = perf_counter() + strategy.fetch_all() + end: float = perf_counter() + print(f'{test_name} finished in {end - start:.2f}s.') diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/__init__.py b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/__init__.py new file mode 100644 index 0000000000000..216620a11025e --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/__init__.py @@ -0,0 +1,4 @@ +# +# Copyright (C) 2020-2022 Dremio Corporation +# +# See "LICENSE" for license information. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/base_strategy.py b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/base_strategy.py new file mode 100644 index 0000000000000..ce4ae2990ae03 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/base_strategy.py @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020-2022 Dremio Corporation +# +# See "LICENSE" for license information. + +from abc import ABC, abstractmethod # NOTE: ABC is Python >= 3.4 +from enum import Enum +from typing import Any, Iterable, List + +from test_strategy.execution_details import ExecutionDetails, ConnectionDetails + + +class BaseStrategy(ABC): + """ + Interface for testing with different libraries. + """ + + @property + @abstractmethod + def execution_details(self) -> ExecutionDetails: + """ + Defines an abstract property getter that can be used as `x.execution_details`. + """ + pass + + @execution_details.setter + @abstractmethod + def execution_details(self, value: ExecutionDetails) -> None: + """ + Defines an abstract property setter that can be used as `x.execution_details = val`. + """ + pass + + @abstractmethod + def fetch_all(self) -> Iterable[Any]: + """ + Defines an abstract method that should interface with DBAPI's 'fetch_all' of the respective library. + """ + pass + + @abstractmethod + def set_sql_query(self, value: str) -> None: + """ + Defines an abstract method that should change the TestDetail's SQL Query to a given value. + """ + pass + + class ConnectionType(Enum): + USER_DEFINED_STRING = 1 + DSN_DEFINED_PROPERTIES = 2 + PARAMETER_DEFINED_PROPERTIES = 3 + _REQUIRED_PARAMETERS: List[str] = ['driver', 'host', 'port', 'user', 'password'] + + @staticmethod + def get_connection_type(conn_details: ConnectionDetails): + static_self = BaseStrategy.ConnectionType + if conn_details.user_connection_string: + return static_self.USER_DEFINED_STRING + elif conn_details.dsn: + return static_self.DSN_DEFINED_PROPERTIES + elif all(val for key, val in conn_details.__dict__.items() if key in static_self._REQUIRED_PARAMETERS): + # Proceed if all required parameters have truthy values + return static_self.PARAMETER_DEFINED_PROPERTIES + else: + # All parameters are optional, so they'll all have '--' + raise ValueError( + f'To run this tool you must specify either ' + f'--user_connection_string, ' + f'--dsn, ' + f'or at least {["--" + val for val in static_self._REQUIRED_PARAMETERS]}') diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/execution_details.py b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/execution_details.py new file mode 100644 index 0000000000000..36e6813701906 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/execution_details.py @@ -0,0 +1,47 @@ +# +# Copyright (C) 2020-2022 Dremio Corporation +# +# See "LICENSE" for license information. + +from dataclasses import dataclass +from typing import Any, Dict + + +@dataclass +class ConnectionDetails: + """ + Class for storing connection information like host, port, user, password. + """ + dsn: str + host: str + port: int + user: str + driver: str + password: str + use_encryption: bool + token: str = lambda: '' + trusted_certs: str = lambda: '' + connected: bool = lambda: False + user_connection_string: str = lambda: '' + use_system_trust_store: bool = lambda: True + library_options: Dict[str, Any] = lambda: dict() + disable_certificate_verification: bool = lambda: False + + +@dataclass +class TestDetails: + """ + Class for storing test information like which ODBC library to use, and the SQL query that should run. + """ + odbc_library: str + sql_query: str + test_case: str + + +@dataclass +class ExecutionDetails: + """ + Class for storing the connection and test details. + """ + connection_details: ConnectionDetails + test_details: TestDetails diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/pyodbc_strategy.py b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/pyodbc_strategy.py new file mode 100644 index 0000000000000..1cdd1eec7ba91 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/pyodbc_strategy.py @@ -0,0 +1,73 @@ +# +# Copyright (C) 2020-2022 Dremio Corporation +# +# See "LICENSE" for license information. + +from typing import List + +from pyodbc import Row, Cursor, Connection, connect + +from test_strategy.base_strategy import BaseStrategy +from test_strategy.execution_details import ExecutionDetails, ConnectionDetails, TestDetails + + +class PyOdbcStrategy(BaseStrategy): + """ + Implements a BaseStrategy for PyODBC. + """ + + def __init__(self, execution_details: ExecutionDetails) -> None: + super().__init__() + self._execution_details: ExecutionDetails = execution_details + self._connection: Connection = self._connect_with_execution_details(execution_details) + execution_details.connection_details.connected = True + + @property + def execution_details(self) -> ExecutionDetails: + return self._execution_details + + @execution_details.setter + def execution_details(self, value: ExecutionDetails) -> None: + self._execution_details = value + + def fetch_all(self) -> List[Row]: + cursor: Cursor = self._get_cursor() + test_details: TestDetails = self.execution_details.test_details + sql_query: str = test_details.sql_query + + cursor.execute(sql_query) + return cursor.fetchall() + + def set_sql_query(self, value: str) -> None: + test_details: TestDetails = self.execution_details.test_details + test_details.sql_query = value + + def _get_cursor(self) -> Cursor: + return self._connection.cursor() + + @staticmethod + def _connect_with_execution_details(execution_details: ExecutionDetails) -> Connection: + conn_details: ConnectionDetails = execution_details.connection_details + connection_type = BaseStrategy.ConnectionType.get_connection_type(conn_details=conn_details) + + if connection_type == BaseStrategy.ConnectionType.USER_DEFINED_STRING: + return connect(connection_string=conn_details.user_connection_string, **conn_details.library_options) + elif connection_type == BaseStrategy.ConnectionType.DSN_DEFINED_PROPERTIES: + return connect( + f'DSN={conn_details.dsn}', + autocommit=True, # transactions not supported in Flight SQL ODBC + **conn_details.library_options + ) + elif BaseStrategy.ConnectionType.USER_DEFINED_STRING: + return connect( + f'Driver={conn_details.driver};' + + f'HOST={conn_details.host};PORT={conn_details.port};' + + f'UID={conn_details.user};PWD={conn_details.password};' + + f'useEncryption={int(conn_details.use_encryption)};' + + (f'token={conn_details.token};' if conn_details.token else '') + + (f'trustedCerts={conn_details.trusted_certs};' if conn_details.trusted_certs else '') + + f'useSystemTrustStore={int(conn_details.use_system_trust_store)};' + + f'disableCertificateVerification={int(conn_details.disable_certificate_verification)}', + autocommit=True, # transactions not supported in Flight SQL ODBC + **conn_details.library_options + ) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/turbodbc_strategy.py b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/turbodbc_strategy.py new file mode 100644 index 0000000000000..a63beb07c13a0 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbc_perf_testing/test_strategy/turbodbc_strategy.py @@ -0,0 +1,78 @@ +# +# Copyright (C) 2020-2022 Dremio Corporation +# +# See "LICENSE" for license information. + +from typing import Any, List, Dict + +from turbodbc import Rows, connect, make_options +from turbodbc.connect import Connection +from turbodbc.cursor import Cursor +from turbodbc_intern import Options + +from test_strategy.base_strategy import BaseStrategy +from test_strategy.execution_details import ExecutionDetails, ConnectionDetails, TestDetails + + +class TurbodbcStrategy(BaseStrategy): + """ + Implements a BaseStrategy for Turbodbc. + """ + + def __init__(self, execution_details: ExecutionDetails) -> None: + super().__init__() + self._execution_details: ExecutionDetails = execution_details + self._connection: Connection = self._connect_with_execution_details(execution_details) + execution_details.connection_details.connected = True + + @property + def execution_details(self) -> ExecutionDetails: + return self._execution_details + + @execution_details.setter + def execution_details(self, value: ExecutionDetails) -> None: + self._execution_details = value + + def fetch_all(self) -> List[Rows]: + cursor: Cursor = self._get_cursor() + test_details: TestDetails = self.execution_details.test_details + sql_query: str = test_details.sql_query + + cursor.execute(sql_query) + return cursor.fetchall() + + def set_sql_query(self, value: str) -> None: + test_details: TestDetails = self.execution_details.test_details + test_details.sql_query = value + + def _get_cursor(self) -> Cursor: + return self._connection.cursor() + + @staticmethod + def _connect_with_execution_details(execution_details: ExecutionDetails) -> Connection: + connection_details: ConnectionDetails = execution_details.connection_details + extra_opts: Dict[str, Any] = { + 'autocommit': True, # transactions not supported in Flight SQL ODBC + **connection_details.library_options + } + options: Options = make_options(**extra_opts) + connection_type = BaseStrategy.ConnectionType.get_connection_type(conn_details=connection_details) + + if connection_type == BaseStrategy.ConnectionType.USER_DEFINED_STRING: + return connect(connection_string=connection_details.user_connection_string, turbodbc_options=options) + elif connection_type == BaseStrategy.ConnectionType.DSN_DEFINED_PROPERTIES: + return connect(dsn=connection_details.dsn, turbodbc_options=options) + elif connection_type == BaseStrategy.ConnectionType.PARAMETER_DEFINED_PROPERTIES: + return connect( + driver=connection_details.driver, + host=connection_details.host, + port=connection_details.port, + uid=connection_details.user, + pwd=connection_details.password, + useEncryption=int(connection_details.use_encryption), + token=connection_details.token, + trustedCerts=connection_details.trusted_certs, + useSystemTrustStore=int(connection_details.use_system_trust_store), + disableCertificateVerification=int(connection_details.disable_certificate_verification), + turbodbc_options=options + ) From 0d34c77eee015261a69f78e19d9e4bbce40c158a Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Wed, 20 Jul 2022 17:09:38 -0300 Subject: [PATCH 181/183] Implement double-buffering This implements buffering of FlightStreamChunks, allowing the driver to better leverage IO, as results are buffered as they arrive and can be consumed afterwards when the client requests them. This adds a new connection property "ChunkBufferCapacity" to set the buffer capacity with a default value of 5. Change-Id: I73454fc942f4b5fe8390ec4e582ea18b04eba9b4 --- .../flightsql-odbc/flight_sql/CMakeLists.txt | 4 +- .../flight_sql/flight_sql_connection.cc | 18 ++- .../flight_sql/flight_sql_connection.h | 3 + .../flight_sql/flight_sql_result_set.cc | 10 +- .../flight_sql/flight_sql_result_set.h | 4 +- .../flight_sql_stream_chunk_buffer.cc | 63 +++++++++ .../flight_sql_stream_chunk_buffer.h | 42 ++++++ .../flight_sql_stream_chunk_iterator.cc | 62 --------- .../flight_sql_stream_chunk_iterator.h | 40 ------ .../flight_sql/get_info_cache.cc | 4 +- .../flightsql-odbc/flight_sql/main.cc | 15 +-- .../include/odbcabstraction/blocking_queue.h | 123 ++++++++++++++++++ .../include/odbcabstraction/types.h | 5 +- 13 files changed, 267 insertions(+), 126 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_buffer.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_buffer.h delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/blocking_queue.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt index 3019f62332bc3..44887430398ad 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/CMakeLists.txt @@ -186,8 +186,8 @@ set(ARROW_ODBC_SPI_SOURCES flight_sql_statement_get_tables.h flight_sql_statement_get_type_info.cc flight_sql_statement_get_type_info.h - flight_sql_stream_chunk_iterator.cc - flight_sql_stream_chunk_iterator.h + flight_sql_stream_chunk_buffer.cc + flight_sql_stream_chunk_buffer.h get_info_cache.cc get_info_cache.h json_converter.cc diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index caa2aa3c95127..cfae4b34db501 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -67,13 +67,14 @@ const std::string FlightSqlConnection::TRUSTED_CERTS = "trustedCerts"; const std::string FlightSqlConnection::USE_SYSTEM_TRUST_STORE = "useSystemTrustStore"; const std::string FlightSqlConnection::STRING_COLUMN_LENGTH = "StringColumnLength"; const std::string FlightSqlConnection::USE_WIDE_CHAR = "UseWideChar"; +const std::string FlightSqlConnection::CHUNK_BUFFER_CAPACITY = "ChunkBufferCapacity"; const std::vector FlightSqlConnection::ALL_KEYS = { FlightSqlConnection::DSN, FlightSqlConnection::DRIVER, FlightSqlConnection::HOST, FlightSqlConnection::PORT, FlightSqlConnection::TOKEN, FlightSqlConnection::UID, FlightSqlConnection::USER_ID, FlightSqlConnection::PWD, FlightSqlConnection::USE_ENCRYPTION, FlightSqlConnection::TRUSTED_CERTS, FlightSqlConnection::USE_SYSTEM_TRUST_STORE, FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION, FlightSqlConnection::STRING_COLUMN_LENGTH, - FlightSqlConnection::USE_WIDE_CHAR}; + FlightSqlConnection::USE_WIDE_CHAR, FlightSqlConnection::CHUNK_BUFFER_CAPACITY}; namespace { @@ -201,6 +202,7 @@ void FlightSqlConnection::Connect(const ConnPropertyMap &properties, void FlightSqlConnection::PopulateMetadataSettings(const Connection::ConnPropertyMap &conn_property_map) { metadata_settings_.string_column_length_ = GetStringColumnLength(conn_property_map); metadata_settings_.use_wide_char_ = GetUseWideChar(conn_property_map); + metadata_settings_.chunk_buffer_capacity_ = GetChunkBufferCapacity(conn_property_map); } boost::optional FlightSqlConnection::GetStringColumnLength(const Connection::ConnPropertyMap &conn_property_map) { @@ -229,6 +231,20 @@ bool FlightSqlConnection::GetUseWideChar(const ConnPropertyMap &connPropertyMap) return AsBool(connPropertyMap, FlightSqlConnection::USE_WIDE_CHAR).value_or(default_value); } +size_t FlightSqlConnection::GetChunkBufferCapacity(const ConnPropertyMap &connPropertyMap) { + size_t default_value = 5; + try { + return AsInt32(1, connPropertyMap, FlightSqlConnection::CHUNK_BUFFER_CAPACITY).value_or(default_value); + } catch (const std::exception& e) { + diagnostics_.AddWarning( + std::string("Invalid value for connection property " + FlightSqlConnection::CHUNK_BUFFER_CAPACITY + + ". Please ensure it has a valid numeric value. Message: " + e.what()), + "01000", odbcabstraction::ODBCErrorCodes_GENERAL_WARNING); + } + + return default_value; +} + const FlightCallOptions & FlightSqlConnection::PopulateCallOptions(const ConnPropertyMap &props) { // Set CONNECTION_TIMEOUT attribute or LOGIN_TIMEOUT depending on if this diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h index 4311d63b0ab02..a01be3db7032c 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.h @@ -61,6 +61,7 @@ class FlightSqlConnection : public odbcabstraction::Connection { static const std::string USE_SYSTEM_TRUST_STORE; static const std::string STRING_COLUMN_LENGTH; static const std::string USE_WIDE_CHAR; + static const std::string CHUNK_BUFFER_CAPACITY; explicit FlightSqlConnection(odbcabstraction::OdbcVersion odbc_version, const std::string &driver_version = "0.9.0.0"); @@ -104,6 +105,8 @@ class FlightSqlConnection : public odbcabstraction::Connection { boost::optional GetStringColumnLength(const ConnPropertyMap &connPropertyMap); bool GetUseWideChar(const ConnPropertyMap &connPropertyMap); + + size_t GetChunkBufferCapacity(const ConnPropertyMap &connPropertyMap); }; } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc index a293b4bf91de6..42fbf4352d4c5 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.cc @@ -38,7 +38,7 @@ FlightSqlResultSet::FlightSqlResultSet( const odbcabstraction::MetadataSettings &metadata_settings) : metadata_settings_(metadata_settings), - chunk_iterator_(flight_sql_client, call_options, flight_info), + chunk_buffer_(flight_sql_client, call_options, flight_info, metadata_settings_.chunk_buffer_capacity_), transformer_(transformer), metadata_(transformer ? new FlightSqlResultSetMetadata(transformer->GetTransformedSchema(), metadata_settings_) @@ -64,7 +64,7 @@ size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, size_t bind_typ // populated yet assert(rows > 0); if (current_chunk_.data == nullptr) { - if (!chunk_iterator_.GetNext(¤t_chunk_)) { + if (!chunk_buffer_.GetNext(¤t_chunk_)) { return 0; } @@ -90,7 +90,7 @@ size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, size_t bind_typ static_cast(batch_rows - current_row_)); if (rows_to_fetch == 0) { - if (!chunk_iterator_.GetNext(¤t_chunk_)) { + if (!chunk_buffer_.GetNext(¤t_chunk_)) { break; } @@ -204,12 +204,12 @@ size_t FlightSqlResultSet::Move(size_t rows, size_t bind_offset, size_t bind_typ } void FlightSqlResultSet::Close() { - chunk_iterator_.Close(); + chunk_buffer_.Close(); current_chunk_.data = nullptr; } void FlightSqlResultSet::Cancel() { - chunk_iterator_.Close(); + chunk_buffer_.Close(); current_chunk_.data = nullptr; } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h index 21dc9d0b31340..4f8e15ca58436 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_result_set.h @@ -6,7 +6,7 @@ #pragma once -#include "flight_sql_stream_chunk_iterator.h" +#include "flight_sql_stream_chunk_buffer.h" #include "record_batch_transformer.h" #include "utils.h" #include "odbcabstraction/types.h" @@ -36,7 +36,7 @@ class FlightSqlResultSetColumn; class FlightSqlResultSet : public ResultSet { private: const odbcabstraction::MetadataSettings& metadata_settings_; - FlightStreamChunkIterator chunk_iterator_; + FlightStreamChunkBuffer chunk_buffer_; FlightStreamChunk current_chunk_; std::shared_ptr schema_; std::shared_ptr transformer_; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_buffer.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_buffer.cc new file mode 100644 index 0000000000000..989f16043581e --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_buffer.cc @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#include "flight_sql_stream_chunk_buffer.h" +#include "utils.h" + + +namespace driver { +namespace flight_sql { + +using arrow::flight::FlightEndpoint; + +FlightStreamChunkBuffer::FlightStreamChunkBuffer(FlightSqlClient &flight_sql_client, + const arrow::flight::FlightCallOptions &call_options, + const std::shared_ptr &flight_info, + size_t queue_capacity): queue_(queue_capacity) { + + // FIXME: Endpoint iteration should consider endpoints may be at different hosts + for (const auto & endpoint : flight_info->endpoints()) { + const arrow::flight::Ticket &ticket = endpoint.ticket; + + auto result = flight_sql_client.DoGet(call_options, ticket); + ThrowIfNotOK(result.status()); + std::shared_ptr stream_reader_ptr(std::move(result.ValueOrDie())); + + BlockingQueue>::Supplier supplier = [=] { + auto result = stream_reader_ptr->Next(); + bool isNotOk = !result.ok(); + bool isNotEmpty = result.ok() && (result.ValueOrDie().data != nullptr); + + return boost::make_optional(isNotOk || isNotEmpty, std::move(result)); + }; + queue_.AddProducer(std::move(supplier)); + } +} + +bool FlightStreamChunkBuffer::GetNext(FlightStreamChunk *chunk) { + Result result; + if (!queue_.Pop(&result)) { + return false; + } + + if (!result.status().ok()) { + Close(); + throw odbcabstraction::DriverException(result.status().message()); + } + *chunk = std::move(result.ValueOrDie()); + return chunk->data != nullptr; +} + +void FlightStreamChunkBuffer::Close() { + queue_.Close(); +} + +FlightStreamChunkBuffer::~FlightStreamChunkBuffer() { + Close(); +} + +} +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_buffer.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_buffer.h new file mode 100644 index 0000000000000..bbe55daa5b6f8 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_buffer.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#pragma once + +#include +#include +#include + + +namespace driver { +namespace flight_sql { + +using arrow::Result; +using arrow::flight::FlightInfo; +using arrow::flight::FlightStreamChunk; +using arrow::flight::FlightStreamReader; +using arrow::flight::sql::FlightSqlClient; +using driver::odbcabstraction::BlockingQueue; + +class FlightStreamChunkBuffer { + BlockingQueue> queue_; + +public: + FlightStreamChunkBuffer(FlightSqlClient &flight_sql_client, + const arrow::flight::FlightCallOptions &call_options, + const std::shared_ptr &flight_info, + size_t queue_capacity = 5); + + ~FlightStreamChunkBuffer(); + + void Close(); + + bool GetNext(FlightStreamChunk* chunk); + +}; + +} +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc deleted file mode 100644 index e979f0ee6e821..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2020-2022 Dremio Corporation - * - * See "LICENSE" for license information. - */ - -#include "flight_sql_stream_chunk_iterator.h" -#include -#include "utils.h" - -namespace driver { -namespace flight_sql { - -using arrow::flight::FlightEndpoint; - -FlightStreamChunkIterator::FlightStreamChunkIterator( - FlightSqlClient &flight_sql_client, - const arrow::flight::FlightCallOptions &call_options, - const std::shared_ptr &flight_info) - : closed_(false) { - const std::vector &endpoints = flight_info->endpoints(); - - stream_readers_.reserve(endpoints.size()); - for (int i = 0; i < endpoints.size(); ++i) { - auto result = flight_sql_client.DoGet(call_options, endpoints[i].ticket); - ThrowIfNotOK(result.status()); - stream_readers_.push_back(std::move(result.ValueOrDie())); - } - - stream_readers_it_ = stream_readers_.begin(); -} - -FlightStreamChunkIterator::~FlightStreamChunkIterator() { Close(); } - -bool FlightStreamChunkIterator::GetNext(FlightStreamChunk *chunk) { - if (closed_) return false; - - chunk->data = nullptr; - while (stream_readers_it_ != stream_readers_.end()) { - const auto &chunk_result = (*stream_readers_it_)->Next(); - ThrowIfNotOK(chunk_result.status()); - chunk->data = chunk_result.ValueOrDie().data; - if (chunk->data != nullptr) { - return true; - } - ++stream_readers_it_; - } - return false; -} - -void FlightStreamChunkIterator::Close() { - if (closed_) { - return; - } - for (const auto &item : stream_readers_) { - item->Cancel(); - } - closed_ = true; -} - -} // namespace flight_sql -} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.h deleted file mode 100644 index 00d00a03d0779..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_stream_chunk_iterator.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2020-2022 Dremio Corporation - * - * See "LICENSE" for license information. - */ - -#pragma once - -#include -#include - -namespace driver { -namespace flight_sql { - -using arrow::flight::FlightInfo; -using arrow::flight::FlightStreamChunk; -using arrow::flight::FlightStreamReader; -using arrow::flight::sql::FlightSqlClient; - -class FlightStreamChunkIterator { -private: - std::vector> stream_readers_; - std::vector>::iterator stream_readers_it_; - bool closed_; - -public: - FlightStreamChunkIterator( - FlightSqlClient &flight_sql_client, - const arrow::flight::FlightCallOptions &call_options, - const std::shared_ptr &flight_info); - - ~FlightStreamChunkIterator(); - - bool GetNext(FlightStreamChunk *chunk); - - void Close(); -}; - -} // namespace flight_sql -} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc index 0d08465a1575c..b87ab94553c14 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/get_info_cache.cc @@ -17,7 +17,7 @@ #include #include -#include "flight_sql_stream_chunk_iterator.h" +#include "flight_sql_stream_chunk_buffer.h" #include "scalar_function_reporter.h" #include "utils.h" @@ -279,7 +279,7 @@ bool GetInfoCache::LoadInfoFromServer() { arrow::Result> result = sql_client_->GetSqlInfo(call_options_, {}); ThrowIfNotOK(result.status()); - FlightStreamChunkIterator chunk_iter(*sql_client_, call_options_, + FlightStreamChunkBuffer chunk_iter(*sql_client_, call_options_, result.ValueOrDie()); FlightStreamChunk chunk; diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc index 034f095e9956d..ce842aaba1568 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/main.cc @@ -72,22 +72,17 @@ void TestBindColumn(const std::shared_ptr &connection) { void TestGetData(const std::shared_ptr &connection) { const std::shared_ptr &statement = connection->CreateStatement(); statement->Execute( - "SELECT * FROM \"@dremio\".\"test_numeric\""); + "SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6"); const std::shared_ptr &result_set = statement->GetResultSet(); const std::shared_ptr &metadata = result_set->GetMetadata(); - std::cout << metadata->GetDataType(1) << std::endl; - while (result_set->Move(1, 0, 0, nullptr) == 1) { - driver::odbcabstraction::NUMERIC_STRUCT result; + char result[128]; ssize_t result_length; - result_set->GetData(1, driver::odbcabstraction::CDataType_NUMERIC, 0, 0, - &result, 0, &result_length); - std::cout << "precision:" << result.precision << std::endl; - std::cout << "scale:" << result.scale << std::endl; - std::cout << "sign:" << result.sign << std::endl; - std::cout << "val:" << result.val << std::endl; + result_set->GetData(1, driver::odbcabstraction::CDataType_CHAR, 0, 0, + &result, sizeof(result), &result_length); + std::cout << result << std::endl; } } diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/blocking_queue.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/blocking_queue.h new file mode 100644 index 0000000000000..1329fff5479fb --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/blocking_queue.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace driver { +namespace odbcabstraction { + + +template +class BlockingQueue { + + size_t capacity_; + std::vector buffer_; + size_t buffer_size_{0}; + size_t left_{0}; // index where variables are put inside of buffer (produced) + size_t right_{0}; // index where variables are removed from buffer (consumed) + + std::mutex mtx_; + std::condition_variable not_empty_; + std::condition_variable not_full_; + + std::vector threads_; + std::atomic active_threads_{0}; + std::atomic closed_{false}; + +public: + typedef std::function(void)> Supplier; + + BlockingQueue(size_t capacity): capacity_(capacity), buffer_(capacity) {} + + void AddProducer(Supplier supplier) { + active_threads_++; + threads_.emplace_back([=] { + while (!closed_) { + // Block while queue is full + std::unique_lock unique_lock(mtx_); + if (!WaitUntilCanPushOrClosed(unique_lock)) break; + unique_lock.unlock(); + + // Only one thread at a time be notified and call supplier + auto item = supplier(); + if (!item) break; + + Push(*item); + } + + std::unique_lock unique_lock(mtx_); + active_threads_--; + not_empty_.notify_all(); + }); + } + + void Push(T item) { + std::unique_lock unique_lock(mtx_); + if (!WaitUntilCanPushOrClosed(unique_lock)) return; + + buffer_[right_] = std::move(item); + + right_ = (right_ + 1) % capacity_; + buffer_size_++; + + not_empty_.notify_one(); + } + + bool Pop(T *result) { + std::unique_lock unique_lock(mtx_); + if (!WaitUntilCanPopOrClosed(unique_lock)) return false; + + *result = std::move(buffer_[left_]); + + left_ = (left_ + 1) % capacity_; + buffer_size_--; + + not_full_.notify_one(); + + return true; + } + + void Close() { + std::unique_lock unique_lock(mtx_); + + if (closed_) return; + closed_ = true; + not_empty_.notify_all(); + not_full_.notify_all(); + + unique_lock.unlock(); + + for (auto &item: threads_) { + item.join(); + } + } + +private: + bool WaitUntilCanPushOrClosed(std::unique_lock &unique_lock) { + not_full_.wait(unique_lock, [this]() { + return closed_ || buffer_size_ != capacity_; + }); + return !closed_; + } + + bool WaitUntilCanPopOrClosed(std::unique_lock &unique_lock) { + not_empty_.wait(unique_lock, [this]() { + return closed_ || buffer_size_ != 0 || active_threads_ == 0; + }); + + return !closed_ && buffer_size_ > 0; + } +}; + +} +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h index f6ed916b89f10..2f367cbcb8355 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/types.h @@ -164,8 +164,9 @@ enum RowStatus: uint16_t { }; struct MetadataSettings { - boost::optional string_column_length_{boost::none}; - bool use_wide_char_; + boost::optional string_column_length_{boost::none}; + size_t chunk_buffer_capacity_; + bool use_wide_char_; }; } // namespace odbcabstraction From bb95d6d91f872311d1039d4211a5e1f73bb2695f Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Thu, 28 Jul 2022 17:36:45 -0300 Subject: [PATCH 182/183] Revert "Implement logger interface" This reverts commit 60dd060e7570d9435e17037a6e93f2609bbff264. The reason is that this commit introduced build problems on Windows and there are some design decisions we should take a second look into. Change-Id: Ia3e0da34b18e43fa593ec0eb2f4482bc18840ef5 --- .../flightsql-odbc/CMakeLists.txt | 22 - .../flight_sql/flight_sql_driver.cc | 74 -- .../include/flight_sql/flight_sql_driver.h | 2 - .../odbcabstraction/CMakeLists.txt | 9 - .../include/odbcabstraction/logger.h | 52 -- .../include/odbcabstraction/spd_logger.h | 44 - .../include/odbcabstraction/spi/driver.h | 3 - .../include/odbcabstraction/utils.h | 7 - .../flightsql-odbc/odbcabstraction/logger.cc | 24 - .../odbcabstraction/spd_logger.cc | 146 ---- .../flightsql-odbc/odbcabstraction/utils.cc | 49 -- .../odbcabstraction/whereami.cc | 804 ------------------ .../flightsql-odbc/odbcabstraction/whereami.h | 67 -- .../flightsql-odbc/vcpkg.json | 1 - 14 files changed, 1304 deletions(-) delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/logger.h delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spd_logger.h delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/logger.cc delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/spd_logger.cc delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.cc delete mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt index aea59e469344a..cd7966fac61d7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/CMakeLists.txt @@ -25,28 +25,6 @@ if(CMAKE_BUILD_TYPE STREQUAL "Release") add_compile_definitions(NDEBUG) endif() -add_compile_definitions(FMT_HEADER_ONLY) - -include(ExternalProject) - -message("Using spdlog from https://github.com/gabime/spdlog on tag v1.10.0") -ExternalProject_Add( - dep_spdlog - GIT_REPOSITORY "https://github.com/gabime/spdlog" - GIT_TAG "v1.10.0" - GIT_SHALLOW 1 - UPDATE_COMMAND "" - PATCH_COMMAND "" - CMAKE_ARGS - -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/dep_spdlog-prefix/src/dep_spdlog-install - -DSPDLOG_BUILD_EXAMPLES=OFF - -DSPDLOG_BUILD_BENCH=OFF - -DSPDLOG_BUILD_TESTS=OFF - TEST_COMMAND "" -) - -include_directories(${CMAKE_CURRENT_BINARY_DIR}/dep_spdlog-prefix/src/dep_spdlog/include) - # Fetch and include GTest # Adapted from Google's documentation: https://google.github.io/googletest/quickstart-cmake.html#set-up-a-project include(FetchContent) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index 5cabfe79454db..8e731d3b4414f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -5,41 +5,14 @@ */ #include "flight_sql_connection.h" -#include "odbcabstraction/utils.h" -#include #include -#include #include - -#define DEFAULT_MAXIMUM_FILE_SIZE 16777216 - namespace driver { namespace flight_sql { using odbcabstraction::Connection; using odbcabstraction::OdbcVersion; -using odbcabstraction::LogLevel; -using odbcabstraction::SPDLogger; - -namespace { - LogLevel ToLogLevel(int64_t level) { - switch (level) { - case 0: - return LogLevel::TRACE; - case 1: - return LogLevel::DEBUG; - case 2: - return LogLevel::INFO; - case 3: - return LogLevel::WARN; - case 4: - return LogLevel::ERROR; - default: - return LogLevel::OFF; - } - } -} FlightSqlDriver::FlightSqlDriver() : diagnostics_("Apache Arrow", "Flight SQL", OdbcVersion::V_3), @@ -58,52 +31,5 @@ odbcabstraction::Diagnostics &FlightSqlDriver::GetDiagnostics() { void FlightSqlDriver::SetVersion(std::string version) { version_ = std::move(version); } - -void FlightSqlDriver::RegisterLog(const std::string &configFileName) { - odbcabstraction::PropertyMap propertyMap; - driver::odbcabstraction::ReadConfigFile(propertyMap, configFileName); - - auto log_enable_iterator = propertyMap.find(SPDLogger::LOG_ENABLED); - - auto log_enabled = log_enable_iterator != propertyMap.end() ? - odbcabstraction::AsBool(log_enable_iterator->second) : false; - - auto log_path_iterator = propertyMap.find(SPDLogger::LOG_PATH); - - auto log_path = - log_path_iterator != propertyMap.end() ? log_path_iterator->second : ""; - - if (*log_enabled && !log_path.empty()) { - auto log_level_iterator = propertyMap.find(SPDLogger::LOG_LEVEL); - - auto log_level = - log_level_iterator != propertyMap.end() ? std::stoi(log_level_iterator->second) : 1; - - auto maximum_file_size_iterator = propertyMap.find(SPDLogger::MAXIMUM_FILE_SIZE); - - auto maximum_file_size = maximum_file_size_iterator != propertyMap.end() ? - std::stoi(maximum_file_size_iterator->second) : DEFAULT_MAXIMUM_FILE_SIZE; - - auto maximum_file_quantity_iterator = propertyMap. - find(SPDLogger::FILE_QUANTITY); - - auto maximum_file_quantity = - maximum_file_quantity_iterator != propertyMap.end() ? std::stoi( - maximum_file_quantity_iterator->second) : 1; - - std::unique_ptr logger (new odbcabstraction::SPDLogger()); - - logger->init(maximum_file_quantity, maximum_file_size, - log_path, ToLogLevel(log_level)); - odbcabstraction::Logger::SetInstance(std::move(logger)); - } else { - std::unique_ptr logger (new odbcabstraction::SPDLogger()); - - logger->init(1, 1, - log_path, LogLevel::OFF); - odbcabstraction::Logger::SetInstance(std::move(logger)); - } -} - } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h index 52078d5721623..e55a7126c0359 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h @@ -26,8 +26,6 @@ class FlightSqlDriver : public odbcabstraction::Driver { odbcabstraction::Diagnostics &GetDiagnostics() override; void SetVersion(std::string version) override; - - void RegisterLog(const std::string &configFileName) override; }; }; // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index 85a250533cae9..0ffd493a201e7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -12,9 +12,7 @@ add_library(odbcabstraction include/odbcabstraction/diagnostics.h include/odbcabstraction/error_codes.h include/odbcabstraction/exceptions.h - include/odbcabstraction/logger.h include/odbcabstraction/platform.h - include/odbcabstraction/spd_logger.h include/odbcabstraction/types.h include/odbcabstraction/utils.h include/odbcabstraction/odbc_impl/AttributeUtils.h @@ -34,11 +32,7 @@ add_library(odbcabstraction diagnostics.cc encoding.cc exceptions.cc - logger.cc - spd_logger.cc utils.cc - whereami.h - whereami.cc odbc_impl/ODBCConnection.cc odbc_impl/ODBCDescriptor.cc odbc_impl/ODBCEnvironment.cc @@ -51,7 +45,4 @@ set_target_properties(odbcabstraction LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib ) - -add_dependencies(odbcabstraction dep_spdlog) - target_link_libraries(odbcabstraction) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/logger.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/logger.h deleted file mode 100644 index aac286334494d..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/logger.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2020-2022 Dremio Corporation - * - * See "LICENSE" for license information. - */ - -#pragma once - -#include -#include -#include - -#include -#include - -#include - -#define LOG_DEBUG(...) driver::odbcabstraction::Logger::GetInstance()->log(driver::odbcabstraction::LogLevel::DEBUG, __VA_ARGS__); -#define LOG_INFO(...) driver::odbcabstraction::Logger::GetInstance()->log(driver::odbcabstraction::LogLevel::INFO, __VA_ARGS__); -#define LOG_ERROR(...) driver::odbcabstraction::Logger::GetInstance()->log(driver::odbcabstraction::LogLevel::ERROR, __VA_ARGS__); -#define LOG_TRACE(...) driver::odbcabstraction::Logger::GetInstance()->log(driver::odbcabstraction::LogLevel::TRACE, __VA_ARGS__); -#define LOG_WARN(...) driver::odbcabstraction::Logger::GetInstance()->log(driver::odbcabstraction::LogLevel::WARN, __VA_ARGS__); - -namespace driver { -namespace odbcabstraction { - -enum LogLevel { TRACE, DEBUG, INFO, WARN, ERROR, OFF }; - -class Logger { -protected: - Logger() = default; - -public: - static Logger *GetInstance(); - static void SetInstance(std::unique_ptr logger); - - virtual ~Logger() = default; - - virtual void log(LogLevel level, const std::string &message) = 0; - - virtual bool checkLogLevel(LogLevel called) = 0; - - template - void log(LogLevel level, fmt::format_string fmt, Args &&... args) { - if(checkLogLevel(level)) { - log(level, fmt::format(fmt, args...)); - } - }; -}; - -} // namespace odbcabstraction -} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spd_logger.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spd_logger.h deleted file mode 100644 index 2d4a3e75b364a..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spd_logger.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2020-2022 Dremio Corporation - * - * See "LICENSE" for license information. - */ - -#pragma once - -#include "odbcabstraction/logger.h" - -#include -#include - -#include - -namespace driver { -namespace odbcabstraction { - -class SPDLogger : public Logger { -protected: - std::shared_ptr logger_; - -public: - static const std::string LOG_LEVEL; - static const std::string LOG_PATH; - static const std::string MAXIMUM_FILE_SIZE; - static const std::string FILE_QUANTITY; - static const std::string LOG_ENABLED; - - SPDLogger() = default; - ~SPDLogger(); - SPDLogger(SPDLogger &other) = delete; - - void operator=(const SPDLogger &) = delete; - void init(int64_t fileQuantity, int64_t maxFileSize, - const std::string &fileNamePrefix, LogLevel level); - - void log(LogLevel level, const std::string &message) override; - - bool checkLogLevel(LogLevel called) override; -}; - -} // namespace odbcabstraction -} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h index b5968d302c255..974704f7fbf3f 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h @@ -35,9 +35,6 @@ class Driver { /// \brief Sets the driver version. virtual void SetVersion(std::string version) = 0; - - /// \brief Register a log to be used by the system. - virtual void RegisterLog(const std::string &configFileName) = 0; }; } // namespace odbcabstraction diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h index a3f19c963693b..a5617adac5036 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h @@ -7,15 +7,11 @@ #pragma once #include -#include #include namespace driver { namespace odbcabstraction { -typedef std::map - PropertyMap; - using driver::odbcabstraction::Connection; /// Parse a string value to a boolean. @@ -40,8 +36,5 @@ boost::optional AsBool(const Connection::ConnPropertyMap& connPropertyMap, /// \exception std::out_of_range exception from \link std::stoi \endlink boost::optional AsInt32(int32_t min_value, const Connection::ConnPropertyMap& connPropertyMap, const std::string& property_name); - - -void ReadConfigFile(PropertyMap &properties, const std::string &configFileName); } // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/logger.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/logger.cc deleted file mode 100644 index 16ac682df7aec..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/logger.cc +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2020-2022 Dremio Corporation - * - * See "LICENSE" for license information. - */ - - -#include - -namespace driver { -namespace odbcabstraction { - -static std::unique_ptr odbc_logger_ = nullptr; - -Logger *Logger::GetInstance() { - return odbc_logger_.get(); -} - -void Logger::SetInstance(std::unique_ptrlogger) { - odbc_logger_ = std::move(logger); -} - -} -} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/spd_logger.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/spd_logger.cc deleted file mode 100644 index 8fcf1ac0489b4..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/spd_logger.cc +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2020-2022 Dremio Corporation - * - * See "LICENSE" for license information. - */ - -#include "odbcabstraction/spd_logger.h" - -#include "odbcabstraction/logger.h" - -#include -#include -#include - -#include -#include - -namespace driver { -namespace odbcabstraction { - -const std::string SPDLogger::LOG_LEVEL = "LogLevel"; -const std::string SPDLogger::LOG_PATH= "LogPath"; -const std::string SPDLogger::MAXIMUM_FILE_SIZE= "MaximumFileSize"; -const std::string SPDLogger::FILE_QUANTITY= "FileQuantity"; -const std::string SPDLogger::LOG_ENABLED= "LogEnabled"; - -namespace { -std::function shutdown_handler; -void signal_handler(int signal) { - shutdown_handler(signal); -} - -typedef void (*Handler)(int signum); - -Handler old_sigint_handler = SIG_IGN; -Handler old_sigsegv_handler = SIG_IGN; -Handler old_sigabrt_handler = SIG_IGN; -Handler old_sigkill_handler = SIG_IGN; - -Handler GetHandlerFromSignal(int signum) { - switch (signum) { - case(SIGINT): - return old_sigint_handler; - case(SIGSEGV): - return old_sigsegv_handler; - case(SIGABRT): - return old_sigabrt_handler; - case(SIGKILL): - return old_sigkill_handler; - } -} - -void SetSignalHandler(int signum) { - Handler old = signal(signum, SIG_IGN); - if (old != SIG_IGN) { - auto old_handler = GetHandlerFromSignal(signum); - old_handler = old; - } - signal(signum, signal_handler); -} - -void ResetSignalHandler(int signum) { - Handler actual_handler = signal(signum, SIG_IGN); - if (actual_handler == signal_handler) { - signal(signum, GetHandlerFromSignal(signum)); - } -} - - -spdlog::level::level_enum ToSpdLogLevel(LogLevel level) { - switch (level) { - case TRACE: - return spdlog::level::trace; - case DEBUG: - return spdlog::level::debug; - case INFO: - return spdlog::level::info; - case WARN: - return spdlog::level::warn; - case ERROR: - return spdlog::level::err; - default: - return spdlog::level::off; - } -} -} // namespace - -void SPDLogger::init(int64_t fileQuantity, int64_t maxFileSize, - const std::string &fileNamePrefix, LogLevel level) { - logger_ = spdlog::rotating_logger_mt( - "ODBC Logger", fileNamePrefix, maxFileSize, fileQuantity); - - logger_->set_level(ToSpdLogLevel(level)); - - if (level != LogLevel::OFF) { - SetSignalHandler(SIGINT); - SetSignalHandler(SIGSEGV); - SetSignalHandler(SIGABRT); - SetSignalHandler(SIGKILL); - shutdown_handler = [&](int signal) { - logger_->flush(); - spdlog::shutdown(); - auto handler = GetHandlerFromSignal(signal); - handler(signal); - }; - } -} - -void SPDLogger::log(LogLevel level, const std::string &message) { - switch (level) { - case DEBUG: - logger_->debug(message); - break; - case TRACE: - logger_->trace(message); - break; - case INFO: - logger_->info(message); - break; - case WARN: - logger_->warn(message); - break; - case ERROR: - logger_->error(message); - break; - } -} - -SPDLogger::~SPDLogger() { - ResetSignalHandler(SIGINT); - ResetSignalHandler(SIGSEGV); - ResetSignalHandler(SIGABRT); - ResetSignalHandler(SIGKILL); -} - -bool SPDLogger::checkLogLevel(LogLevel called) { - auto set = logger_->level(); - if (set == spdlog::level::off) { - return false; - } else { - return set <= ToSpdLogLevel(called); - } -} - -} // namespace odbcabstraction -} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc index 831c63c2eeadd..8256cb230af40 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc @@ -5,16 +5,8 @@ */ #include -#include "whereami.h" - -#include -#include #include -#include -#include - -#define CONFIG_LOG_NAME "/arrow-odbc.ini" namespace driver { namespace odbcabstraction { @@ -53,46 +45,5 @@ boost::optional AsInt32(int32_t min_value, const Connection::ConnProper return boost::none; } -std::string GetModulePath() { - std::vector path; - int length, dirname_length; - length = wai_getModulePath(NULL, 0, &dirname_length); - - if (length != 0) { - path.resize(length); - wai_getModulePath(path.data(), length, &dirname_length); - } else { - throw DriverException("Could not find module path."); - } - - return std::string(path.begin(), path.begin() + dirname_length); -} - -void ReadConfigFile(PropertyMap &properties, const std::string &configFileName) { - auto config_path = GetModulePath(); - - std::ifstream myfile; - myfile.open(config_path + "/" + configFileName); - - if (myfile.fail()) { - throw DriverException("Could not read the driver config file."); - } - - std::string temp_config; - - boost::char_separator separator("="); - while(myfile.good()) { - myfile >> temp_config; - boost::tokenizer< boost::char_separator> tokenizer(temp_config, separator); - - auto iterator = tokenizer.begin(); - - std::string key = *iterator; - std::string value = *++iterator; - - properties[key] = std::move(value); - } -} - } // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.cc deleted file mode 100644 index 39324d16e2cb8..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.cc +++ /dev/null @@ -1,804 +0,0 @@ -// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses -// without any warranty. -// by Gregory Pakosz (@gpakosz) -// https://github.com/gpakosz/whereami - -// in case you want to #include "whereami.c" in a larger compilation unit -#if !defined(WHEREAMI_H) -#include "whereami.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(__linux__) || defined(__CYGWIN__) -#undef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE -#elif defined(__APPLE__) -#undef _DARWIN_C_SOURCE -#define _DARWIN_C_SOURCE -#define _DARWIN_BETTER_REALPATH -#endif - -#if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC) -#include -#endif - -#if !defined(WAI_MALLOC) -#define WAI_MALLOC(size) malloc(size) -#endif - -#if !defined(WAI_FREE) -#define WAI_FREE(p) free(p) -#endif - -#if !defined(WAI_REALLOC) -#define WAI_REALLOC(p, size) realloc(p, size) -#endif - -#ifndef WAI_NOINLINE -#if defined(_MSC_VER) -#define WAI_NOINLINE __declspec(noinline) -#elif defined(__GNUC__) -#define WAI_NOINLINE __attribute__((noinline)) -#else -#error unsupported compiler -#endif -#endif - -#if defined(_MSC_VER) -#define WAI_RETURN_ADDRESS() _ReturnAddress() -#elif defined(__GNUC__) -#define WAI_RETURN_ADDRESS() __builtin_extract_return_addr(__builtin_return_address(0)) -#else -#error unsupported compiler -#endif - -#if defined(_WIN32) - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#if defined(_MSC_VER) -#pragma warning(push, 3) -#endif -#include -#include -#if defined(_MSC_VER) -#pragma warning(pop) -#endif -#include - -static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length) -{ - wchar_t buffer1[MAX_PATH]; - wchar_t buffer2[MAX_PATH]; - wchar_t* path = NULL; - int length = -1; - bool ok; - - for (ok = false; !ok; ok = true) - { - DWORD size; - int length_, length__; - - size = GetModuleFileNameW(module, buffer1, sizeof(buffer1) / sizeof(buffer1[0])); - - if (size == 0) - break; - else if (size == (DWORD)(sizeof(buffer1) / sizeof(buffer1[0]))) - { - DWORD size_ = size; - do - { - wchar_t* path_; - - path_ = (wchar_t*)WAI_REALLOC(path, sizeof(wchar_t) * size_ * 2); - if (!path_) - break; - size_ *= 2; - path = path_; - size = GetModuleFileNameW(module, path, size_); - } - while (size == size_); - - if (size == size_) - break; - } - else - path = buffer1; - - if (!_wfullpath(buffer2, path, MAX_PATH)) - break; - length_ = (int)wcslen(buffer2); - length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_ , out, capacity, NULL, NULL); - - if (length__ == 0) - length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_, NULL, 0, NULL, NULL); - if (length__ == 0) - break; - - if (length__ <= capacity && dirname_length) - { - int i; - - for (i = length__ - 1; i >= 0; --i) - { - if (out[i] == '\\') - { - *dirname_length = i; - break; - } - } - } - - length = length__; - } - - if (path != buffer1) - WAI_FREE(path); - - return ok ? length : -1; -} - -WAI_NOINLINE WAI_FUNCSPEC -int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) -{ - return WAI_PREFIX(getModulePath_)(NULL, out, capacity, dirname_length); -} - -WAI_NOINLINE WAI_FUNCSPEC -int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) -{ - HMODULE module; - int length = -1; - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable: 4054) -#endif - if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)WAI_RETURN_ADDRESS(), &module)) -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - { - length = WAI_PREFIX(getModulePath_)(module, out, capacity, dirname_length); - } - - return length; -} - -#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) || defined(WAI_USE_PROC_SELF_EXE) - -#include -#include -#include -#if defined(__linux__) -#include -#else -#include -#endif -#ifndef __STDC_FORMAT_MACROS -#define __STDC_FORMAT_MACROS -#endif -#include -#include - -#if !defined(WAI_PROC_SELF_EXE) -#if defined(__sun) -#define WAI_PROC_SELF_EXE "/proc/self/path/a.out" -#else -#define WAI_PROC_SELF_EXE "/proc/self/exe" -#endif -#endif - -WAI_FUNCSPEC -int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) -{ - char buffer[PATH_MAX]; - char* resolved = NULL; - int length = -1; - bool ok; - - for (ok = false; !ok; ok = true) - { - resolved = realpath(WAI_PROC_SELF_EXE, buffer); - if (!resolved) - break; - - length = (int)strlen(resolved); - if (length <= capacity) - { - memcpy(out, resolved, length); - - if (dirname_length) - { - int i; - - for (i = length - 1; i >= 0; --i) - { - if (out[i] == '/') - { - *dirname_length = i; - break; - } - } - } - } - } - - return ok ? length : -1; -} - -#if !defined(WAI_PROC_SELF_MAPS_RETRY) -#define WAI_PROC_SELF_MAPS_RETRY 5 -#endif - -#if !defined(WAI_PROC_SELF_MAPS) -#if defined(__sun) -#define WAI_PROC_SELF_MAPS "/proc/self/map" -#else -#define WAI_PROC_SELF_MAPS "/proc/self/maps" -#endif -#endif - -#if defined(__ANDROID__) || defined(ANDROID) -#include -#include -#include -#endif -#include - -WAI_NOINLINE WAI_FUNCSPEC -int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) -{ - int length = -1; - FILE* maps = NULL; - - for (int r = 0; r < WAI_PROC_SELF_MAPS_RETRY; ++r) - { - maps = fopen(WAI_PROC_SELF_MAPS, "r"); - if (!maps) - break; - - for (;;) - { - char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX]; - uint64_t low, high; - char perms[5]; - uint64_t offset; - uint32_t major, minor; - char path[PATH_MAX]; - uint32_t inode; - - if (!fgets(buffer, sizeof(buffer), maps)) - break; - - if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8) - { - uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS(); - if (low <= addr && addr <= high) - { - char* resolved; - - resolved = realpath(path, buffer); - if (!resolved) - break; - - length = (int)strlen(resolved); -#if defined(__ANDROID__) || defined(ANDROID) - if (length > 4 - &&buffer[length - 1] == 'k' - &&buffer[length - 2] == 'p' - &&buffer[length - 3] == 'a' - &&buffer[length - 4] == '.') - { - int fd = open(path, O_RDONLY); - if (fd == -1) - { - length = -1; // retry - break; - } - - char* begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0); - if (begin == MAP_FAILED) - { - close(fd); - length = -1; // retry - break; - } - - char* p = begin + offset - 30; // minimum size of local file header - while (p >= begin) // scan backwards - { - if (*((uint32_t*)p) == 0x04034b50UL) // local file header signature found - { - uint16_t length_ = *((uint16_t*)(p + 26)); - - if (length + 2 + length_ < (int)sizeof(buffer)) - { - memcpy(&buffer[length], "!/", 2); - memcpy(&buffer[length + 2], p + 30, length_); - length += 2 + length_; - } - - break; - } - - --p; - } - - munmap(begin, offset); - close(fd); - } -#endif - if (length <= capacity) - { - memcpy(out, resolved, length); - - if (dirname_length) - { - int i; - - for (i = length - 1; i >= 0; --i) - { - if (out[i] == '/') - { - *dirname_length = i; - break; - } - } - } - } - - break; - } - } - } - - fclose(maps); - maps = NULL; - - if (length != -1) - break; - } - - return length; -} - -#elif defined(__APPLE__) - -#include -#include -#include -#include -#include -#include - -WAI_FUNCSPEC -int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) -{ - char buffer1[PATH_MAX]; - char buffer2[PATH_MAX]; - char* path = buffer1; - char* resolved = NULL; - int length = -1; - bool ok; - - for (ok = false; !ok; ok = true) - { - uint32_t size = (uint32_t)sizeof(buffer1); - if (_NSGetExecutablePath(path, &size) == -1) - { - path = (char*)WAI_MALLOC(size); - if (!_NSGetExecutablePath(path, &size)) - break; - } - - resolved = realpath(path, buffer2); - if (!resolved) - break; - - length = (int)strlen(resolved); - if (length <= capacity) - { - memcpy(out, resolved, length); - - if (dirname_length) - { - int i; - - for (i = length - 1; i >= 0; --i) - { - if (out[i] == '/') - { - *dirname_length = i; - break; - } - } - } - } - } - - if (path != buffer1) - WAI_FREE(path); - - return ok ? length : -1; -} - -WAI_NOINLINE WAI_FUNCSPEC -int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) -{ - char buffer[PATH_MAX]; - char* resolved = NULL; - int length = -1; - - for(;;) - { - Dl_info info; - - if (dladdr(WAI_RETURN_ADDRESS(), &info)) - { - resolved = realpath(info.dli_fname, buffer); - if (!resolved) - break; - - length = (int)strlen(resolved); - if (length <= capacity) - { - memcpy(out, resolved, length); - - if (dirname_length) - { - int i; - - for (i = length - 1; i >= 0; --i) - { - if (out[i] == '/') - { - *dirname_length = i; - break; - } - } - } - } - } - - break; - } - - return length; -} - -#elif defined(__QNXNTO__) - -#include -#include -#include -#include -#include -#include - -#if !defined(WAI_PROC_SELF_EXE) -#define WAI_PROC_SELF_EXE "/proc/self/exefile" -#endif - -WAI_FUNCSPEC -int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) -{ - char buffer1[PATH_MAX]; - char buffer2[PATH_MAX]; - char* resolved = NULL; - FILE* self_exe = NULL; - int length = -1; - bool ok; - - for (ok = false; !ok; ok = true) - { - self_exe = fopen(WAI_PROC_SELF_EXE, "r"); - if (!self_exe) - break; - - if (!fgets(buffer1, sizeof(buffer1), self_exe)) - break; - - resolved = realpath(buffer1, buffer2); - if (!resolved) - break; - - length = (int)strlen(resolved); - if (length <= capacity) - { - memcpy(out, resolved, length); - - if (dirname_length) - { - int i; - - for (i = length - 1; i >= 0; --i) - { - if (out[i] == '/') - { - *dirname_length = i; - break; - } - } - } - } - } - - fclose(self_exe); - - return ok ? length : -1; -} - -WAI_FUNCSPEC -int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) -{ - char buffer[PATH_MAX]; - char* resolved = NULL; - int length = -1; - - for(;;) - { - Dl_info info; - - if (dladdr(WAI_RETURN_ADDRESS(), &info)) - { - resolved = realpath(info.dli_fname, buffer); - if (!resolved) - break; - - length = (int)strlen(resolved); - if (length <= capacity) - { - memcpy(out, resolved, length); - - if (dirname_length) - { - int i; - - for (i = length - 1; i >= 0; --i) - { - if (out[i] == '/') - { - *dirname_length = i; - break; - } - } - } - } - } - - break; - } - - return length; -} - -#elif defined(__DragonFly__) || defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) - -#include -#include -#include -#include -#include -#include -#include - -#if defined(__OpenBSD__) - -#include - -WAI_FUNCSPEC -int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) -{ - char buffer1[4096]; - char buffer2[PATH_MAX]; - char buffer3[PATH_MAX]; - char** argv = (char**)buffer1; - char* resolved = NULL; - int length = -1; - bool ok; - - for (ok = false; !ok; ok = true) - { - int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; - size_t size; - - if (sysctl(mib, 4, NULL, &size, NULL, 0) != 0) - break; - - if (size > sizeof(buffer1)) - { - argv = (char**)WAI_MALLOC(size); - if (!argv) - break; - } - - if (sysctl(mib, 4, argv, &size, NULL, 0) != 0) - break; - - if (strchr(argv[0], '/')) - { - resolved = realpath(argv[0], buffer2); - if (!resolved) - break; - } - else - { - const char* PATH = getenv("PATH"); - if (!PATH) - break; - - size_t argv0_length = strlen(argv[0]); - - const char* begin = PATH; - while (1) - { - const char* separator = strchr(begin, ':'); - const char* end = separator ? separator : begin + strlen(begin); - - if (end - begin > 0) - { - if (*(end -1) == '/') - --end; - - if (((end - begin) + 1 + argv0_length + 1) <= sizeof(buffer2)) - { - memcpy(buffer2, begin, end - begin); - buffer2[end - begin] = '/'; - memcpy(buffer2 + (end - begin) + 1, argv[0], argv0_length + 1); - - resolved = realpath(buffer2, buffer3); - if (resolved) - break; - } - } - - if (!separator) - break; - - begin = ++separator; - } - - if (!resolved) - break; - } - - length = (int)strlen(resolved); - if (length <= capacity) - { - memcpy(out, resolved, length); - - if (dirname_length) - { - int i; - - for (i = length - 1; i >= 0; --i) - { - if (out[i] == '/') - { - *dirname_length = i; - break; - } - } - } - } - } - - if (argv != (char**)buffer1) - WAI_FREE(argv); - - return ok ? length : -1; -} - -#else - -WAI_FUNCSPEC -int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) -{ - char buffer1[PATH_MAX]; - char buffer2[PATH_MAX]; - char* path = buffer1; - char* resolved = NULL; - int length = -1; - bool ok; - - for (ok = false; !ok; ok = true) - { -#if defined(__NetBSD__) - int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; -#else - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; -#endif - size_t size = sizeof(buffer1); - - if (sysctl(mib, 4, path, &size, NULL, 0) != 0) - break; - - resolved = realpath(path, buffer2); - if (!resolved) - break; - - length = (int)strlen(resolved); - if (length <= capacity) - { - memcpy(out, resolved, length); - - if (dirname_length) - { - int i; - - for (i = length - 1; i >= 0; --i) - { - if (out[i] == '/') - { - *dirname_length = i; - break; - } - } - } - } - } - - return ok ? length : -1; -} - -#endif - -WAI_NOINLINE WAI_FUNCSPEC -int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) -{ - char buffer[PATH_MAX]; - char* resolved = NULL; - int length = -1; - - for(;;) - { - Dl_info info; - - if (dladdr(WAI_RETURN_ADDRESS(), &info)) - { - resolved = realpath(info.dli_fname, buffer); - if (!resolved) - break; - - length = (int)strlen(resolved); - if (length <= capacity) - { - memcpy(out, resolved, length); - - if (dirname_length) - { - int i; - - for (i = length - 1; i >= 0; --i) - { - if (out[i] == '/') - { - *dirname_length = i; - break; - } - } - } - } - } - - break; - } - - return length; -} - -#else - -#error unsupported platform - -#endif - -#ifdef __cplusplus -} -#endif diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.h deleted file mode 100644 index ca62d674cd2d1..0000000000000 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.h +++ /dev/null @@ -1,67 +0,0 @@ -// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses -// without any warranty. -// by Gregory Pakosz (@gpakosz) -// https://github.com/gpakosz/whereami - -#ifndef WHEREAMI_H -#define WHEREAMI_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef WAI_FUNCSPEC -#define WAI_FUNCSPEC -#endif -#ifndef WAI_PREFIX -#define WAI_PREFIX(function) wai_##function -#endif - -/** - * Returns the path to the current executable. - * - * Usage: - * - first call `int length = wai_getExecutablePath(NULL, 0, NULL);` to - * retrieve the length of the path - * - allocate the destination buffer with `path = (char*)malloc(length + 1);` - * - call `wai_getExecutablePath(path, length, NULL)` again to retrieve the - * path - * - add a terminal NUL character with `path[length] = '\0';` - * - * @param out destination buffer, optional - * @param capacity destination buffer capacity - * @param dirname_length optional recipient for the length of the dirname part - * of the path. - * - * @return the length of the executable path on success (without a terminal NUL - * character), otherwise `-1` - */ -WAI_FUNCSPEC -int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length); - -/** - * Returns the path to the current module - * - * Usage: - * - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve - * the length of the path - * - allocate the destination buffer with `path = (char*)malloc(length + 1);` - * - call `wai_getModulePath(path, length, NULL)` again to retrieve the path - * - add a terminal NUL character with `path[length] = '\0';` - * - * @param out destination buffer, optional - * @param capacity destination buffer capacity - * @param dirname_length optional recipient for the length of the dirname part - * of the path. - * - * @return the length of the module path on success (without a terminal NUL - * character), otherwise `-1` - */ -WAI_FUNCSPEC -int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length); - -#ifdef __cplusplus -} -#endif - -#endif // #ifndef WHEREAMI_H diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json index 519d6441bec61..88edaa56773f3 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json @@ -20,7 +20,6 @@ "protobuf", "zlib", "re2", - "spdlog", "grpc", "utf8proc", "zlib", From d401927222c6f3fc779590f693cf546c997677c3 Mon Sep 17 00:00:00 2001 From: Rafael Telles Date: Fri, 29 Jul 2022 13:08:17 -0300 Subject: [PATCH 183/183] Reapply "Implement logger interface" This reverts commit bb95d6d91f872311d1039d4211a5e1f73bb2695f: Implement logger interface - Add an interface for logger - Define Macro for each log level in the interface - Add an implementation from the logger interface - Add the spdlog dependency to the CMakeLists.txt In addition to that this commit this also: - Fixes build on Windows - Changes log strategy to be lazy, so we can log strings without impact performance if logging is disabled Change-Id: If58d9c1ee7ea11390d858bd9815e6b9b11a9bee9 --- .../flight_sql/flight_sql_connection.cc | 2 +- .../flight_sql/flight_sql_driver.cc | 69 ++ .../include/flight_sql/flight_sql_driver.h | 2 + .../odbcabstraction/CMakeLists.txt | 28 +- .../include/odbcabstraction/logger.h | 54 ++ .../include/odbcabstraction/spd_logger.h | 42 + .../include/odbcabstraction/spi/connection.h | 24 +- .../include/odbcabstraction/spi/driver.h | 3 + .../include/odbcabstraction/utils.h | 6 + .../flightsql-odbc/odbcabstraction/logger.cc | 24 + .../odbcabstraction/spd_logger.cc | 136 +++ .../flightsql-odbc/odbcabstraction/utils.cc | 52 ++ .../odbcabstraction/whereami.cc | 804 ++++++++++++++++++ .../flightsql-odbc/odbcabstraction/whereami.h | 67 ++ .../flightsql-odbc/vcpkg.json | 1 + 15 files changed, 1300 insertions(+), 14 deletions(-) create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/logger.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spd_logger.h create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/logger.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/spd_logger.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.cc create mode 100644 flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.h diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc index cfae4b34db501..d0b62888dec74 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_connection.cc @@ -114,7 +114,7 @@ inline std::string GetCerts() { #endif -const std::set BUILT_IN_PROPERTIES = { +const std::set BUILT_IN_PROPERTIES = { FlightSqlConnection::HOST, FlightSqlConnection::PORT, FlightSqlConnection::USER, diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc index 8e731d3b4414f..87d4f3a53396e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/flight_sql_driver.cc @@ -5,14 +5,41 @@ */ #include "flight_sql_connection.h" +#include "odbcabstraction/utils.h" +#include #include #include + +#define DEFAULT_MAXIMUM_FILE_SIZE 16777216 +#define CONFIG_FILE_NAME "arrow-odbc.ini" + namespace driver { namespace flight_sql { using odbcabstraction::Connection; using odbcabstraction::OdbcVersion; +using odbcabstraction::LogLevel; +using odbcabstraction::SPDLogger; + +namespace { + LogLevel ToLogLevel(int64_t level) { + switch (level) { + case 0: + return LogLevel::LogLevel_TRACE; + case 1: + return LogLevel::LogLevel_DEBUG; + case 2: + return LogLevel::LogLevel_INFO; + case 3: + return LogLevel::LogLevel_WARN; + case 4: + return LogLevel::LogLevel_ERROR; + default: + return LogLevel::LogLevel_OFF; + } + } +} FlightSqlDriver::FlightSqlDriver() : diagnostics_("Apache Arrow", "Flight SQL", OdbcVersion::V_3), @@ -31,5 +58,47 @@ odbcabstraction::Diagnostics &FlightSqlDriver::GetDiagnostics() { void FlightSqlDriver::SetVersion(std::string version) { version_ = std::move(version); } + +void FlightSqlDriver::RegisterLog() { + odbcabstraction::PropertyMap propertyMap; + driver::odbcabstraction::ReadConfigFile(propertyMap, CONFIG_FILE_NAME); + + auto log_enable_iterator = propertyMap.find(SPDLogger::LOG_ENABLED); + auto log_enabled = log_enable_iterator != propertyMap.end() ? + odbcabstraction::AsBool(log_enable_iterator->second) : false; + if (!log_enabled) { + return; + } + + auto log_path_iterator = propertyMap.find(SPDLogger::LOG_PATH); + auto log_path = + log_path_iterator != propertyMap.end() ? log_path_iterator->second : ""; + if (log_path.empty()) { + return; + } + + auto log_level_iterator = propertyMap.find(SPDLogger::LOG_LEVEL); + auto log_level = + ToLogLevel(log_level_iterator != propertyMap.end() ? std::stoi(log_level_iterator->second) : 1); + if (log_level == odbcabstraction::LogLevel_OFF) { + return; + } + + auto maximum_file_size_iterator = propertyMap.find(SPDLogger::MAXIMUM_FILE_SIZE); + auto maximum_file_size = maximum_file_size_iterator != propertyMap.end() ? + std::stoi(maximum_file_size_iterator->second) : DEFAULT_MAXIMUM_FILE_SIZE; + + auto maximum_file_quantity_iterator = propertyMap.find(SPDLogger::FILE_QUANTITY); + auto maximum_file_quantity = + maximum_file_quantity_iterator != propertyMap.end() ? std::stoi( + maximum_file_quantity_iterator->second) : 1; + + std::unique_ptr logger(new odbcabstraction::SPDLogger()); + + logger->init(maximum_file_quantity, maximum_file_size, + log_path, log_level); + odbcabstraction::Logger::SetInstance(std::move(logger)); +} + } // namespace flight_sql } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h index e55a7126c0359..98845230d98b7 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/flight_sql/include/flight_sql/flight_sql_driver.h @@ -26,6 +26,8 @@ class FlightSqlDriver : public odbcabstraction::Driver { odbcabstraction::Diagnostics &GetDiagnostics() override; void SetVersion(std::string version) override; + + void RegisterLog() override; }; }; // namespace flight_sql diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt index 0ffd493a201e7..3ebf5570990e2 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/CMakeLists.txt @@ -7,12 +7,17 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) include_directories(include) +# Ensure fmt is loaded as header only +add_compile_definitions(FMT_HEADER_ONLY) + add_library(odbcabstraction include/odbcabstraction/calendar_utils.h include/odbcabstraction/diagnostics.h include/odbcabstraction/error_codes.h include/odbcabstraction/exceptions.h + include/odbcabstraction/logger.h include/odbcabstraction/platform.h + include/odbcabstraction/spd_logger.h include/odbcabstraction/types.h include/odbcabstraction/utils.h include/odbcabstraction/odbc_impl/AttributeUtils.h @@ -32,7 +37,11 @@ add_library(odbcabstraction diagnostics.cc encoding.cc exceptions.cc + logger.cc + spd_logger.cc utils.cc + whereami.h + whereami.cc odbc_impl/ODBCConnection.cc odbc_impl/ODBCDescriptor.cc odbc_impl/ODBCEnvironment.cc @@ -45,4 +54,21 @@ set_target_properties(odbcabstraction LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib ) -target_link_libraries(odbcabstraction) + +include(FetchContent) +FetchContent_Declare( + spdlog + URL https://github.com/gabime/spdlog/archive/76fb40d95455f249bd70824ecfcae7a8f0930fa3.zip + CONFIGURE_COMMAND "" + BUILD_COMMAND "" +) +FetchContent_GetProperties(spdlog) +if(NOT spdlog_POPULATED) + FetchContent_Populate(spdlog) +endif() + +add_library(spdlog INTERFACE) +target_include_directories(spdlog INTERFACE ${spdlog_SOURCE_DIR}/include) + +add_dependencies(odbcabstraction spdlog) +target_include_directories(odbcabstraction PUBLIC ${spdlog_SOURCE_DIR}/include) diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/logger.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/logger.h new file mode 100644 index 0000000000000..b085f2bbcc26d --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/logger.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#pragma once + +#include +#include + +#include + +#define __LAZY_LOG(LEVEL, ...) do { \ + driver::odbcabstraction::Logger *logger = driver::odbcabstraction::Logger::GetInstance(); \ + if (logger) { \ + logger->log(driver::odbcabstraction::LogLevel::LogLevel_##LEVEL, [&]() { \ + return fmt::format(__VA_ARGS__); \ + }); \ + } \ +} while(0) +#define LOG_DEBUG(...) __LAZY_LOG(DEBUG, __VA_ARGS__) +#define LOG_INFO(...) __LAZY_LOG(INFO, __VA_ARGS__) +#define LOG_ERROR(...) __LAZY_LOG(ERROR, __VA_ARGS__) +#define LOG_TRACE(...) __LAZY_LOG(TRACE, __VA_ARGS__) +#define LOG_WARN(...) __LAZY_LOG(WARN, __VA_ARGS__) + +namespace driver { +namespace odbcabstraction { + +enum LogLevel { + LogLevel_TRACE, + LogLevel_DEBUG, + LogLevel_INFO, + LogLevel_WARN, + LogLevel_ERROR, + LogLevel_OFF +}; + +class Logger { +protected: + Logger() = default; + +public: + static Logger *GetInstance(); + static void SetInstance(std::unique_ptr logger); + + virtual ~Logger() = default; + + virtual void log(LogLevel level, const std::function &build_message) = 0; +}; + +} // namespace odbcabstraction +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spd_logger.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spd_logger.h new file mode 100644 index 0000000000000..dfa633edf1118 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spd_logger.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#pragma once + +#include "odbcabstraction/logger.h" + +#include +#include + +#include + +namespace driver { +namespace odbcabstraction { + +class SPDLogger : public Logger { +protected: + std::shared_ptr logger_; + +public: + static const std::string LOG_LEVEL; + static const std::string LOG_PATH; + static const std::string MAXIMUM_FILE_SIZE; + static const std::string FILE_QUANTITY; + static const std::string LOG_ENABLED; + + SPDLogger() = default; + ~SPDLogger(); + SPDLogger(SPDLogger &other) = delete; + + void operator=(const SPDLogger &) = delete; + void init(int64_t fileQuantity, int64_t maxFileSize, + const std::string &fileNamePrefix, LogLevel level); + + void log(LogLevel level, const std::function &build_message) override; +}; + +} // namespace odbcabstraction +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/connection.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/connection.h index 4c1c4bb2323a0..9fafc44d4bb41 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/connection.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/connection.h @@ -18,6 +18,17 @@ namespace driver { namespace odbcabstraction { +/// \brief Case insensitive comparator +struct CaseInsensitiveComparator + : std::binary_function { + bool operator()(const std::string &s1, const std::string &s2) const { + return boost::lexicographical_compare(s1, s2, boost::is_iless()); + } +}; + +// PropertyMap is case-insensitive for keys. +typedef std::map PropertyMap; + class Statement; /// \brief High-level representation of an ODBC connection. @@ -38,20 +49,9 @@ class Connection { PACKET_SIZE, // uint32_t - The Packet Size }; - /// \brief Case insensitive comparator - struct CaseInsensitiveComparator - : std::binary_function { - bool operator()(const std::string &s1, const std::string &s2) const { - return boost::lexicographical_compare(s1, s2, boost::is_iless()); - } - }; - typedef boost::variant Attribute; - typedef std::string Property; typedef boost::variant Info; - // ConnPropertyMap is case-insensitive for keys. - typedef std::map - ConnPropertyMap; + typedef PropertyMap ConnPropertyMap; /// \brief Establish the connection. /// \param properties[in] properties used to establish the connection. diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h index 974704f7fbf3f..e9e60b5202f10 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/spi/driver.h @@ -35,6 +35,9 @@ class Driver { /// \brief Sets the driver version. virtual void SetVersion(std::string version) = 0; + + /// \brief Register a log to be used by the system. + virtual void RegisterLog() = 0; }; } // namespace odbcabstraction diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h index a5617adac5036..138a19bf8b3fe 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/include/odbcabstraction/utils.h @@ -6,7 +6,9 @@ #pragma once +#include #include +#include #include namespace driver { @@ -36,5 +38,9 @@ boost::optional AsBool(const Connection::ConnPropertyMap& connPropertyMap, /// \exception std::out_of_range exception from \link std::stoi \endlink boost::optional AsInt32(int32_t min_value, const Connection::ConnPropertyMap& connPropertyMap, const std::string& property_name); + + +void ReadConfigFile(PropertyMap &properties, const std::string &configFileName); + } // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/logger.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/logger.cc new file mode 100644 index 0000000000000..16ac682df7aec --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/logger.cc @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + + +#include + +namespace driver { +namespace odbcabstraction { + +static std::unique_ptr odbc_logger_ = nullptr; + +Logger *Logger::GetInstance() { + return odbc_logger_.get(); +} + +void Logger::SetInstance(std::unique_ptrlogger) { + odbc_logger_ = std::move(logger); +} + +} +} diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/spd_logger.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/spd_logger.cc new file mode 100644 index 0000000000000..6151ddedd02d1 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/spd_logger.cc @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2020-2022 Dremio Corporation + * + * See "LICENSE" for license information. + */ + +#include "odbcabstraction/spd_logger.h" + +#include "odbcabstraction/logger.h" + +#include +#include +#include + +#include +#include + +namespace driver { +namespace odbcabstraction { + +const std::string SPDLogger::LOG_LEVEL = "LogLevel"; +const std::string SPDLogger::LOG_PATH= "LogPath"; +const std::string SPDLogger::MAXIMUM_FILE_SIZE= "MaximumFileSize"; +const std::string SPDLogger::FILE_QUANTITY= "FileQuantity"; +const std::string SPDLogger::LOG_ENABLED= "LogEnabled"; + +namespace { +std::function shutdown_handler; +void signal_handler(int signal) { + shutdown_handler(signal); +} + +typedef void (*Handler)(int signum); + +Handler old_sigint_handler = SIG_IGN; +Handler old_sigsegv_handler = SIG_IGN; +Handler old_sigabrt_handler = SIG_IGN; +#ifdef SIGKILL +Handler old_sigkill_handler = SIG_IGN; +#endif + +Handler GetHandlerFromSignal(int signum) { + switch (signum) { + case(SIGINT): + return old_sigint_handler; + case(SIGSEGV): + return old_sigsegv_handler; + case(SIGABRT): + return old_sigabrt_handler; +#ifdef SIGKILL + case(SIGKILL): + return old_sigkill_handler; +#endif + } +} + +void SetSignalHandler(int signum) { + Handler old = signal(signum, SIG_IGN); + if (old != SIG_IGN) { + auto old_handler = GetHandlerFromSignal(signum); + old_handler = old; + } + signal(signum, signal_handler); +} + +void ResetSignalHandler(int signum) { + Handler actual_handler = signal(signum, SIG_IGN); + if (actual_handler == signal_handler) { + signal(signum, GetHandlerFromSignal(signum)); + } +} + + +inline spdlog::level::level_enum ToSpdLogLevel(LogLevel level) { + switch (level) { + case LogLevel_TRACE: + return spdlog::level::trace; + case LogLevel_DEBUG: + return spdlog::level::debug; + case LogLevel_INFO: + return spdlog::level::info; + case LogLevel_WARN: + return spdlog::level::warn; + case LogLevel_ERROR: + return spdlog::level::err; + default: + return spdlog::level::off; + } +} +} // namespace + +void SPDLogger::init(int64_t fileQuantity, int64_t maxFileSize, + const std::string &fileNamePrefix, LogLevel level) { + logger_ = spdlog::rotating_logger_mt( + "ODBC Logger", fileNamePrefix, maxFileSize, fileQuantity); + + logger_->set_level(ToSpdLogLevel(level)); + + if (level != LogLevel::LogLevel_OFF) { + SetSignalHandler(SIGINT); + SetSignalHandler(SIGSEGV); + SetSignalHandler(SIGABRT); +#ifdef SIGKILL + SetSignalHandler(SIGKILL); +#endif + shutdown_handler = [&](int signal) { + logger_->flush(); + spdlog::shutdown(); + auto handler = GetHandlerFromSignal(signal); + handler(signal); + }; + } +} + +void SPDLogger::log(LogLevel level, const std::function &build_message) { + auto level_set = logger_->level(); + spdlog::level::level_enum spdlog_level = ToSpdLogLevel(level); + if (level_set == spdlog::level::off || level_set > spdlog_level) { + return; + } + + const std::string &message = build_message(); + logger_->log(spdlog_level, message); +} + +SPDLogger::~SPDLogger() { + ResetSignalHandler(SIGINT); + ResetSignalHandler(SIGSEGV); + ResetSignalHandler(SIGABRT); +#ifdef SIGKILL + ResetSignalHandler(SIGKILL); +#endif +} + +} // namespace odbcabstraction +} // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc index 8256cb230af40..23be030dc719e 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/utils.cc @@ -5,8 +5,15 @@ */ #include +#include "whereami.h" + +#include +#include #include +#include +#include +#include namespace driver { namespace odbcabstraction { @@ -45,5 +52,50 @@ boost::optional AsInt32(int32_t min_value, const Connection::ConnProper return boost::none; } +std::string GetModulePath() { + std::vector path; + int length, dirname_length; + length = wai_getModulePath(NULL, 0, &dirname_length); + + if (length != 0) { + path.resize(length); + wai_getModulePath(path.data(), length, &dirname_length); + } else { + throw DriverException("Could not find module path."); + } + + return std::string(path.begin(), path.begin() + dirname_length); +} + +void ReadConfigFile(PropertyMap &properties, const std::string &config_file_name) { + auto config_path = GetModulePath(); + + std::ifstream config_file; + auto config_file_path = config_path + "/" + config_file_name; + config_file.open(config_file_path); + + if (config_file.fail()) { + auto error_msg = "Arrow Flight SQL ODBC driver config file not found on \"" + config_file_path + "\""; + std::cerr << error_msg << std::endl; + + throw DriverException(error_msg); + } + + std::string temp_config; + + boost::char_separator separator("="); + while(config_file.good()) { + config_file >> temp_config; + boost::tokenizer> tokenizer(temp_config, separator); + + auto iterator = tokenizer.begin(); + + std::string key = *iterator; + std::string value = *++iterator; + + properties[key] = std::move(value); + } +} + } // namespace odbcabstraction } // namespace driver diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.cc b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.cc new file mode 100644 index 0000000000000..39324d16e2cb8 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.cc @@ -0,0 +1,804 @@ +// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses +// without any warranty. +// by Gregory Pakosz (@gpakosz) +// https://github.com/gpakosz/whereami + +// in case you want to #include "whereami.c" in a larger compilation unit +#if !defined(WHEREAMI_H) +#include "whereami.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__linux__) || defined(__CYGWIN__) +#undef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#elif defined(__APPLE__) +#undef _DARWIN_C_SOURCE +#define _DARWIN_C_SOURCE +#define _DARWIN_BETTER_REALPATH +#endif + +#if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC) +#include +#endif + +#if !defined(WAI_MALLOC) +#define WAI_MALLOC(size) malloc(size) +#endif + +#if !defined(WAI_FREE) +#define WAI_FREE(p) free(p) +#endif + +#if !defined(WAI_REALLOC) +#define WAI_REALLOC(p, size) realloc(p, size) +#endif + +#ifndef WAI_NOINLINE +#if defined(_MSC_VER) +#define WAI_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) +#define WAI_NOINLINE __attribute__((noinline)) +#else +#error unsupported compiler +#endif +#endif + +#if defined(_MSC_VER) +#define WAI_RETURN_ADDRESS() _ReturnAddress() +#elif defined(__GNUC__) +#define WAI_RETURN_ADDRESS() __builtin_extract_return_addr(__builtin_return_address(0)) +#else +#error unsupported compiler +#endif + +#if defined(_WIN32) + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#if defined(_MSC_VER) +#pragma warning(push, 3) +#endif +#include +#include +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +#include + +static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length) +{ + wchar_t buffer1[MAX_PATH]; + wchar_t buffer2[MAX_PATH]; + wchar_t* path = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + DWORD size; + int length_, length__; + + size = GetModuleFileNameW(module, buffer1, sizeof(buffer1) / sizeof(buffer1[0])); + + if (size == 0) + break; + else if (size == (DWORD)(sizeof(buffer1) / sizeof(buffer1[0]))) + { + DWORD size_ = size; + do + { + wchar_t* path_; + + path_ = (wchar_t*)WAI_REALLOC(path, sizeof(wchar_t) * size_ * 2); + if (!path_) + break; + size_ *= 2; + path = path_; + size = GetModuleFileNameW(module, path, size_); + } + while (size == size_); + + if (size == size_) + break; + } + else + path = buffer1; + + if (!_wfullpath(buffer2, path, MAX_PATH)) + break; + length_ = (int)wcslen(buffer2); + length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_ , out, capacity, NULL, NULL); + + if (length__ == 0) + length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_, NULL, 0, NULL, NULL); + if (length__ == 0) + break; + + if (length__ <= capacity && dirname_length) + { + int i; + + for (i = length__ - 1; i >= 0; --i) + { + if (out[i] == '\\') + { + *dirname_length = i; + break; + } + } + } + + length = length__; + } + + if (path != buffer1) + WAI_FREE(path); + + return ok ? length : -1; +} + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + return WAI_PREFIX(getModulePath_)(NULL, out, capacity, dirname_length); +} + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + HMODULE module; + int length = -1; + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable: 4054) +#endif + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)WAI_RETURN_ADDRESS(), &module)) +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + { + length = WAI_PREFIX(getModulePath_)(module, out, capacity, dirname_length); + } + + return length; +} + +#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) || defined(WAI_USE_PROC_SELF_EXE) + +#include +#include +#include +#if defined(__linux__) +#include +#else +#include +#endif +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#include +#include + +#if !defined(WAI_PROC_SELF_EXE) +#if defined(__sun) +#define WAI_PROC_SELF_EXE "/proc/self/path/a.out" +#else +#define WAI_PROC_SELF_EXE "/proc/self/exe" +#endif +#endif + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + resolved = realpath(WAI_PROC_SELF_EXE, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + return ok ? length : -1; +} + +#if !defined(WAI_PROC_SELF_MAPS_RETRY) +#define WAI_PROC_SELF_MAPS_RETRY 5 +#endif + +#if !defined(WAI_PROC_SELF_MAPS) +#if defined(__sun) +#define WAI_PROC_SELF_MAPS "/proc/self/map" +#else +#define WAI_PROC_SELF_MAPS "/proc/self/maps" +#endif +#endif + +#if defined(__ANDROID__) || defined(ANDROID) +#include +#include +#include +#endif +#include + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + int length = -1; + FILE* maps = NULL; + + for (int r = 0; r < WAI_PROC_SELF_MAPS_RETRY; ++r) + { + maps = fopen(WAI_PROC_SELF_MAPS, "r"); + if (!maps) + break; + + for (;;) + { + char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX]; + uint64_t low, high; + char perms[5]; + uint64_t offset; + uint32_t major, minor; + char path[PATH_MAX]; + uint32_t inode; + + if (!fgets(buffer, sizeof(buffer), maps)) + break; + + if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8) + { + uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS(); + if (low <= addr && addr <= high) + { + char* resolved; + + resolved = realpath(path, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); +#if defined(__ANDROID__) || defined(ANDROID) + if (length > 4 + &&buffer[length - 1] == 'k' + &&buffer[length - 2] == 'p' + &&buffer[length - 3] == 'a' + &&buffer[length - 4] == '.') + { + int fd = open(path, O_RDONLY); + if (fd == -1) + { + length = -1; // retry + break; + } + + char* begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0); + if (begin == MAP_FAILED) + { + close(fd); + length = -1; // retry + break; + } + + char* p = begin + offset - 30; // minimum size of local file header + while (p >= begin) // scan backwards + { + if (*((uint32_t*)p) == 0x04034b50UL) // local file header signature found + { + uint16_t length_ = *((uint16_t*)(p + 26)); + + if (length + 2 + length_ < (int)sizeof(buffer)) + { + memcpy(&buffer[length], "!/", 2); + memcpy(&buffer[length + 2], p + 30, length_); + length += 2 + length_; + } + + break; + } + + --p; + } + + munmap(begin, offset); + close(fd); + } +#endif + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + + break; + } + } + } + + fclose(maps); + maps = NULL; + + if (length != -1) + break; + } + + return length; +} + +#elif defined(__APPLE__) + +#include +#include +#include +#include +#include +#include + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* path = buffer1; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + uint32_t size = (uint32_t)sizeof(buffer1); + if (_NSGetExecutablePath(path, &size) == -1) + { + path = (char*)WAI_MALLOC(size); + if (!_NSGetExecutablePath(path, &size)) + break; + } + + resolved = realpath(path, buffer2); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + if (path != buffer1) + WAI_FREE(path); + + return ok ? length : -1; +} + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + break; + } + + return length; +} + +#elif defined(__QNXNTO__) + +#include +#include +#include +#include +#include +#include + +#if !defined(WAI_PROC_SELF_EXE) +#define WAI_PROC_SELF_EXE "/proc/self/exefile" +#endif + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* resolved = NULL; + FILE* self_exe = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + self_exe = fopen(WAI_PROC_SELF_EXE, "r"); + if (!self_exe) + break; + + if (!fgets(buffer1, sizeof(buffer1), self_exe)) + break; + + resolved = realpath(buffer1, buffer2); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + fclose(self_exe); + + return ok ? length : -1; +} + +WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + break; + } + + return length; +} + +#elif defined(__DragonFly__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) + +#include +#include +#include +#include +#include +#include +#include + +#if defined(__OpenBSD__) + +#include + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[4096]; + char buffer2[PATH_MAX]; + char buffer3[PATH_MAX]; + char** argv = (char**)buffer1; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; + size_t size; + + if (sysctl(mib, 4, NULL, &size, NULL, 0) != 0) + break; + + if (size > sizeof(buffer1)) + { + argv = (char**)WAI_MALLOC(size); + if (!argv) + break; + } + + if (sysctl(mib, 4, argv, &size, NULL, 0) != 0) + break; + + if (strchr(argv[0], '/')) + { + resolved = realpath(argv[0], buffer2); + if (!resolved) + break; + } + else + { + const char* PATH = getenv("PATH"); + if (!PATH) + break; + + size_t argv0_length = strlen(argv[0]); + + const char* begin = PATH; + while (1) + { + const char* separator = strchr(begin, ':'); + const char* end = separator ? separator : begin + strlen(begin); + + if (end - begin > 0) + { + if (*(end -1) == '/') + --end; + + if (((end - begin) + 1 + argv0_length + 1) <= sizeof(buffer2)) + { + memcpy(buffer2, begin, end - begin); + buffer2[end - begin] = '/'; + memcpy(buffer2 + (end - begin) + 1, argv[0], argv0_length + 1); + + resolved = realpath(buffer2, buffer3); + if (resolved) + break; + } + } + + if (!separator) + break; + + begin = ++separator; + } + + if (!resolved) + break; + } + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + if (argv != (char**)buffer1) + WAI_FREE(argv); + + return ok ? length : -1; +} + +#else + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* path = buffer1; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { +#if defined(__NetBSD__) + int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; +#else + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; +#endif + size_t size = sizeof(buffer1); + + if (sysctl(mib, 4, path, &size, NULL, 0) != 0) + break; + + resolved = realpath(path, buffer2); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + return ok ? length : -1; +} + +#endif + +WAI_NOINLINE WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + break; + } + + return length; +} + +#else + +#error unsupported platform + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.h b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.h new file mode 100644 index 0000000000000..ca62d674cd2d1 --- /dev/null +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/odbcabstraction/whereami.h @@ -0,0 +1,67 @@ +// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses +// without any warranty. +// by Gregory Pakosz (@gpakosz) +// https://github.com/gpakosz/whereami + +#ifndef WHEREAMI_H +#define WHEREAMI_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef WAI_FUNCSPEC +#define WAI_FUNCSPEC +#endif +#ifndef WAI_PREFIX +#define WAI_PREFIX(function) wai_##function +#endif + +/** + * Returns the path to the current executable. + * + * Usage: + * - first call `int length = wai_getExecutablePath(NULL, 0, NULL);` to + * retrieve the length of the path + * - allocate the destination buffer with `path = (char*)malloc(length + 1);` + * - call `wai_getExecutablePath(path, length, NULL)` again to retrieve the + * path + * - add a terminal NUL character with `path[length] = '\0';` + * + * @param out destination buffer, optional + * @param capacity destination buffer capacity + * @param dirname_length optional recipient for the length of the dirname part + * of the path. + * + * @return the length of the executable path on success (without a terminal NUL + * character), otherwise `-1` + */ +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length); + +/** + * Returns the path to the current module + * + * Usage: + * - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve + * the length of the path + * - allocate the destination buffer with `path = (char*)malloc(length + 1);` + * - call `wai_getModulePath(path, length, NULL)` again to retrieve the path + * - add a terminal NUL character with `path[length] = '\0';` + * + * @param out destination buffer, optional + * @param capacity destination buffer capacity + * @param dirname_length optional recipient for the length of the dirname part + * of the path. + * + * @return the length of the module path on success (without a terminal NUL + * character), otherwise `-1` + */ +WAI_FUNCSPEC +int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length); + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef WHEREAMI_H diff --git a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json index 88edaa56773f3..519d6441bec61 100644 --- a/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json +++ b/flightsql-odbc/flightsql-odbc/flightsql-odbc-clone/flightsql-odbc/vcpkg.json @@ -20,6 +20,7 @@ "protobuf", "zlib", "re2", + "spdlog", "grpc", "utf8proc", "zlib",