diff --git a/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt b/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt index 81b4dd78cc6..ba2df5f9e55 100644 --- a/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt @@ -54,7 +54,7 @@ add_arrow_lib(arrow_flight_sql_odbc SHARED_INSTALL_INTERFACE_LIBS ArrowFlight::arrow_flight_sql_shared STATIC_LINK_LIBS arrow_flight_sql_static STATIC_INSTALL_INTERFACE_LIBS ArrowFlight::arrow_flight_sql_static - SHARED_PRIVATE_LINK_LIBS ODBC::ODBC) + SHARED_PRIVATE_LINK_LIBS ODBC::ODBC odbcabstraction arrow_odbc_spi_impl) foreach(LIB_TARGET ${ARROW_FLIGHT_SQL_ODBC_LIBRARIES}) target_compile_definitions(${LIB_TARGET} PRIVATE ARROW_FLIGHT_SQL_ODBC_EXPORTING) diff --git a/cpp/src/arrow/flight/sql/odbc/entry_points.cc b/cpp/src/arrow/flight/sql/odbc/entry_points.cc index e964fc586e3..5debc8c7985 100644 --- a/cpp/src/arrow/flight/sql/odbc/entry_points.cc +++ b/cpp/src/arrow/flight/sql/odbc/entry_points.cc @@ -36,6 +36,14 @@ SQLRETURN SQL_API SQLAllocEnv(SQLHENV* env) { return arrow::SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, env); } +SQLRETURN SQL_API SQLFreeEnv(SQLHENV env) { + return arrow::SQLFreeHandle(SQL_HANDLE_ENV, env); +} + +SQLRETURN SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle) { + return arrow::SQLFreeHandle(type, handle); +} + SQLRETURN SQL_API SQLDriverConnect(SQLHDBC conn, SQLHWND windowHandle, SQLWCHAR* inConnectionString, SQLSMALLINT inConnectionStringLen, diff --git a/cpp/src/arrow/flight/sql/odbc/flight_sql/CMakeLists.txt b/cpp/src/arrow/flight/sql/odbc/flight_sql/CMakeLists.txt index 7cfc51e78f3..9bd45d58f38 100644 --- a/cpp/src/arrow/flight/sql/odbc/flight_sql/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/odbc/flight_sql/CMakeLists.txt @@ -123,8 +123,7 @@ target_include_directories(arrow_odbc_spi_impl PUBLIC ${CMAKE_CURRENT_LIST_DIR}) find_package(ArrowFlightSql) -target_link_libraries(arrow_odbc_spi_impl PUBLIC odbcabstraction - arrow_flight_sql_static) +target_link_libraries(arrow_odbc_spi_impl PUBLIC odbcabstraction arrow_flight_sql_shared) if(MSVC) set(CMAKE_CXX_FLAGS_RELEASE "/MD") diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_api.cc b/cpp/src/arrow/flight/sql/odbc/odbc_api.cc index 6dfcc1493ab..ea00c46caf6 100644 --- a/cpp/src/arrow/flight/sql/odbc/odbc_api.cc +++ b/cpp/src/arrow/flight/sql/odbc/odbc_api.cc @@ -16,11 +16,12 @@ // under the License. -#include "arrow/flight/sql/odbc/odbcabstraction/include/odbcabstraction/odbc_impl/odbc_environment.h" +#include +#include // odbc_api includes windows.h, which needs to be put behind winsock2.h. // odbc_environment.h includes winsock2.h -#include "arrow/flight/sql/odbc/odbc_api.h" +#include namespace arrow { @@ -30,14 +31,47 @@ namespace arrow switch (type) { - case SQL_HANDLE_ENV: - - // TODO: uncomment below code after flightsqlodbc is fixed - // using ODBCEnvironment; - // *result = reinterpret_cast< SQLHENV >(new ODBCEnvironment()); - - // return SQL_SUCCESS + case SQL_HANDLE_ENV: { + using ODBC::ODBCEnvironment; + using driver::flight_sql::FlightSqlDriver; + + std::shared_ptr odbc_driver = std::make_shared(); + *result = reinterpret_cast(new ODBCEnvironment(odbc_driver)); + + return SQL_SUCCESS; + } + + case SQL_HANDLE_DBC: { return SQL_INVALID_HANDLE; + } + + case SQL_HANDLE_STMT: { + return SQL_INVALID_HANDLE; + } + + default: + break; + } + + return SQL_ERROR; + } + + SQLRETURN SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle) + { + switch (type) { + case SQL_HANDLE_ENV: { + using ODBC::ODBCEnvironment; + + ODBCEnvironment* environment = reinterpret_cast(handle); + + if (!environment) { + return SQL_INVALID_HANDLE; + } + + delete environment; + + return SQL_SUCCESS; + } case SQL_HANDLE_DBC: return SQL_INVALID_HANDLE; @@ -45,10 +79,17 @@ namespace arrow case SQL_HANDLE_STMT: return SQL_INVALID_HANDLE; + case SQL_HANDLE_DESC: + return SQL_INVALID_HANDLE; + default: break; } return SQL_ERROR; } -} // namespace arrow + + + + + } // namespace arrow diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_api.h b/cpp/src/arrow/flight/sql/odbc/odbc_api.h index 5aaeb81a976..75bf4aa0ca0 100644 --- a/cpp/src/arrow/flight/sql/odbc/odbc_api.h +++ b/cpp/src/arrow/flight/sql/odbc/odbc_api.h @@ -31,5 +31,8 @@ namespace arrow { + SQLRETURN SQLAllocEnv(SQLHENV* env); SQLRETURN SQLAllocHandle(SQLSMALLINT type, SQLHANDLE parent, SQLHANDLE* result); -} //arrow + SQLRETURN SQLFreeEnv(SQLHENV env); + SQLRETURN SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle); + } //arrow diff --git a/cpp/src/arrow/flight/sql/odbc/odbcabstraction/odbc_impl/odbc_connection.cc b/cpp/src/arrow/flight/sql/odbc/odbcabstraction/odbc_impl/odbc_connection.cc index 419d7d3b6db..c589c8d8ab5 100644 --- a/cpp/src/arrow/flight/sql/odbc/odbcabstraction/odbc_impl/odbc_connection.cc +++ b/cpp/src/arrow/flight/sql/odbc/odbcabstraction/odbc_impl/odbc_connection.cc @@ -52,10 +52,13 @@ const boost::xpressive::sregex CONNECTION_STR_REGEX( // entries in the properties. void loadPropertiesFromDSN(const std::string& dsn, Connection::ConnPropertyMap& properties) { + // TODO - fix build errors with configuration window + /* 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"); @@ -81,14 +84,17 @@ void loadPropertiesFromDSN(const std::string& dsn, 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))); } } + */ } } // namespace diff --git a/cpp/src/arrow/flight/sql/odbc/tests/connection_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/connection_test.cc index 88a0e1680dc..9e6dd03f0f7 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/connection_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/connection_test.cc @@ -29,7 +29,7 @@ namespace flight { namespace odbc { namespace integration_tests { -TEST(connection_test, TestSQLAllocHandle) { +TEST(SQLAllocHandle, TestSQLAllocHandleEnv) { // ODBC Environment SQLHENV env; @@ -40,6 +40,43 @@ TEST(connection_test, TestSQLAllocHandle) { EXPECT_TRUE(env != NULL); } +TEST(SQLAllocEnv, TestSQLAllocEnv) { + + // ODBC Environment + SQLHENV env; + + // Allocate an environment handle + SQLRETURN return_value = SQLAllocEnv(&env); + + EXPECT_TRUE(return_value == SQL_SUCCESS); +} + +TEST(SQLFreeHandle, TestSQLFreeHandleEnv) { + // ODBC Environment + SQLHENV env; + + // Allocate an environment handle + SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); + + // Free an environment handle + SQLRETURN return_value = SQLFreeHandle(SQL_HANDLE_ENV, env); + + EXPECT_TRUE(return_value == SQL_SUCCESS); +} + +TEST(SQLFreeEnv, TestSQLFreeEnv) { + // ODBC Environment + SQLHENV env; + + // Allocate an environment handle + SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); + + // Free an environment handle + SQLRETURN return_value = SQLFreeEnv(env); + + EXPECT_TRUE(return_value == SQL_SUCCESS); +} + } // namespace integration_tests } // namespace odbc } // namespace flight