diff --git a/cpp/src/arrow/flight/sql/odbc/entry_points.cc b/cpp/src/arrow/flight/sql/odbc/entry_points.cc index 5debc8c7985..83244222ab6 100644 --- a/cpp/src/arrow/flight/sql/odbc/entry_points.cc +++ b/cpp/src/arrow/flight/sql/odbc/entry_points.cc @@ -36,12 +36,20 @@ SQLRETURN SQL_API SQLAllocEnv(SQLHENV* env) { return arrow::SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, env); } +SQLRETURN SQL_API SQLAllocConnect(SQLHENV env, SQLHDBC* conn) { + return arrow::SQLAllocHandle(SQL_HANDLE_DBC, env, conn); +} + +SQLRETURN SQL_API SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle) { + return arrow::SQLFreeHandle(type, handle); +} + 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 SQLFreeConnect(SQLHDBC conn) { + return arrow::SQLFreeHandle(SQL_HANDLE_DBC, conn); } SQLRETURN SQL_API SQLDriverConnect(SQLHDBC conn, SQLHWND windowHandle, diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_api.cc b/cpp/src/arrow/flight/sql/odbc/odbc_api.cc index ea00c46caf6..f0075c07e83 100644 --- a/cpp/src/arrow/flight/sql/odbc/odbc_api.cc +++ b/cpp/src/arrow/flight/sql/odbc/odbc_api.cc @@ -17,6 +17,8 @@ #include +#include +#include #include // odbc_api includes windows.h, which needs to be put behind winsock2.h. @@ -34,15 +36,36 @@ namespace arrow 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)); + + static FlightSqlDriver* odbc_driver = new FlightSqlDriver(); + static std::shared_ptr driver_ptr = + std::make_shared(odbc_driver); + *result = reinterpret_cast(new ODBCEnvironment(driver_ptr)); return SQL_SUCCESS; } case SQL_HANDLE_DBC: { - return SQL_INVALID_HANDLE; + using ODBC::ODBCConnection; + using ODBC::ODBCEnvironment; + + *result = SQL_NULL_HDBC; + + ODBCEnvironment* environment = reinterpret_cast(parent); + + if (!environment) { + return SQL_INVALID_HANDLE; + } + + std::shared_ptr conn = environment->CreateConnection(); + + if (!conn) { + return SQL_INVALID_HANDLE; + } + + *result = reinterpret_cast(conn.get()); + + return SQL_SUCCESS; } case SQL_HANDLE_STMT: { @@ -73,8 +96,19 @@ namespace arrow return SQL_SUCCESS; } - case SQL_HANDLE_DBC: - return SQL_INVALID_HANDLE; + case SQL_HANDLE_DBC: { + using ODBC::ODBCConnection; + + ODBCConnection* conn = reinterpret_cast(handle); + + if (!conn) { + return SQL_INVALID_HANDLE; + } + + conn->releaseConnection(); + + return SQL_SUCCESS; + } case SQL_HANDLE_STMT: return SQL_INVALID_HANDLE; @@ -89,7 +123,4 @@ namespace arrow return SQL_ERROR; } - - - } // 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 75bf4aa0ca0..d8a581659b3 100644 --- a/cpp/src/arrow/flight/sql/odbc/odbc_api.h +++ b/cpp/src/arrow/flight/sql/odbc/odbc_api.h @@ -31,8 +31,6 @@ namespace arrow { - SQLRETURN SQLAllocEnv(SQLHENV* env); SQLRETURN SQLAllocHandle(SQLSMALLINT type, SQLHANDLE parent, SQLHANDLE* result); - SQLRETURN SQLFreeEnv(SQLHENV env); SQLRETURN SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle); - } //arrow +} // namespace arrow 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 9e6dd03f0f7..bbb3c0a4167 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/connection_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/connection_test.cc @@ -51,7 +51,42 @@ TEST(SQLAllocEnv, TestSQLAllocEnv) { EXPECT_TRUE(return_value == SQL_SUCCESS); } +TEST(SQLAllocHandle, TestSQLAllocHandleConnect) { + + // ODBC Environment + SQLHENV env; + SQLHDBC conn; + + // Allocate an environment handle + SQLRETURN return_value = SQLAllocEnv(&env); + + EXPECT_TRUE(return_value == SQL_SUCCESS); + + // Allocate a connection using alloc handle + SQLRETURN return_alloc_handle = SQLAllocHandle(SQL_HANDLE_DBC, env, &conn); + + EXPECT_TRUE(return_alloc_handle == SQL_SUCCESS); +} + +TEST(SQLAllocConnect, TestSQLAllocHandleConnect) { + + // ODBC Environment + SQLHENV env; + SQLHDBC conn; + + // Allocate an environment handle + SQLRETURN return_value = SQLAllocEnv(&env); + + EXPECT_TRUE(return_value == SQL_SUCCESS); + + // Allocate a connection using alloc handle + SQLRETURN return_alloc_connect = SQLAllocConnect(env, &conn); + + EXPECT_TRUE(return_alloc_connect == SQL_SUCCESS); +} + TEST(SQLFreeHandle, TestSQLFreeHandleEnv) { + // ODBC Environment SQLHENV env; @@ -65,6 +100,7 @@ TEST(SQLFreeHandle, TestSQLFreeHandleEnv) { } TEST(SQLFreeEnv, TestSQLFreeEnv) { + // ODBC Environment SQLHENV env; @@ -77,6 +113,50 @@ TEST(SQLFreeEnv, TestSQLFreeEnv) { EXPECT_TRUE(return_value == SQL_SUCCESS); } +TEST(SQLFreeHandle, TestSQLFreeHandleConnect) { + + // ODBC Environment + SQLHENV env; + SQLHDBC conn; + + // Allocate an environment handle + SQLRETURN return_value = SQLAllocEnv(&env); + + EXPECT_TRUE(return_value == SQL_SUCCESS); + + // Allocate a connection using alloc handle + SQLRETURN return_alloc_handle = SQLAllocHandle(SQL_HANDLE_DBC, env, &conn); + + EXPECT_TRUE(return_alloc_handle == SQL_SUCCESS); + + // Free the created connection using free handle + SQLRETURN return_free_handle = SQLFreeHandle(SQL_HANDLE_DBC, conn); + + EXPECT_TRUE(return_free_handle == SQL_SUCCESS); +} + +TEST(SQLFreeConnect, TestSQLFreeConnect) { + + // ODBC Environment + SQLHENV env; + SQLHDBC conn; + + // Allocate an environment handle + SQLRETURN return_env = SQLAllocEnv(&env); + + EXPECT_TRUE(return_env == SQL_SUCCESS); + + // Allocate a connection using alloc handle + SQLRETURN return_alloc_handle = SQLAllocHandle(SQL_HANDLE_DBC, env, &conn); + + EXPECT_TRUE(return_alloc_handle == SQL_SUCCESS); + + // Free the created connection using free connect + SQLRETURN return_free_connect = SQLFreeConnect(conn); + + EXPECT_TRUE(return_free_connect == SQL_SUCCESS); +} + } // namespace integration_tests } // namespace odbc } // namespace flight