Skip to content

Commit 524d981

Browse files
authored
Add SQLError Tests
* add test to free null handles. Without handle value initialization, segfault error was seen Move `SQLGetDiagField` and `SQLGetDiagRec` tests to `errors_test.cc` * Address comments from James * Add ODBC Ver 2 tests * update test name to indicate if error handling is from driver manager. * add tests for warnings. * fix lint errors. * remove SQL_ATTR_APP_ROW_DESC that is not applicable to Environment Attribute.
1 parent e7d8794 commit 524d981

File tree

5 files changed

+634
-251
lines changed

5 files changed

+634
-251
lines changed

cpp/src/arrow/flight/sql/odbc/odbc_api.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -617,8 +617,7 @@ SQLRETURN SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER valuePtr,
617617
return SQL_SUCCESS;
618618
}
619619

620-
case SQL_ATTR_CONNECTION_POOLING:
621-
case SQL_ATTR_APP_ROW_DESC: {
620+
case SQL_ATTR_CONNECTION_POOLING: {
622621
throw DriverException("Optional feature not supported.", "HYC00");
623622
}
624623

@@ -669,8 +668,7 @@ SQLRETURN SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER valuePtr,
669668
}
670669
}
671670

672-
case SQL_ATTR_CONNECTION_POOLING:
673-
case SQL_ATTR_APP_ROW_DESC: {
671+
case SQL_ATTR_CONNECTION_POOLING: {
674672
throw DriverException("Optional feature not supported.", "HYC00");
675673
}
676674

cpp/src/arrow/flight/sql/odbc/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ add_arrow_test(flight_sql_odbc_test
3434
columns_test.cc
3535
connection_attr_test.cc
3636
connection_info_test.cc
37+
errors_test.cc
3738
statement_attr_test.cc
3839
statement_test.cc
3940
tables_test.cc

cpp/src/arrow/flight/sql/odbc/tests/connection_test.cc

Lines changed: 18 additions & 244 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,24 @@ TEST(SQLFreeHandle, TestSQLFreeHandleConnect) {
128128
EXPECT_TRUE(return_free_handle == SQL_SUCCESS);
129129
}
130130

131+
TYPED_TEST(FlightSQLODBCTestBase, TestFreeNullHandles) {
132+
// Verifies attempt to free invalid handle does not cause segfault
133+
// Attempt to free null statement handle
134+
SQLRETURN ret = SQLFreeHandle(SQL_HANDLE_STMT, this->stmt);
135+
136+
EXPECT_EQ(ret, SQL_INVALID_HANDLE);
137+
138+
// Attempt to free null connection handle
139+
ret = SQLFreeHandle(SQL_HANDLE_DBC, this->conn);
140+
141+
EXPECT_EQ(ret, SQL_INVALID_HANDLE);
142+
143+
// Attempt to free null environment handle
144+
ret = SQLFreeHandle(SQL_HANDLE_ENV, this->env);
145+
146+
EXPECT_EQ(ret, SQL_INVALID_HANDLE);
147+
}
148+
131149
TEST(SQLFreeConnect, TestSQLFreeConnect) {
132150
// ODBC Environment
133151
SQLHENV env;
@@ -811,250 +829,6 @@ TEST(SQLDisconnect, TestSQLDisconnectWithoutConnection) {
811829
EXPECT_EQ(ret, SQL_SUCCESS);
812830
}
813831

814-
TYPED_TEST(FlightSQLODBCTestBase, TestSQLGetDiagFieldWForConnectFailure) {
815-
// ODBC Environment
816-
SQLHENV env;
817-
SQLHDBC conn;
818-
819-
// Allocate an environment handle
820-
SQLRETURN ret = SQLAllocEnv(&env);
821-
822-
EXPECT_EQ(ret, SQL_SUCCESS);
823-
824-
ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
825-
826-
EXPECT_EQ(ret, SQL_SUCCESS);
827-
828-
// Allocate a connection using alloc handle
829-
ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);
830-
831-
EXPECT_EQ(ret, SQL_SUCCESS);
832-
833-
// Invalid connect string
834-
std::string connect_str = this->getInvalidConnectionString();
835-
836-
ASSERT_OK_AND_ASSIGN(std::wstring wconnect_str,
837-
arrow::util::UTF8ToWideString(connect_str));
838-
std::vector<SQLWCHAR> connect_str0(wconnect_str.begin(), wconnect_str.end());
839-
840-
SQLWCHAR outstr[ODBC_BUFFER_SIZE];
841-
SQLSMALLINT outstrlen;
842-
843-
// Connecting to ODBC server.
844-
ret = SQLDriverConnect(conn, NULL, &connect_str0[0],
845-
static_cast<SQLSMALLINT>(connect_str0.size()), outstr,
846-
ODBC_BUFFER_SIZE, &outstrlen, SQL_DRIVER_NOPROMPT);
847-
848-
EXPECT_TRUE(ret == SQL_ERROR);
849-
850-
// Retrieve all supported header level and record level data
851-
SQLSMALLINT HEADER_LEVEL = 0;
852-
SQLSMALLINT RECORD_1 = 1;
853-
854-
// SQL_DIAG_NUMBER
855-
SQLINTEGER diag_number;
856-
SQLSMALLINT diag_number_length;
857-
858-
ret = SQLGetDiagField(SQL_HANDLE_DBC, conn, HEADER_LEVEL, SQL_DIAG_NUMBER, &diag_number,
859-
sizeof(SQLINTEGER), &diag_number_length);
860-
861-
EXPECT_EQ(ret, SQL_SUCCESS);
862-
863-
EXPECT_EQ(diag_number, 1);
864-
865-
// SQL_DIAG_SERVER_NAME
866-
SQLWCHAR server_name[ODBC_BUFFER_SIZE];
867-
SQLSMALLINT server_name_length;
868-
869-
ret = SQLGetDiagField(SQL_HANDLE_DBC, conn, RECORD_1, SQL_DIAG_SERVER_NAME, server_name,
870-
ODBC_BUFFER_SIZE, &server_name_length);
871-
872-
EXPECT_EQ(ret, SQL_SUCCESS);
873-
874-
// SQL_DIAG_MESSAGE_TEXT
875-
SQLWCHAR message_text[ODBC_BUFFER_SIZE];
876-
SQLSMALLINT message_text_length;
877-
878-
ret = SQLGetDiagField(SQL_HANDLE_DBC, conn, RECORD_1, SQL_DIAG_MESSAGE_TEXT,
879-
message_text, ODBC_BUFFER_SIZE, &message_text_length);
880-
881-
EXPECT_EQ(ret, SQL_SUCCESS);
882-
883-
EXPECT_GT(message_text_length, 100);
884-
885-
// SQL_DIAG_NATIVE
886-
SQLINTEGER diag_native;
887-
SQLSMALLINT diag_native_length;
888-
889-
ret = SQLGetDiagField(SQL_HANDLE_DBC, conn, RECORD_1, SQL_DIAG_NATIVE, &diag_native,
890-
sizeof(diag_native), &diag_native_length);
891-
892-
EXPECT_EQ(ret, SQL_SUCCESS);
893-
894-
EXPECT_EQ(diag_native, 200);
895-
896-
// SQL_DIAG_SQLSTATE
897-
const SQLSMALLINT sql_state_size = 6;
898-
SQLWCHAR sql_state[sql_state_size];
899-
SQLSMALLINT sql_state_length;
900-
ret = SQLGetDiagField(SQL_HANDLE_DBC, conn, RECORD_1, SQL_DIAG_SQLSTATE, sql_state,
901-
sql_state_size * driver::odbcabstraction::GetSqlWCharSize(),
902-
&sql_state_length);
903-
904-
EXPECT_EQ(ret, SQL_SUCCESS);
905-
906-
// 28000
907-
EXPECT_EQ(sql_state[0], '2');
908-
EXPECT_EQ(sql_state[1], '8');
909-
EXPECT_EQ(sql_state[2], '0');
910-
EXPECT_EQ(sql_state[3], '0');
911-
EXPECT_EQ(sql_state[4], '0');
912-
913-
// Free connection handle
914-
ret = SQLFreeHandle(SQL_HANDLE_DBC, conn);
915-
916-
EXPECT_EQ(ret, SQL_SUCCESS);
917-
918-
// Free environment handle
919-
ret = SQLFreeHandle(SQL_HANDLE_ENV, env);
920-
921-
EXPECT_EQ(ret, SQL_SUCCESS);
922-
}
923-
924-
TYPED_TEST(FlightSQLODBCTestBase, TestSQLGetDiagFieldWForConnectFailureNTS) {
925-
// Test is disabled because driver manager on Windows does not pass through SQL_NTS
926-
// This test case can be potentially used on macOS/Linux
927-
GTEST_SKIP();
928-
// ODBC Environment
929-
SQLHENV env;
930-
SQLHDBC conn;
931-
932-
// Allocate an environment handle
933-
SQLRETURN ret = SQLAllocEnv(&env);
934-
935-
EXPECT_EQ(ret, SQL_SUCCESS);
936-
937-
ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
938-
939-
EXPECT_EQ(ret, SQL_SUCCESS);
940-
941-
// Allocate a connection using alloc handle
942-
ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);
943-
944-
EXPECT_EQ(ret, SQL_SUCCESS);
945-
946-
// Invalid connect string
947-
std::string connect_str = this->getInvalidConnectionString();
948-
949-
ASSERT_OK_AND_ASSIGN(std::wstring wconnect_str,
950-
arrow::util::UTF8ToWideString(connect_str));
951-
std::vector<SQLWCHAR> connect_str0(wconnect_str.begin(), wconnect_str.end());
952-
953-
SQLWCHAR outstr[ODBC_BUFFER_SIZE];
954-
SQLSMALLINT outstrlen;
955-
956-
// Connecting to ODBC server.
957-
ret = SQLDriverConnect(conn, NULL, &connect_str0[0],
958-
static_cast<SQLSMALLINT>(connect_str0.size()), outstr,
959-
ODBC_BUFFER_SIZE, &outstrlen, SQL_DRIVER_NOPROMPT);
960-
961-
EXPECT_TRUE(ret == SQL_ERROR);
962-
963-
// Retrieve all supported header level and record level data
964-
SQLSMALLINT RECORD_1 = 1;
965-
966-
// SQL_DIAG_MESSAGE_TEXT SQL_NTS
967-
SQLWCHAR message_text[ODBC_BUFFER_SIZE];
968-
SQLSMALLINT message_text_length;
969-
970-
message_text[ODBC_BUFFER_SIZE - 1] = '\0';
971-
972-
ret = SQLGetDiagField(SQL_HANDLE_DBC, conn, RECORD_1, SQL_DIAG_MESSAGE_TEXT,
973-
message_text, SQL_NTS, &message_text_length);
974-
975-
EXPECT_EQ(ret, SQL_SUCCESS);
976-
977-
EXPECT_GT(message_text_length, 100);
978-
979-
// Free connection handle
980-
ret = SQLFreeHandle(SQL_HANDLE_DBC, conn);
981-
982-
EXPECT_EQ(ret, SQL_SUCCESS);
983-
984-
// Free environment handle
985-
ret = SQLFreeHandle(SQL_HANDLE_ENV, env);
986-
987-
EXPECT_EQ(ret, SQL_SUCCESS);
988-
}
989-
990-
TYPED_TEST(FlightSQLODBCTestBase, TestSQLGetDiagRecForConnectFailure) {
991-
// ODBC Environment
992-
SQLHENV env;
993-
SQLHDBC conn;
994-
995-
// Allocate an environment handle
996-
SQLRETURN ret = SQLAllocEnv(&env);
997-
998-
EXPECT_EQ(ret, SQL_SUCCESS);
999-
1000-
ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
1001-
1002-
EXPECT_EQ(ret, SQL_SUCCESS);
1003-
1004-
// Allocate a connection using alloc handle
1005-
ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);
1006-
1007-
EXPECT_EQ(ret, SQL_SUCCESS);
1008-
1009-
// Invalid connect string
1010-
std::string connect_str = this->getInvalidConnectionString();
1011-
1012-
ASSERT_OK_AND_ASSIGN(std::wstring wconnect_str,
1013-
arrow::util::UTF8ToWideString(connect_str));
1014-
std::vector<SQLWCHAR> connect_str0(wconnect_str.begin(), wconnect_str.end());
1015-
1016-
SQLWCHAR outstr[ODBC_BUFFER_SIZE];
1017-
SQLSMALLINT outstrlen;
1018-
1019-
// Connecting to ODBC server.
1020-
ret = SQLDriverConnect(conn, NULL, &connect_str0[0],
1021-
static_cast<SQLSMALLINT>(connect_str0.size()), outstr,
1022-
ODBC_BUFFER_SIZE, &outstrlen, SQL_DRIVER_NOPROMPT);
1023-
1024-
EXPECT_TRUE(ret == SQL_ERROR);
1025-
1026-
SQLWCHAR sql_state[6];
1027-
SQLINTEGER native_error;
1028-
SQLWCHAR message[ODBC_BUFFER_SIZE];
1029-
SQLSMALLINT message_length;
1030-
1031-
ret = SQLGetDiagRec(SQL_HANDLE_DBC, conn, 1, sql_state, &native_error, message,
1032-
ODBC_BUFFER_SIZE, &message_length);
1033-
1034-
EXPECT_EQ(ret, SQL_SUCCESS);
1035-
1036-
EXPECT_GT(message_length, 120);
1037-
1038-
EXPECT_EQ(native_error, 200);
1039-
1040-
// 28000
1041-
EXPECT_EQ(sql_state[0], '2');
1042-
EXPECT_EQ(sql_state[1], '8');
1043-
EXPECT_EQ(sql_state[2], '0');
1044-
EXPECT_EQ(sql_state[3], '0');
1045-
EXPECT_EQ(sql_state[4], '0');
1046-
1047-
// Free connection handle
1048-
ret = SQLFreeHandle(SQL_HANDLE_DBC, conn);
1049-
1050-
EXPECT_EQ(ret, SQL_SUCCESS);
1051-
1052-
// Free environment handle
1053-
ret = SQLFreeHandle(SQL_HANDLE_ENV, env);
1054-
1055-
EXPECT_EQ(ret, SQL_SUCCESS);
1056-
}
1057-
1058832
TYPED_TEST(FlightSQLODBCTestBase, TestConnect) {
1059833
// Verifies connect and disconnect works on its own
1060834
this->connect();

0 commit comments

Comments
 (0)