diff --git a/cpp/src/arrow/flight/sql/odbc/entry_points.cc b/cpp/src/arrow/flight/sql/odbc/entry_points.cc index 5debc8c7985..0f1947fefd5 100644 --- a/cpp/src/arrow/flight/sql/odbc/entry_points.cc +++ b/cpp/src/arrow/flight/sql/odbc/entry_points.cc @@ -27,21 +27,66 @@ #include "arrow/flight/sql/odbc/odbc_api.h" #include "arrow/flight/sql/odbc/visibility.h" -SQLRETURN SQL_API SQLAllocHandle(SQLSMALLINT type, SQLHANDLE parent, - SQLHANDLE* result) { - return arrow::SQLAllocHandle(type, parent, result); +SQLRETURN SQL_API SQLAllocHandle(SQLSMALLINT type, SQLHANDLE parent, SQLHANDLE* result) { + + switch (type) { + case SQL_HANDLE_ENV: { + return arrow::SQLAllocEnv(result); + } + + case SQL_HANDLE_DBC: { + return arrow::SQLAllocConnect(parent, result); + } + + case SQL_HANDLE_STMT: { + return SQL_INVALID_HANDLE; + } + + default: { + return SQL_ERROR; + } + } } SQLRETURN SQL_API SQLAllocEnv(SQLHENV* env) { - return arrow::SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, env); + return arrow::SQLAllocEnv(env); +} + +SQLRETURN SQL_API SQLAllocConnect(SQLHENV env, SQLHDBC* conn) { + return arrow::SQLAllocConnect(env, conn); +} + +SQLRETURN SQL_API SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle) { + + switch (type) { + case SQL_HANDLE_ENV: { + return arrow::SQLFreeEnv(handle); + } + + case SQL_HANDLE_DBC: { + return arrow::SQLFreeConnect(handle); + } + + case SQL_HANDLE_STMT: { + return SQL_INVALID_HANDLE; + } + + case SQL_HANDLE_DESC: { + return SQL_INVALID_HANDLE; + } + + default: { + return SQL_ERROR; + } + } } SQLRETURN SQL_API SQLFreeEnv(SQLHENV env) { - return arrow::SQLFreeHandle(SQL_HANDLE_ENV, env); + return arrow::SQLFreeEnv(env); } -SQLRETURN SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle) { - return arrow::SQLFreeHandle(type, handle); +SQLRETURN SQL_API SQLFreeConnect(SQLHDBC conn) { + return arrow::SQLFreeConnect(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..916119e6d79 100644 --- a/cpp/src/arrow/flight/sql/odbc/odbc_api.cc +++ b/cpp/src/arrow/flight/sql/odbc/odbc_api.cc @@ -17,6 +17,7 @@ #include +#include #include // odbc_api includes windows.h, which needs to be put behind winsock2.h. @@ -25,71 +26,70 @@ namespace arrow { - SQLRETURN SQLAllocHandle(SQLSMALLINT type, SQLHANDLE parent, SQLHANDLE* result) { - // TODO: implement SQLAllocHandle by linking to `odbc_impl` - *result = 0; + SQLRETURN SQLAllocEnv(SQLHENV* env) { + using driver::flight_sql::FlightSqlDriver; + using ODBC::ODBCEnvironment; - switch (type) - { - case SQL_HANDLE_ENV: { - using ODBC::ODBCEnvironment; - using driver::flight_sql::FlightSqlDriver; + *env = SQL_NULL_HENV; - std::shared_ptr odbc_driver = std::make_shared(); - *result = reinterpret_cast(new ODBCEnvironment(odbc_driver)); + std::shared_ptr odbc_driver = std::make_shared(); + *env = reinterpret_cast(new ODBCEnvironment(odbc_driver)); - return SQL_SUCCESS; - } + return SQL_SUCCESS; + } + + SQLRETURN SQLAllocConnect(SQLHENV env, SQLHDBC* conn) { + using ODBC::ODBCConnection; + using ODBC::ODBCEnvironment; - case SQL_HANDLE_DBC: { - return SQL_INVALID_HANDLE; - } + *conn = SQL_NULL_HDBC; - case SQL_HANDLE_STMT: { - return SQL_INVALID_HANDLE; - } + ODBCEnvironment* environment = reinterpret_cast(env); - default: - break; + if (!environment) { + return SQL_INVALID_HANDLE; } - return SQL_ERROR; - } + std::shared_ptr connection = environment->CreateConnection(); + + if (!connection) { + return environment->GetDiagnostics().GetNativeError(0); + } + + *connection = reinterpret_cast(&connection); - SQLRETURN SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle) - { - switch (type) { - case SQL_HANDLE_ENV: { - using ODBC::ODBCEnvironment; + return SQL_SUCCESS; + } - ODBCEnvironment* environment = reinterpret_cast(handle); + SQLRETURN SQLFreeEnv(SQLHENV env) { + using ODBC::ODBCEnvironment; - if (!environment) { - return SQL_INVALID_HANDLE; - } + ODBCEnvironment* environment = reinterpret_cast(env); - delete environment; + if (!environment) { + return SQL_INVALID_HANDLE; + } - return SQL_SUCCESS; - } + delete environment; - case SQL_HANDLE_DBC: - return SQL_INVALID_HANDLE; + return SQL_SUCCESS; + } - case SQL_HANDLE_STMT: - return SQL_INVALID_HANDLE; + SQLRETURN SQLFreeConnect(SQLHDBC conn) { + using ODBC::ODBCConnection; - case SQL_HANDLE_DESC: - return SQL_INVALID_HANDLE; + ODBCConnection* odbc_conn = reinterpret_cast(conn); - default: - break; + if (!odbc_conn) { + return SQL_INVALID_HANDLE; } - return SQL_ERROR; - } - + // TODO: Fix Pointer or Reference to an incomplete type + // odbc_connection->releaseConnection(); + delete odbc_conn; + return SQL_SUCCESS; + } } // 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..68876f72b9e 100644 --- a/cpp/src/arrow/flight/sql/odbc/odbc_api.h +++ b/cpp/src/arrow/flight/sql/odbc/odbc_api.h @@ -32,7 +32,7 @@ namespace arrow { SQLRETURN SQLAllocEnv(SQLHENV* env); - SQLRETURN SQLAllocHandle(SQLSMALLINT type, SQLHANDLE parent, SQLHANDLE* result); + SQLRETURN SQLAllocConnect(SQLHENV env, SQLHDBC* conn); SQLRETURN SQLFreeEnv(SQLHENV env); - SQLRETURN SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle); - } //arrow + SQLRETURN SQLFreeConnect(SQLHDBC conn); +} // 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