From 3439e98ace7d8590a4d279975e311388ab7fe465 Mon Sep 17 00:00:00 2001 From: justing-bq <62349012+justing-bq@users.noreply.github.com> Date: Mon, 6 Apr 2026 14:43:54 -0700 Subject: [PATCH 1/2] Fix tests on Linux --- ci/scripts/cpp_test.sh | 1 - .../flight/sql/odbc/tests/columns_test.cc | 22 ++++--- .../sql/odbc/tests/connection_attr_test.cc | 66 ++++++++++++++----- .../sql/odbc/tests/connection_info_test.cc | 12 +++- .../flight/sql/odbc/tests/errors_test.cc | 23 ++++--- .../sql/odbc/tests/get_functions_test.cc | 7 +- .../flight/sql/odbc/tests/odbc_test_suite.h | 1 + .../sql/odbc/tests/statement_attr_test.cc | 4 ++ .../flight/sql/odbc/tests/statement_test.cc | 43 +++++++----- .../flight/sql/odbc/tests/tables_test.cc | 14 +++- .../flight/sql/odbc/tests/type_info_test.cc | 24 +++---- 11 files changed, 144 insertions(+), 73 deletions(-) diff --git a/ci/scripts/cpp_test.sh b/ci/scripts/cpp_test.sh index 2f88cdc819b2..241addbfebd2 100755 --- a/ci/scripts/cpp_test.sh +++ b/ci/scripts/cpp_test.sh @@ -55,7 +55,6 @@ if ! type minio >/dev/null 2>&1; then fi case "$(uname)" in Linux) - exclude_tests+=("arrow-flight-sql-odbc-test") n_jobs=$(nproc) ;; Darwin) diff --git a/cpp/src/arrow/flight/sql/odbc/tests/columns_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/columns_test.cc index 9e36c23f8ddd..abe6d8e6994a 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/columns_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/columns_test.cc @@ -46,6 +46,9 @@ TYPED_TEST_SUITE(ColumnsOdbcV2Test, TestTypesOdbcV2); namespace { // Helper functions + +// GH-49702: TODO Disabled on Linux due to BlockingQueue issue +#ifndef __linux__ void CheckSQLColumns( SQLHSTMT stmt, const std::wstring& expected_table, const std::wstring& expected_column, const SQLINTEGER& expected_data_type, @@ -125,6 +128,7 @@ void CheckRemoteSQLColumns( expected_octet_char_length, expected_ordinal_position, expected_is_nullable); } +#endif // __linux__ void CheckSQLColAttribute(SQLHSTMT stmt, SQLUSMALLINT idx, const std::string& expected_column_name, @@ -416,6 +420,8 @@ TYPED_TEST(ColumnsTest, SQLColumnsTestInputData) { ValidateFetch(this->stmt, SQL_SUCCESS); } +// GH-49702: TODO Disabled on Linux due to BlockingQueue issue +#ifndef __linux__ TEST_F(ColumnsMockTest, TestSQLColumnsAllColumns) { // Check table pattern and column pattern returns all columns @@ -1210,6 +1216,7 @@ TEST_F(ColumnsMockTest, TestSQLColumnsTableColumnPattern) { // There is no more column EXPECT_EQ(SQL_NO_DATA, SQLFetch(this->stmt)); } +#endif // __linux__ TEST_F(ColumnsMockTest, TestSQLColumnsInvalidTablePattern) { ASSIGN_SQLWCHAR_ARR(table_pattern, L"non-existent-table"); @@ -2560,10 +2567,6 @@ TEST_F(ColumnsMockTest, SQLDescribeColUnicodeTableMetadata) { ASSIGN_SQLWCHAR_ARR_AND_LEN(sql_query, L"SELECT * from 数据 LIMIT 1;"); - ASSIGN_SQLWCHAR_ARR_AND_LEN(expected_column_name, L"资料"); - SQLSMALLINT expected_column_data_type = SQL_WVARCHAR; - SQLULEN expected_column_size = 0; - ASSERT_EQ(SQL_SUCCESS, SQLExecDirect(this->stmt, sql_query, sql_query_len)); ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt)); @@ -2572,13 +2575,14 @@ TEST_F(ColumnsMockTest, SQLDescribeColUnicodeTableMetadata) { buf_char_len, &name_length, &column_data_type, &column_size, &decimal_digits, &nullable)); - EXPECT_EQ(name_length, expected_column_name_len); + std::wstring expected_column_name_wstr = std::wstring(L"资料"); + size_t expected_column_name_len = expected_column_name_wstr.length(); std::wstring returned(column_name, column_name + name_length); - std::wstring expected_col_name_str = ConvertToWString(expected_column_name); - EXPECT_EQ(expected_col_name_str, returned); - EXPECT_EQ(expected_column_data_type, column_data_type); - EXPECT_EQ(expected_column_size, column_size); + EXPECT_EQ(expected_column_name_wstr, returned); + EXPECT_EQ(expected_column_name_len, name_length); + EXPECT_EQ(SQL_WVARCHAR, column_data_type); + EXPECT_EQ(0, column_size); EXPECT_EQ(0, decimal_digits); EXPECT_EQ(SQL_NULLABLE, nullable); diff --git a/cpp/src/arrow/flight/sql/odbc/tests/connection_attr_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/connection_attr_test.cc index 4e690f59ebcb..7f79c33eb85a 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/connection_attr_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/connection_attr_test.cc @@ -33,6 +33,13 @@ using TestTypes = ::testing::Types; TYPED_TEST_SUITE(ConnectionAttributeTest, TestTypes); +template +class ConnectionAttributePreConnectTest : public T {}; + +using TestTypesHandle = ::testing::Types; +TYPED_TEST_SUITE(ConnectionAttributePreConnectTest, TestTypesHandle); + #ifdef SQL_ATTR_ASYNC_DBC_EVENT TYPED_TEST(ConnectionAttributeTest, TestSQLSetConnectAttrAsyncDbcEventUnsupported) { ASSERT_EQ(SQL_ERROR, SQLSetConnectAttr(this->conn, SQL_ATTR_ASYNC_DBC_EVENT, 0, 0)); @@ -117,31 +124,34 @@ TYPED_TEST(ConnectionAttributeTest, TestSQLSetConnectAttrTraceDMOnly) { } #endif // __APPLE__ -TYPED_TEST(ConnectionAttributeTest, TestSQLSetConnectAttrTracefileDMOnly) { +TYPED_TEST(ConnectionAttributePreConnectTest, TestSQLSetConnectAttrTracefileDMOnly) { // Verify DM-only attribute is handled by Driver Manager // Use placeholder value as we want the call to fail, or else // the driver manager will produce a trace file. std::wstring trace_file = L"invalid/file/path"; std::vector trace_file0(trace_file.begin(), trace_file.end()); + +#ifdef _WIN32 ASSERT_EQ(SQL_ERROR, SQLSetConnectAttr(this->conn, SQL_ATTR_TRACEFILE, &trace_file0[0], static_cast(trace_file0.size()))); -#ifdef __APPLE__ - VerifyOdbcErrorState(SQL_HANDLE_DBC, this->conn, kErrorStateHYC00); -#else VerifyOdbcErrorState(SQL_HANDLE_DBC, this->conn, kErrorStateHY000); -#endif // __APPLE__ +#else // Mac & Linux + ASSERT_EQ(SQL_SUCCESS, + SQLSetConnectAttr(this->conn, SQL_ATTR_TRACEFILE, &trace_file0[0], + static_cast(trace_file0.size()))); +#endif } TYPED_TEST(ConnectionAttributeTest, TestSQLSetConnectAttrTranslateLabDMOnly) { // Verify DM-only attribute is handled by Driver Manager ASSERT_EQ(SQL_ERROR, SQLSetConnectAttr(this->conn, SQL_ATTR_TRANSLATE_LIB, 0, 0)); // Checks for invalid argument return error -#ifdef __APPLE__ - VerifyOdbcErrorState(SQL_HANDLE_DBC, this->conn, kErrorStateHYC00); -#else +#ifdef _WIN32 VerifyOdbcErrorState(SQL_HANDLE_DBC, this->conn, kErrorStateHY024); -#endif // __APPLE__ +#else // Mac & Linux + VerifyOdbcErrorState(SQL_HANDLE_DBC, this->conn, kErrorStateHYC00); +#endif } TYPED_TEST(ConnectionAttributeTest, TestSQLSetConnectAttrTranslateOptionUnsupported) { @@ -166,8 +176,8 @@ TYPED_TEST(ConnectionAttributeTest, TestSQLGetConnectAttrDbcInfoTokenSetOnly) { } #endif -// iODBC does not treat SQL_ATTR_ODBC_CURSORS as DM-only -#ifndef __APPLE__ +// Driver Manager behavior tests for Windows only. +#ifdef _WIN32 TYPED_TEST(ConnectionAttributeTest, TestSQLGetConnectAttrOdbcCursorsDMOnly) { // Verify that DM-only attribute is handled by driver manager SQLULEN cursor_attr; @@ -176,7 +186,6 @@ TYPED_TEST(ConnectionAttributeTest, TestSQLGetConnectAttrOdbcCursorsDMOnly) { EXPECT_EQ(SQL_CUR_USE_DRIVER, cursor_attr); } -// iODBC needs to be compiled with tracing enabled to handle SQL_ATTR_TRACE TYPED_TEST(ConnectionAttributeTest, TestSQLGetConnectAttrTraceDMOnly) { // Verify that DM-only attribute is handled by driver manager SQLUINTEGER trace; @@ -185,7 +194,6 @@ TYPED_TEST(ConnectionAttributeTest, TestSQLGetConnectAttrTraceDMOnly) { EXPECT_EQ(SQL_OPT_TRACE_OFF, trace); } -// iODBC needs to be compiled with tracing enabled to handle SQL_ATTR_TRACEFILE TYPED_TEST(ConnectionAttributeTest, TestSQLGetConnectAttrTraceFileDMOnly) { // Verify that DM-only attribute is handled by driver manager SQLWCHAR out_str[kOdbcBufferSize]; @@ -199,7 +207,7 @@ TYPED_TEST(ConnectionAttributeTest, TestSQLGetConnectAttrTraceFileDMOnly) { ODBC::SqlWcharToString(out_str, static_cast(out_str_len)); EXPECT_FALSE(out_connection_string.empty()); } -#endif // __APPLE__ +#endif // _WIN32 TYPED_TEST(ConnectionAttributeTest, TestSQLGetConnectAttrTranslateLibUnsupported) { SQLWCHAR out_str[kOdbcBufferSize]; @@ -226,11 +234,17 @@ TYPED_TEST(ConnectionAttributeTest, TestSQLGetConnectAttrTxnIsolationUnsupported #ifdef SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE TYPED_TEST(ConnectionAttributeTest, TestSQLGetConnectAttrAsyncDbcFunctionsEnableUnsupported) { - // Verifies that the Windows driver manager returns HY114 for unsupported functionality SQLUINTEGER enable; +# ifdef _WIN32 + // Verifies that the Windows driver manager returns HY114 for unsupported functionality ASSERT_EQ(SQL_ERROR, SQLGetConnectAttr(this->conn, SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE, &enable, 0, 0)); VerifyOdbcErrorState(SQL_HANDLE_DBC, this->conn, kErrorStateHY114); +# else // Mac & Linux + ASSERT_EQ( + SQL_SUCCESS, + SQLGetConnectAttr(this->conn, SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE, &enable, 0, 0)); +# endif } #endif @@ -357,14 +371,24 @@ TYPED_TEST(ConnectionAttributeTest, TestSQLSetConnectAttrLoginTimeoutValid) { EXPECT_EQ(42, timeout); } +#ifdef __linux__ +// On Linux, SQL_ATTR_PACKET_SIZE can only be set before connection +// which is why use a different test fixture for Linux. +TYPED_TEST(ConnectionAttributePreConnectTest, TestSQLSetConnectAttrPacketSizeValid) { +#else // Windows & Mac TYPED_TEST(ConnectionAttributeTest, TestSQLSetConnectAttrPacketSizeValid) { - // The driver always returns 0. PACKET_SIZE value is unused by the driver. - +#endif // Check default value first SQLUINTEGER size = -1; +#ifdef __linux__ + ASSERT_EQ(SQL_ERROR, + SQLGetConnectAttr(this->conn, SQL_ATTR_PACKET_SIZE, &size, 0, nullptr)); + VerifyOdbcErrorState(SQL_HANDLE_DBC, this->conn, kErrorState08003); +#else // Windows & Mac ASSERT_EQ(SQL_SUCCESS, SQLGetConnectAttr(this->conn, SQL_ATTR_PACKET_SIZE, &size, 0, nullptr)); EXPECT_EQ(0, size); +#endif ASSERT_EQ(SQL_SUCCESS, SQLSetConnectAttr(this->conn, SQL_ATTR_PACKET_SIZE, reinterpret_cast(0), 0)); @@ -374,12 +398,18 @@ TYPED_TEST(ConnectionAttributeTest, TestSQLSetConnectAttrPacketSizeValid) { SQLGetConnectAttr(this->conn, SQL_ATTR_PACKET_SIZE, &size, 0, nullptr)); EXPECT_EQ(0, size); - // Attempt to set to non-zero value, driver should return warning and not error + // Attempt to set to non-zero value, +#ifdef __linux__ + EXPECT_EQ(SQL_SUCCESS, SQLSetConnectAttr(this->conn, SQL_ATTR_PACKET_SIZE, + reinterpret_cast(2), 0)); +#else // Windows & Mac + // driver should return warning and not error EXPECT_EQ(SQL_SUCCESS_WITH_INFO, SQLSetConnectAttr(this->conn, SQL_ATTR_PACKET_SIZE, reinterpret_cast(2), 0)); // Verify warning status VerifyOdbcErrorState(SQL_HANDLE_DBC, this->conn, kErrorState01S02); +#endif } } // namespace arrow::flight::sql::odbc diff --git a/cpp/src/arrow/flight/sql/odbc/tests/connection_info_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/connection_info_test.cc index 257e8affa48e..a1116bb1c47e 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/connection_info_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/connection_info_test.cc @@ -143,6 +143,9 @@ TYPED_TEST(ConnectionInfoTest, TestSQLGetInfoDataSourceName) { } #ifdef SQL_DRIVER_AWARE_POOLING_SUPPORTED +// GH-49782: TODO Disabled on Linux until SQL_DRIVER_AWARE_POOLING_SUPPORTED is +// implemented in the driver. +# ifndef __linux__ TYPED_TEST(ConnectionInfoTest, TestSQLGetInfoDriverAwarePoolingSupported) { // According to Microsoft documentation, ODBC driver does not need to implement // SQL_DRIVER_AWARE_POOLING_SUPPORTED and the Driver Manager will ignore the @@ -153,7 +156,8 @@ TYPED_TEST(ConnectionInfoTest, TestSQLGetInfoDriverAwarePoolingSupported) { EXPECT_EQ(static_cast(SQL_DRIVER_AWARE_POOLING_NOT_CAPABLE), value); } -#endif +# endif // __linux__ +#endif // SQL_DRIVER_AWARE_POOLING_SUPPORTED // These information types are implemented by the Driver Manager alone. TYPED_TEST(ConnectionInfoTest, TestSQLGetInfoDriverHdbc) { @@ -331,9 +335,11 @@ TYPED_TEST(ConnectionInfoTest, TestSQLGetInfoOdbcVer) { std::wstring result = ConvertToWString(value); -#ifdef __APPLE__ +#if defined(__APPLE__) EXPECT_EQ(std::wstring(L"03.52.0000"), result); -#else +#elif defined(__linux__) + EXPECT_EQ(std::wstring(L"03.52"), result); +#else // WINDOWS EXPECT_EQ(std::wstring(L"03.80.0000"), result); #endif // __APPLE__ } diff --git a/cpp/src/arrow/flight/sql/odbc/tests/errors_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/errors_test.cc index 0a010356fea9..7e734accb8d5 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/errors_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/errors_test.cc @@ -313,15 +313,20 @@ TYPED_TEST(ErrorsTest, TestSQLGetDiagRecInputData) { EXPECT_EQ(SQL_NO_DATA, SQLGetDiagRec(SQL_HANDLE_DBC, this->conn, 1, nullptr, nullptr, nullptr, 0, nullptr)); - // Invalid handle #ifdef __APPLE__ // MacOS ODBC driver manager requires connection handle EXPECT_EQ(SQL_INVALID_HANDLE, SQLGetDiagRec(0, this->conn, 1, nullptr, nullptr, nullptr, 0, nullptr)); #else - EXPECT_EQ(SQL_INVALID_HANDLE, + // Linux & Windows driver managers have different expected return values +# ifdef __linux__ + SQLRETURN expected_rc = SQL_ERROR; +# else // Windows + SQLRETURN expected_rc = SQL_INVALID_HANDLE; +# endif + EXPECT_EQ(expected_rc, SQLGetDiagRec(0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr)); -#endif // __APPLE__ +#endif } TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorInputData) { @@ -491,13 +496,13 @@ TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorEnvErrorFromDriverManager) { EXPECT_EQ(0, native_error); // Function sequence error state from driver manager -#ifdef _WIN32 - // Windows Driver Manager returns S1010 - EXPECT_EQ(kErrorStateS1010, SqlWcharToString(sql_state)); -#else - // unix Driver Manager returns HY010 +#ifdef __APPLE__ + // MacOS Driver Manager returns HY010 EXPECT_EQ(kErrorStateHY010, SqlWcharToString(sql_state)); -#endif // _WIN32 +#else // Linux & Windows + // Linux & Windows Driver Managers returns S1010 + EXPECT_EQ(kErrorStateS1010, SqlWcharToString(sql_state)); +#endif std::string msg = SqlWcharToString(message); EXPECT_FALSE(msg.empty()); diff --git a/cpp/src/arrow/flight/sql/odbc/tests/get_functions_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/get_functions_test.cc index 2181f8a3b408..b01b0d71d5e4 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/get_functions_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/get_functions_test.cc @@ -40,8 +40,9 @@ using TestTypesOdbcV2 = ::testing::Types; TYPED_TEST_SUITE(GetFunctionsOdbcV2Test, TestTypesOdbcV2); -// MacOS driver manager iODBC does not support SQLGetFunctions for ODBC 3.x or 2.x driver -#ifndef __APPLE__ +// Unix driver managers iODBC and Unix-ODBC do not support SQLGetFunctions +// for ODBC 3.x or 2.x driver +#ifdef _WIN32 TYPED_TEST(GetFunctionsTest, TestSQLGetFunctionsAllFunctions) { // Verify driver manager return values for SQLGetFunctions @@ -218,6 +219,6 @@ TYPED_TEST(GetFunctionsOdbcV2Test, TestSQLGetFunctionsUnsupportedSingleAPI) { api_exists = -1; } } -#endif // __APPLE__ +#endif // _WIN32 } // namespace arrow::flight::sql::odbc diff --git a/cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.h b/cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.h index f4de85f69938..845631b6cd32 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.h +++ b/cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.h @@ -246,6 +246,7 @@ bool CompareConnPropertyMap(Connection::ConnPropertyMap map1, /// Get error message from ODBC driver using SQLGetDiagRec std::string GetOdbcErrorMessage(SQLSMALLINT handle_type, SQLHANDLE handle); +static constexpr std::string_view kErrorState00000 = "00000"; static constexpr std::string_view kErrorState01004 = "01004"; static constexpr std::string_view kErrorState01S02 = "01S02"; static constexpr std::string_view kErrorState01S07 = "01S07"; diff --git a/cpp/src/arrow/flight/sql/odbc/tests/statement_attr_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/statement_attr_test.cc index 6903ce0431e7..fc5c5f9d1e64 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/statement_attr_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/statement_attr_test.cc @@ -427,7 +427,11 @@ TYPED_TEST(StatementAttributeTest, TestSQLSetStmtAttrAsyncEnableUnsupported) { TYPED_TEST(StatementAttributeTest, TestSQLSetStmtAttrAsyncStmtEventUnsupported) { // Driver does not support asynchronous notification ValidateSetStmtAttrErrorCode(this->stmt, SQL_ATTR_ASYNC_STMT_EVENT, 0, SQL_ERROR, +# ifdef __linux__ + kErrorStateHYC00); +# else // Windows & Mac kErrorStateHY118); +# endif } #endif diff --git a/cpp/src/arrow/flight/sql/odbc/tests/statement_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/statement_test.cc index 5bf9ef17ca4e..b14eb676dd9c 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/statement_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/statement_test.cc @@ -401,9 +401,9 @@ TEST_F(StatementMockTest, TestSQLExecDirectVarbinaryQuery) { SQLLEN ind; ASSERT_EQ(SQL_SUCCESS, SQLGetData(this->stmt, 1, SQL_C_BINARY, &varbinary_val[0], buf_len, &ind)); - EXPECT_EQ('\xAB', varbinary_val[0]); - EXPECT_EQ('\xCD', varbinary_val[1]); - EXPECT_EQ('\xEF', varbinary_val[2]); + EXPECT_EQ(static_cast('\xAB'), static_cast(varbinary_val[0])); + EXPECT_EQ(static_cast('\xCD'), static_cast(varbinary_val[1])); + EXPECT_EQ(static_cast('\xEF'), static_cast(varbinary_val[2])); } // Tests with SQL_C_DEFAULT as the target type @@ -641,9 +641,9 @@ TEST_F(StatementRemoteTest, TestSQLExecDirectVarbinaryQueryDefaultType) { SQLLEN ind; ASSERT_EQ(SQL_SUCCESS, SQLGetData(this->stmt, 1, SQL_C_DEFAULT, &varbinary_val[0], buf_len, &ind)); - EXPECT_EQ('\xAB', varbinary_val[0]); - EXPECT_EQ('\xCD', varbinary_val[1]); - EXPECT_EQ('\xEF', varbinary_val[2]); + EXPECT_EQ(static_cast('\xAB'), static_cast(varbinary_val[0])); + EXPECT_EQ(static_cast('\xCD'), static_cast(varbinary_val[1])); + EXPECT_EQ(static_cast('\xEF'), static_cast(varbinary_val[2])); } // TODO(GH-48730): Enable this test when ARD/IRD descriptor support is fully implemented @@ -1030,9 +1030,9 @@ TEST_F(StatementMockTest, TestSQLExecDirectVarbinaryTruncation) { SQLGetData(this->stmt, 1, SQL_C_BINARY, &varbinary_val[0], buf_len, &ind)); // Verify binary truncation is reported VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, kErrorState01004); - EXPECT_EQ('\xAB', varbinary_val[0]); - EXPECT_EQ('\xCD', varbinary_val[1]); - EXPECT_EQ('\xEF', varbinary_val[2]); + EXPECT_EQ(static_cast('\xAB'), static_cast(varbinary_val[0])); + EXPECT_EQ(static_cast('\xCD'), static_cast(varbinary_val[1])); + EXPECT_EQ(static_cast('\xEF'), static_cast(varbinary_val[2])); EXPECT_EQ(4, ind); // Fetch same column 2nd time @@ -1043,7 +1043,7 @@ TEST_F(StatementMockTest, TestSQLExecDirectVarbinaryTruncation) { ASSERT_EQ(SQL_SUCCESS, SQLGetData(this->stmt, 1, SQL_C_BINARY, &varbinary_val2[0], buf_len, &ind)); - EXPECT_EQ('\xAB', varbinary_val[0]); + EXPECT_EQ(static_cast('\xAB'), static_cast(varbinary_val[0])); EXPECT_EQ(1, ind); // Attempt to fetch data 3rd time @@ -1166,9 +1166,9 @@ TEST_F(StatementRemoteTest, TestSQLExecDirectNullQueryNullIndicator) { VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, kErrorState22002); } -// MacOS Driver Manager iODBC returns SQL_ERROR when invalid buffer length is provided to -// SQLGetData -#ifndef __APPLE__ +// The MacOS and Linux Driver Managers return SQL_ERROR when invalid buffer length is +// provided to SQLGetData +#ifdef _WIN32 TYPED_TEST(StatementTest, TestSQLExecDirectIgnoreInvalidBufLen) { // Verify the driver ignores invalid buffer length for fixed data types @@ -1366,7 +1366,7 @@ TYPED_TEST(StatementTest, TestSQLExecDirectIgnoreInvalidBufLen) { EXPECT_EQ(59, timestamp_var.second); EXPECT_EQ(0, timestamp_var.fraction); } -#endif // __APPLE__ +#endif // _WIN32 TYPED_TEST(StatementTest, TestSQLBindColDataQuery) { // Numeric Types @@ -1698,9 +1698,9 @@ TEST_F(StatementMockTest, TestSQLBindColVarbinaryQuery) { ASSERT_EQ(SQL_SUCCESS, SQLFetch(this->stmt)); // Check varbinary values - EXPECT_EQ('\xAB', varbinary_val[0]); - EXPECT_EQ('\xCD', varbinary_val[1]); - EXPECT_EQ('\xEF', varbinary_val[2]); + EXPECT_EQ(static_cast('\xAB'), static_cast(varbinary_val[0])); + EXPECT_EQ(static_cast('\xCD'), static_cast(varbinary_val[1])); + EXPECT_EQ(static_cast('\xEF'), static_cast(varbinary_val[2])); } TEST_F(StatementRemoteTest, TestSQLBindColNullQuery) { @@ -1986,8 +1986,13 @@ TYPED_TEST(StatementTest, TestSQLMoreResultsNoData) { TYPED_TEST(StatementTest, TestSQLMoreResultsInvalidFunctionSequence) { // Verify function sequence error state is reported when SQLMoreResults is called // without executing any queries +#ifdef __linux__ + ASSERT_EQ(SQL_NO_DATA, SQLMoreResults(this->stmt)); + VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, kErrorState00000); +#else // Windows & Mac ASSERT_EQ(SQL_ERROR, SQLMoreResults(this->stmt)); VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, kErrorStateHY010); +#endif } TYPED_TEST(StatementTest, TestSQLNativeSqlReturnsInputString) { @@ -2174,7 +2179,11 @@ TYPED_TEST(StatementTest, SQLRowCountReturnsSuccessOnNullptr) { TYPED_TEST(StatementTest, SQLRowCountFunctionSequenceErrorOnNoQuery) { SQLLEN row_count = 0; +#ifdef __linux__ + SQLLEN expected_value = -1; +#else // Windows & Mac SQLLEN expected_value = 0; +#endif ASSERT_EQ(SQL_ERROR, SQLRowCount(this->stmt, &row_count)); #ifdef __APPLE__ diff --git a/cpp/src/arrow/flight/sql/odbc/tests/tables_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/tables_test.cc index 6a5c8053d7ad..8d253ab3bcf2 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/tables_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/tables_test.cc @@ -31,7 +31,7 @@ class TablesTest : public T {}; class TablesMockTest : public FlightSQLODBCMockTestBase {}; class TablesRemoteTest : public FlightSQLODBCRemoteTestBase {}; -using TestTypes = ::testing::Types; +using TestTypes = ::testing::Types; TYPED_TEST_SUITE(TablesTest, TestTypes); template @@ -78,6 +78,8 @@ TYPED_TEST(TablesTest, SQLTablesTestInputData) { ValidateFetch(this->stmt, SQL_SUCCESS); } +// GH-49702: TODO Disabled on Linux due to BlockingQueue issue +#ifndef __linux__ TEST_F(TablesMockTest, SQLTablesTestGetMetadataForAllCatalogs) { SQLWCHAR empty[] = {0}; ASSIGN_SQLWCHAR_ARR(SQL_ALL_CATALOGS_W, L"%"); @@ -97,6 +99,7 @@ TEST_F(TablesMockTest, SQLTablesTestGetMetadataForAllCatalogs) { ValidateFetch(this->stmt, SQL_NO_DATA); } +#endif // __linux__ TEST_F(TablesMockTest, SQLTablesTestGetMetadataForNamedCatalog) { CreateTestTable(); @@ -138,6 +141,8 @@ TEST_F(TablesMockTest, SQLTablesTestGetSchemaHasNoData) { ValidateFetch(this->stmt, SQL_NO_DATA); } +// GH-49702: TODO Disabled on Linux due to BlockingQueue issue +#ifndef __linux__ TEST_F(TablesRemoteTest, SQLTablesTestGetMetadataForAllSchemas) { SQLWCHAR empty[] = {0}; ASSIGN_SQLWCHAR_ARR(SQL_ALL_SCHEMAS_W, L"%"); @@ -342,6 +347,7 @@ TEST_F(TablesMockTest, SQLTablesTestGetMetadataForUnicodeTableByTableName) { DropUnicodeTable(); } +#endif // __linux__ TEST_F(TablesMockTest, SQLTablesTestGetMetadataForInvalidTableNameNoData) { CreateTestTable(); @@ -408,6 +414,8 @@ TEST_F(TablesMockTest, SQLTablesGetMetadataForTableType) { DropTestTable(); } +// GH-49702: TODO Disabled on Linux due to BlockingQueue issue +#ifndef __linux__ TEST_F(TablesRemoteTest, SQLTablesGetMetadataForTableTypeTable) { // Requires creation of user table named ODBCTest using schema $scratch in remote server @@ -436,6 +444,7 @@ TEST_F(TablesRemoteTest, SQLTablesGetMetadataForTableTypeTable) { ValidateFetch(this->stmt, SQL_NO_DATA); } } +#endif // __linux__ TEST_F(TablesRemoteTest, SQLTablesGetMetadataForTableTypeViewHasNoData) { SQLWCHAR empty[] = {0}; @@ -452,6 +461,8 @@ TEST_F(TablesRemoteTest, SQLTablesGetMetadataForTableTypeViewHasNoData) { ValidateFetch(this->stmt, SQL_NO_DATA); } +// GH-49702: TODO Disabled on Linux due to BlockingQueue issue +#ifndef __linux__ TEST_F(TablesMockTest, SQLTablesGetSupportedTableTypes) { SQLWCHAR empty[] = {0}; ASSIGN_SQLWCHAR_ARR(SQL_ALL_TABLE_TYPES_W, L"%"); @@ -492,6 +503,7 @@ TEST_F(TablesRemoteTest, SQLTablesGetSupportedTableTypes) { ValidateFetch(this->stmt, SQL_NO_DATA); } +#endif // __linux__ TYPED_TEST(TablesTest, SQLTablesGetMetadataBySQLDescribeCol) { SQLWCHAR column_name[1024]; diff --git a/cpp/src/arrow/flight/sql/odbc/tests/type_info_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/type_info_test.cc index 04e178f8f555..2458ea9974c0 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/type_info_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/type_info_test.cc @@ -1649,15 +1649,15 @@ TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoDateODBCVer2) { } TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoSQLTypeDate) { -#ifdef __APPLE__ - ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(stmt, SQL_TYPE_DATE)); -#else +#ifdef _WIN32 // Pass ODBC Ver 3 data type ASSERT_EQ(SQL_ERROR, SQLGetTypeInfo(stmt, SQL_TYPE_DATE)); // Driver manager returns SQL data type out of range error state VerifyOdbcErrorState(SQL_HANDLE_STMT, stmt, kErrorStateS1004); -#endif // __APPLE__ +#else // Mac & Linux + ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(stmt, SQL_TYPE_DATE)); +#endif } TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoSQLTypeTime) { @@ -1762,15 +1762,15 @@ TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoTimeODBCVer2) { } TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoSQLTypeTime) { -#ifdef __APPLE__ - ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(stmt, SQL_TYPE_TIME)); -#else +#ifdef _WIN32 // Pass ODBC Ver 3 data type ASSERT_EQ(SQL_ERROR, SQLGetTypeInfo(stmt, SQL_TYPE_TIME)); // Driver manager returns SQL data type out of range error state VerifyOdbcErrorState(SQL_HANDLE_STMT, stmt, kErrorStateS1004); -#endif // __APPLE__ +#else // Mac & Linux + ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(stmt, SQL_TYPE_TIME)); +#endif } TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoSQLTypeTimestamp) { @@ -1874,15 +1874,15 @@ TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoSQLTimestampODBCVer2) { } TEST_F(TypeInfoOdbcV2MockTest, TestSQLGetTypeInfoSQLTypeTimestamp) { -#ifdef __APPLE__ - ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(stmt, SQL_TYPE_TIMESTAMP)); -#else +#ifdef _WIN32 // Pass ODBC Ver 3 data type ASSERT_EQ(SQL_ERROR, SQLGetTypeInfo(stmt, SQL_TYPE_TIMESTAMP)); // Driver manager returns SQL data type out of range error state VerifyOdbcErrorState(SQL_HANDLE_STMT, stmt, kErrorStateS1004); -#endif // __APPLE__ +#else // Mac & Linux + ASSERT_EQ(SQL_SUCCESS, SQLGetTypeInfo(stmt, SQL_TYPE_TIMESTAMP)); +#endif } TEST_F(TypeInfoMockTest, TestSQLGetTypeInfoInvalidDataType) { From 549d4c230cfe246ec3ee3e0f5da86fc0e2017502 Mon Sep 17 00:00:00 2001 From: justing-bq <62349012+justing-bq@users.noreply.github.com> Date: Fri, 22 May 2026 10:54:09 -0700 Subject: [PATCH 2/2] Address review feedback --- cpp/src/arrow/flight/sql/odbc/tests/connection_attr_test.cc | 3 +-- cpp/src/arrow/flight/sql/odbc/tests/connection_info_test.cc | 4 ++-- cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.h | 1 - cpp/src/arrow/flight/sql/odbc/tests/statement_test.cc | 3 +-- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/cpp/src/arrow/flight/sql/odbc/tests/connection_attr_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/connection_attr_test.cc index 7f79c33eb85a..1f1a5e99d614 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/connection_attr_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/connection_attr_test.cc @@ -127,8 +127,7 @@ TYPED_TEST(ConnectionAttributeTest, TestSQLSetConnectAttrTraceDMOnly) { TYPED_TEST(ConnectionAttributePreConnectTest, TestSQLSetConnectAttrTracefileDMOnly) { // Verify DM-only attribute is handled by Driver Manager - // Use placeholder value as we want the call to fail, or else - // the driver manager will produce a trace file. + // Use placeholder value to avoid the driver manager from producing a trace file. std::wstring trace_file = L"invalid/file/path"; std::vector trace_file0(trace_file.begin(), trace_file.end()); diff --git a/cpp/src/arrow/flight/sql/odbc/tests/connection_info_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/connection_info_test.cc index a1116bb1c47e..232aa985c7e3 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/connection_info_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/connection_info_test.cc @@ -339,9 +339,9 @@ TYPED_TEST(ConnectionInfoTest, TestSQLGetInfoOdbcVer) { EXPECT_EQ(std::wstring(L"03.52.0000"), result); #elif defined(__linux__) EXPECT_EQ(std::wstring(L"03.52"), result); -#else // WINDOWS +#else // WINDOWS EXPECT_EQ(std::wstring(L"03.80.0000"), result); -#endif // __APPLE__ +#endif } TYPED_TEST(ConnectionInfoTest, TestSQLGetInfoParamArrayRowCounts) { diff --git a/cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.h b/cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.h index 845631b6cd32..f4de85f69938 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.h +++ b/cpp/src/arrow/flight/sql/odbc/tests/odbc_test_suite.h @@ -246,7 +246,6 @@ bool CompareConnPropertyMap(Connection::ConnPropertyMap map1, /// Get error message from ODBC driver using SQLGetDiagRec std::string GetOdbcErrorMessage(SQLSMALLINT handle_type, SQLHANDLE handle); -static constexpr std::string_view kErrorState00000 = "00000"; static constexpr std::string_view kErrorState01004 = "01004"; static constexpr std::string_view kErrorState01S02 = "01S02"; static constexpr std::string_view kErrorState01S07 = "01S07"; diff --git a/cpp/src/arrow/flight/sql/odbc/tests/statement_test.cc b/cpp/src/arrow/flight/sql/odbc/tests/statement_test.cc index b14eb676dd9c..f090e39f551a 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/statement_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/statement_test.cc @@ -1043,7 +1043,7 @@ TEST_F(StatementMockTest, TestSQLExecDirectVarbinaryTruncation) { ASSERT_EQ(SQL_SUCCESS, SQLGetData(this->stmt, 1, SQL_C_BINARY, &varbinary_val2[0], buf_len, &ind)); - EXPECT_EQ(static_cast('\xAB'), static_cast(varbinary_val[0])); + EXPECT_EQ(static_cast('\xAB'), static_cast(varbinary_val2[0])); EXPECT_EQ(1, ind); // Attempt to fetch data 3rd time @@ -1988,7 +1988,6 @@ TYPED_TEST(StatementTest, TestSQLMoreResultsInvalidFunctionSequence) { // without executing any queries #ifdef __linux__ ASSERT_EQ(SQL_NO_DATA, SQLMoreResults(this->stmt)); - VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, kErrorState00000); #else // Windows & Mac ASSERT_EQ(SQL_ERROR, SQLMoreResults(this->stmt)); VerifyOdbcErrorState(SQL_HANDLE_STMT, this->stmt, kErrorStateHY010);