Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions cpp/src/arrow/flight/sql/odbc/odbc_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -617,8 +617,7 @@ SQLRETURN SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER valuePtr,
return SQL_SUCCESS;
}

case SQL_ATTR_CONNECTION_POOLING:
case SQL_ATTR_APP_ROW_DESC: {
case SQL_ATTR_CONNECTION_POOLING: {
throw DriverException("Optional feature not supported.", "HYC00");
}

Expand Down Expand Up @@ -669,8 +668,7 @@ SQLRETURN SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER valuePtr,
}
}

case SQL_ATTR_CONNECTION_POOLING:
case SQL_ATTR_APP_ROW_DESC: {
case SQL_ATTR_CONNECTION_POOLING: {
throw DriverException("Optional feature not supported.", "HYC00");
}

Expand Down
1 change: 1 addition & 0 deletions cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ add_arrow_test(flight_sql_odbc_test
columns_test.cc
connection_attr_test.cc
connection_info_test.cc
errors_test.cc
statement_attr_test.cc
statement_test.cc
tables_test.cc
Expand Down
262 changes: 18 additions & 244 deletions cpp/src/arrow/flight/sql/odbc/tests/connection_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,24 @@ TEST(SQLFreeHandle, TestSQLFreeHandleConnect) {
EXPECT_TRUE(return_free_handle == SQL_SUCCESS);
}

TYPED_TEST(FlightSQLODBCTestBase, TestFreeNullHandles) {
// Verifies attempt to free invalid handle does not cause segfault
// Attempt to free null statement handle
SQLRETURN ret = SQLFreeHandle(SQL_HANDLE_STMT, this->stmt);

EXPECT_EQ(ret, SQL_INVALID_HANDLE);

// Attempt to free null connection handle
ret = SQLFreeHandle(SQL_HANDLE_DBC, this->conn);

EXPECT_EQ(ret, SQL_INVALID_HANDLE);

// Attempt to free null environment handle
ret = SQLFreeHandle(SQL_HANDLE_ENV, this->env);

EXPECT_EQ(ret, SQL_INVALID_HANDLE);
}

TEST(SQLFreeConnect, TestSQLFreeConnect) {
// ODBC Environment
SQLHENV env;
Expand Down Expand Up @@ -811,250 +829,6 @@ TEST(SQLDisconnect, TestSQLDisconnectWithoutConnection) {
EXPECT_EQ(ret, SQL_SUCCESS);
}

TYPED_TEST(FlightSQLODBCTestBase, TestSQLGetDiagFieldWForConnectFailure) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved these tests to errors_test.cc

// ODBC Environment
SQLHENV env;
SQLHDBC conn;

// Allocate an environment handle
SQLRETURN ret = SQLAllocEnv(&env);

EXPECT_EQ(ret, SQL_SUCCESS);

ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);

EXPECT_EQ(ret, SQL_SUCCESS);

// Allocate a connection using alloc handle
ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);

EXPECT_EQ(ret, SQL_SUCCESS);

// Invalid connect string
std::string connect_str = this->getInvalidConnectionString();

ASSERT_OK_AND_ASSIGN(std::wstring wconnect_str,
arrow::util::UTF8ToWideString(connect_str));
std::vector<SQLWCHAR> connect_str0(wconnect_str.begin(), wconnect_str.end());

SQLWCHAR outstr[ODBC_BUFFER_SIZE];
SQLSMALLINT outstrlen;

// Connecting to ODBC server.
ret = SQLDriverConnect(conn, NULL, &connect_str0[0],
static_cast<SQLSMALLINT>(connect_str0.size()), outstr,
ODBC_BUFFER_SIZE, &outstrlen, SQL_DRIVER_NOPROMPT);

EXPECT_TRUE(ret == SQL_ERROR);

// Retrieve all supported header level and record level data
SQLSMALLINT HEADER_LEVEL = 0;
SQLSMALLINT RECORD_1 = 1;

// SQL_DIAG_NUMBER
SQLINTEGER diag_number;
SQLSMALLINT diag_number_length;

ret = SQLGetDiagField(SQL_HANDLE_DBC, conn, HEADER_LEVEL, SQL_DIAG_NUMBER, &diag_number,
sizeof(SQLINTEGER), &diag_number_length);

EXPECT_EQ(ret, SQL_SUCCESS);

EXPECT_EQ(diag_number, 1);

// SQL_DIAG_SERVER_NAME
SQLWCHAR server_name[ODBC_BUFFER_SIZE];
SQLSMALLINT server_name_length;

ret = SQLGetDiagField(SQL_HANDLE_DBC, conn, RECORD_1, SQL_DIAG_SERVER_NAME, server_name,
ODBC_BUFFER_SIZE, &server_name_length);

EXPECT_EQ(ret, SQL_SUCCESS);

// SQL_DIAG_MESSAGE_TEXT
SQLWCHAR message_text[ODBC_BUFFER_SIZE];
SQLSMALLINT message_text_length;

ret = SQLGetDiagField(SQL_HANDLE_DBC, conn, RECORD_1, SQL_DIAG_MESSAGE_TEXT,
message_text, ODBC_BUFFER_SIZE, &message_text_length);

EXPECT_EQ(ret, SQL_SUCCESS);

EXPECT_GT(message_text_length, 100);

// SQL_DIAG_NATIVE
SQLINTEGER diag_native;
SQLSMALLINT diag_native_length;

ret = SQLGetDiagField(SQL_HANDLE_DBC, conn, RECORD_1, SQL_DIAG_NATIVE, &diag_native,
sizeof(diag_native), &diag_native_length);

EXPECT_EQ(ret, SQL_SUCCESS);

EXPECT_EQ(diag_native, 200);

// SQL_DIAG_SQLSTATE
const SQLSMALLINT sql_state_size = 6;
SQLWCHAR sql_state[sql_state_size];
SQLSMALLINT sql_state_length;
ret = SQLGetDiagField(SQL_HANDLE_DBC, conn, RECORD_1, SQL_DIAG_SQLSTATE, sql_state,
sql_state_size * driver::odbcabstraction::GetSqlWCharSize(),
&sql_state_length);

EXPECT_EQ(ret, SQL_SUCCESS);

// 28000
EXPECT_EQ(sql_state[0], '2');
EXPECT_EQ(sql_state[1], '8');
EXPECT_EQ(sql_state[2], '0');
EXPECT_EQ(sql_state[3], '0');
EXPECT_EQ(sql_state[4], '0');

// Free connection handle
ret = SQLFreeHandle(SQL_HANDLE_DBC, conn);

EXPECT_EQ(ret, SQL_SUCCESS);

// Free environment handle
ret = SQLFreeHandle(SQL_HANDLE_ENV, env);

EXPECT_EQ(ret, SQL_SUCCESS);
}

TYPED_TEST(FlightSQLODBCTestBase, TestSQLGetDiagFieldWForConnectFailureNTS) {
// Test is disabled because driver manager on Windows does not pass through SQL_NTS
// This test case can be potentially used on macOS/Linux
GTEST_SKIP();
// ODBC Environment
SQLHENV env;
SQLHDBC conn;

// Allocate an environment handle
SQLRETURN ret = SQLAllocEnv(&env);

EXPECT_EQ(ret, SQL_SUCCESS);

ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);

EXPECT_EQ(ret, SQL_SUCCESS);

// Allocate a connection using alloc handle
ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);

EXPECT_EQ(ret, SQL_SUCCESS);

// Invalid connect string
std::string connect_str = this->getInvalidConnectionString();

ASSERT_OK_AND_ASSIGN(std::wstring wconnect_str,
arrow::util::UTF8ToWideString(connect_str));
std::vector<SQLWCHAR> connect_str0(wconnect_str.begin(), wconnect_str.end());

SQLWCHAR outstr[ODBC_BUFFER_SIZE];
SQLSMALLINT outstrlen;

// Connecting to ODBC server.
ret = SQLDriverConnect(conn, NULL, &connect_str0[0],
static_cast<SQLSMALLINT>(connect_str0.size()), outstr,
ODBC_BUFFER_SIZE, &outstrlen, SQL_DRIVER_NOPROMPT);

EXPECT_TRUE(ret == SQL_ERROR);

// Retrieve all supported header level and record level data
SQLSMALLINT RECORD_1 = 1;

// SQL_DIAG_MESSAGE_TEXT SQL_NTS
SQLWCHAR message_text[ODBC_BUFFER_SIZE];
SQLSMALLINT message_text_length;

message_text[ODBC_BUFFER_SIZE - 1] = '\0';

ret = SQLGetDiagField(SQL_HANDLE_DBC, conn, RECORD_1, SQL_DIAG_MESSAGE_TEXT,
message_text, SQL_NTS, &message_text_length);

EXPECT_EQ(ret, SQL_SUCCESS);

EXPECT_GT(message_text_length, 100);

// Free connection handle
ret = SQLFreeHandle(SQL_HANDLE_DBC, conn);

EXPECT_EQ(ret, SQL_SUCCESS);

// Free environment handle
ret = SQLFreeHandle(SQL_HANDLE_ENV, env);

EXPECT_EQ(ret, SQL_SUCCESS);
}

TYPED_TEST(FlightSQLODBCTestBase, TestSQLGetDiagRecForConnectFailure) {
// ODBC Environment
SQLHENV env;
SQLHDBC conn;

// Allocate an environment handle
SQLRETURN ret = SQLAllocEnv(&env);

EXPECT_EQ(ret, SQL_SUCCESS);

ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);

EXPECT_EQ(ret, SQL_SUCCESS);

// Allocate a connection using alloc handle
ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);

EXPECT_EQ(ret, SQL_SUCCESS);

// Invalid connect string
std::string connect_str = this->getInvalidConnectionString();

ASSERT_OK_AND_ASSIGN(std::wstring wconnect_str,
arrow::util::UTF8ToWideString(connect_str));
std::vector<SQLWCHAR> connect_str0(wconnect_str.begin(), wconnect_str.end());

SQLWCHAR outstr[ODBC_BUFFER_SIZE];
SQLSMALLINT outstrlen;

// Connecting to ODBC server.
ret = SQLDriverConnect(conn, NULL, &connect_str0[0],
static_cast<SQLSMALLINT>(connect_str0.size()), outstr,
ODBC_BUFFER_SIZE, &outstrlen, SQL_DRIVER_NOPROMPT);

EXPECT_TRUE(ret == SQL_ERROR);

SQLWCHAR sql_state[6];
SQLINTEGER native_error;
SQLWCHAR message[ODBC_BUFFER_SIZE];
SQLSMALLINT message_length;

ret = SQLGetDiagRec(SQL_HANDLE_DBC, conn, 1, sql_state, &native_error, message,
ODBC_BUFFER_SIZE, &message_length);

EXPECT_EQ(ret, SQL_SUCCESS);

EXPECT_GT(message_length, 120);

EXPECT_EQ(native_error, 200);

// 28000
EXPECT_EQ(sql_state[0], '2');
EXPECT_EQ(sql_state[1], '8');
EXPECT_EQ(sql_state[2], '0');
EXPECT_EQ(sql_state[3], '0');
EXPECT_EQ(sql_state[4], '0');

// Free connection handle
ret = SQLFreeHandle(SQL_HANDLE_DBC, conn);

EXPECT_EQ(ret, SQL_SUCCESS);

// Free environment handle
ret = SQLFreeHandle(SQL_HANDLE_ENV, env);

EXPECT_EQ(ret, SQL_SUCCESS);
}

TYPED_TEST(FlightSQLODBCTestBase, TestConnect) {
// Verifies connect and disconnect works on its own
this->connect();
Expand Down
Loading
Loading