From 17f2ff9f94532d75f873a69f938ab587eba527b8 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 11 Feb 2026 15:49:04 -0800 Subject: [PATCH 1/2] SQLError implementation in macOS * SQLError implementation for macOS Disable `SQLGetConnectOption` on macOS as it isn't required by macOS Excel to fetch data --- cpp/src/arrow/flight/sql/odbc/entry_points.cc | 12 +++++ cpp/src/arrow/flight/sql/odbc/odbc_api.cc | 51 ++++++++++++++++++- .../arrow/flight/sql/odbc/odbc_api_internal.h | 6 +++ .../flight/sql/odbc/tests/errors_test.cc | 45 ++++++++++------ .../flight/sql/odbc/tests/odbc_test_suite.h | 3 ++ 5 files changed, 101 insertions(+), 16 deletions(-) diff --git a/cpp/src/arrow/flight/sql/odbc/entry_points.cc b/cpp/src/arrow/flight/sql/odbc/entry_points.cc index 8e7c2e2be71..c03089ffcc6 100644 --- a/cpp/src/arrow/flight/sql/odbc/entry_points.cc +++ b/cpp/src/arrow/flight/sql/odbc/entry_points.cc @@ -83,6 +83,18 @@ SQLRETURN SQL_API SQLGetDiagRec(SQLSMALLINT handle_type, SQLHANDLE handle, buffer_length, text_length_ptr); } +#if defined(__APPLE__) +// macOS ODBC Driver Manager doesn't map SQLError to SQLGetDiagRec, so we need to +// implement SQLError for macOS. +// on Windows, SQLError mapping implemented by Driver Manager is preferred. +SQLRETURN SQL_API SQLError(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt, SQLWCHAR* sql_state, + SQLINTEGER* native_error_ptr, SQLWCHAR* message_text, + SQLSMALLINT buffer_length, SQLSMALLINT* text_length_ptr) { + return arrow::flight::sql::odbc::SQLError(env, conn, stmt, sql_state, native_error_ptr, + message_text, buffer_length, text_length_ptr); +} +#endif // __APPLE__ + SQLRETURN SQL_API SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER value_ptr, SQLINTEGER buffer_len, SQLINTEGER* str_len_ptr) { return arrow::flight::sql::odbc::SQLGetEnvAttr(env, attr, value_ptr, buffer_len, diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_api.cc b/cpp/src/arrow/flight/sql/odbc/odbc_api.cc index 5676b9b05ed..75b35b688aa 100644 --- a/cpp/src/arrow/flight/sql/odbc/odbc_api.cc +++ b/cpp/src/arrow/flight/sql/odbc/odbc_api.cc @@ -247,6 +247,56 @@ SQLRETURN SQLFreeStmt(SQLHSTMT handle, SQLUSMALLINT option) { return SQL_ERROR; } +#if defined(__APPLE__) +SQLRETURN SQLError(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt, SQLWCHAR* sql_state, + SQLINTEGER* native_error_ptr, SQLWCHAR* message_text, + SQLSMALLINT buffer_length, SQLSMALLINT* text_length_ptr) { + ARROW_LOG(DEBUG) << "SQLError called with env: " << env << ", conn: " << conn + << ", stmt: " << stmt + << ", sql_state: " << static_cast(sql_state) + << ", native_error_ptr: " << static_cast(native_error_ptr) + << ", message_text: " << static_cast(message_text) + << ", buffer_length: " << buffer_length + << ", text_length_ptr: " << static_cast(text_length_ptr); + + SQLSMALLINT handle_type; + SQLHANDLE handle; + + if (env) { + handle_type = SQL_HANDLE_ENV; + handle = static_cast(env); + } else if (conn) { + handle_type = SQL_HANDLE_DBC; + handle = static_cast(conn); + } else if (stmt) { + handle_type = SQL_HANDLE_STMT; + handle = static_cast(stmt); + } else { + return static_cast(SQL_INVALID_HANDLE); + } + + // Use the last record + SQLINTEGER diag_number; + SQLSMALLINT diag_number_length; + + SQLRETURN ret = arrow::flight::sql::odbc::SQLGetDiagField( + handle_type, handle, 0, SQL_DIAG_NUMBER, &diag_number, sizeof(SQLINTEGER), 0); + if (ret != SQL_SUCCESS) { + return ret; + } + + if (diag_number == 0) { + return SQL_NO_DATA; + } + + SQLSMALLINT rec_number = static_cast(diag_number); + + return arrow::flight::sql::odbc::SQLGetDiagRec( + handle_type, handle, rec_number, sql_state, native_error_ptr, message_text, + buffer_length, text_length_ptr); +} +#endif // __APPLE__ + inline bool IsValidStringFieldArgs(SQLPOINTER diag_info_ptr, SQLSMALLINT buffer_length, SQLSMALLINT* string_length_ptr, bool is_unicode) { const SQLSMALLINT char_size = is_unicode ? GetSqlWCharSize() : sizeof(char); @@ -736,7 +786,6 @@ SQLRETURN SQLGetConnectAttr(SQLHDBC conn, SQLINTEGER attribute, SQLPOINTER value << ", attribute: " << attribute << ", value_ptr: " << value_ptr << ", buffer_length: " << buffer_length << ", string_length_ptr: " << static_cast(string_length_ptr); - using ODBC::ODBCConnection; return ODBCConnection::ExecuteWithDiagnostics(conn, SQL_ERROR, [=]() { diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_api_internal.h b/cpp/src/arrow/flight/sql/odbc/odbc_api_internal.h index 4fea8569acb..f9d8d887cb8 100644 --- a/cpp/src/arrow/flight/sql/odbc/odbc_api_internal.h +++ b/cpp/src/arrow/flight/sql/odbc/odbc_api_internal.h @@ -31,6 +31,12 @@ namespace arrow::flight::sql::odbc { SQLHANDLE* result); [[nodiscard]] SQLRETURN SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle); [[nodiscard]] SQLRETURN SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT option); +#if defined(__APPLE__) +[[nodiscard]] SQLRETURN SQLError(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt, + SQLWCHAR* sql_state, SQLINTEGER* native_error_ptr, + SQLWCHAR* message_text, SQLSMALLINT buffer_length, + SQLSMALLINT* text_length_ptr); +#endif // __APPLE__ [[nodiscard]] SQLRETURN SQLGetDiagField(SQLSMALLINT handle_type, SQLHANDLE handle, SQLSMALLINT rec_number, SQLSMALLINT diag_identifier, 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 34a32738455..56c92e36419 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/errors_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/errors_test.cc @@ -47,6 +47,8 @@ using TestTypesHandle = ::testing::Types; TYPED_TEST_SUITE(ErrorsHandleTest, TestTypesHandle); +using ODBC::SqlWcharToString; + TYPED_TEST(ErrorsHandleTest, TestSQLGetDiagFieldWForConnectFailure) { // Invalid connect string std::string connect_str = this->GetInvalidConnectionString(); @@ -117,7 +119,7 @@ TYPED_TEST(ErrorsHandleTest, TestSQLGetDiagFieldWForConnectFailure) { sql_state_size * arrow::flight::sql::odbc::GetSqlWCharSize(), &sql_state_length)); - EXPECT_EQ(std::wstring(L"28000"), std::wstring(sql_state)); + EXPECT_EQ(kErrorState28000, SqlWcharToString(sql_state)); } TYPED_TEST(ErrorsHandleTest, DISABLED_TestSQLGetDiagFieldWForConnectFailureNTS) { @@ -216,7 +218,7 @@ TYPED_TEST(ErrorsTest, TestSQLGetDiagFieldWForDescriptorFailureFromDriverManager SQLGetDiagField(SQL_HANDLE_DESC, descriptor, RECORD_1, SQL_DIAG_SQLSTATE, sql_state, sql_state_size * GetSqlWCharSize(), &sql_state_length)); - EXPECT_EQ(std::wstring(L"IM001"), std::wstring(sql_state)); + EXPECT_EQ(kErrorStateIM001, SqlWcharToString(sql_state)); // Free descriptor handle EXPECT_EQ(SQL_SUCCESS, SQLFreeHandle(SQL_HANDLE_DESC, descriptor)); @@ -245,7 +247,7 @@ TYPED_TEST(ErrorsTest, TestSQLGetDiagRecForDescriptorFailureFromDriverManager) { EXPECT_EQ(0, native_error); // API not implemented error from driver manager - EXPECT_EQ(std::wstring(L"IM001"), std::wstring(sql_state)); + EXPECT_EQ(kErrorStateIM001, SqlWcharToString(sql_state)); EXPECT_FALSE(std::wstring(message).empty()); @@ -282,7 +284,7 @@ TYPED_TEST(ErrorsHandleTest, TestSQLGetDiagRecForConnectFailure) { EXPECT_EQ(200, native_error); - EXPECT_EQ(std::wstring(L"28000"), std::wstring(sql_state)); + EXPECT_EQ(kErrorState28000, SqlWcharToString(sql_state)); EXPECT_FALSE(std::wstring(message).empty()); } @@ -345,12 +347,12 @@ TYPED_TEST(ErrorsTest, TestSQLErrorEnvErrorFromDriverManager) { ASSERT_EQ(SQL_SUCCESS, SQLError(this->env, nullptr, nullptr, sql_state, &native_error, message, SQL_MAX_MESSAGE_LENGTH, &message_length)); - EXPECT_GT(message_length, 50); + EXPECT_GT(message_length, 40); EXPECT_EQ(0, native_error); // Function sequence error state from driver manager - EXPECT_EQ(std::wstring(L"HY010"), std::wstring(sql_state)); + EXPECT_EQ(kErrorStateHY010, SqlWcharToString(sql_state)); EXPECT_FALSE(std::wstring(message).empty()); } @@ -378,7 +380,7 @@ TYPED_TEST(ErrorsTest, TestSQLErrorConnError) { EXPECT_EQ(100, native_error); // optional feature not supported error state - EXPECT_EQ(std::wstring(L"HYC00"), std::wstring(sql_state)); + EXPECT_EQ(kErrorStateHYC00, SqlWcharToString(sql_state)); EXPECT_FALSE(std::wstring(message).empty()); } @@ -406,7 +408,7 @@ TYPED_TEST(ErrorsTest, TestSQLErrorStmtError) { EXPECT_EQ(100, native_error); - EXPECT_EQ(std::wstring(L"HY000"), std::wstring(sql_state)); + EXPECT_EQ(kErrorStateHY000, SqlWcharToString(sql_state)); EXPECT_FALSE(std::wstring(message).empty()); } @@ -442,7 +444,7 @@ TYPED_TEST(ErrorsTest, TestSQLErrorStmtWarning) { EXPECT_EQ(1000100, native_error); // Verify string truncation warning is reported - EXPECT_EQ(std::wstring(L"01004"), std::wstring(sql_state)); + EXPECT_EQ(kErrorState01004, SqlWcharToString(sql_state)); EXPECT_FALSE(std::wstring(message).empty()); } @@ -464,22 +466,34 @@ TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorEnvErrorODBCVer2FromDriverManager) { ASSERT_EQ(SQL_SUCCESS, SQLError(this->env, nullptr, nullptr, sql_state, &native_error, message, SQL_MAX_MESSAGE_LENGTH, &message_length)); - EXPECT_GT(message_length, 50); + EXPECT_GT(message_length, 40); EXPECT_EQ(0, native_error); // Function sequence error state from driver manager - EXPECT_EQ(std::wstring(L"S1010"), std::wstring(sql_state)); +#ifdef _WIN32 + // Windows Driver Manager returns S1010 + EXPECT_EQ(kErrorStateS1010, SqlWcharToString(sql_state)); +#else + // unix Driver Manager returns HY010 + EXPECT_EQ(kErrorStateHY010, SqlWcharToString(sql_state)); +#endif // _WIN32 EXPECT_FALSE(std::wstring(message).empty()); } -TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorConnErrorODBCVer2) { +#ifndef __APPLE__ +TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorConnError) { // Test ODBC 2.0 API SQLError with ODBC ver 2. // Known Windows Driver Manager (DM) behavior: // When application passes buffer length greater than SQL_MAX_MESSAGE_LENGTH (512), // DM passes 512 as buffer length to SQLError. + // Known macOS Driver Manager (DM) behavior: + // Attempts to call SQLGetConnectOption without redirecting the API call to + // SQLGetConnectAttr. SQLGetConnectOption is not implemented as it is not required by + // macOS Excel. + // Attempt to set unsupported attribute ASSERT_EQ(SQL_ERROR, SQLGetConnectAttr(this->conn, SQL_ATTR_TXN_ISOLATION, 0, 0, nullptr)); @@ -496,10 +510,11 @@ TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorConnErrorODBCVer2) { EXPECT_EQ(100, native_error); // optional feature not supported error state. Driver Manager maps state to S1C00 - EXPECT_EQ(std::wstring(L"S1C00"), std::wstring(sql_state)); + EXPECT_EQ(kErrorStateS1C00, SqlWcharToString(sql_state)); EXPECT_FALSE(std::wstring(message).empty()); } +#endif // __APPLE__ TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorStmtErrorODBCVer2) { // Test ODBC 2.0 API SQLError with ODBC ver 2. @@ -525,7 +540,7 @@ TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorStmtErrorODBCVer2) { EXPECT_EQ(100, native_error); // Driver Manager maps error state to S1000 - EXPECT_EQ(std::wstring(L"S1000"), std::wstring(sql_state)); + EXPECT_EQ(kErrorStateS1000, SqlWcharToString(sql_state)); EXPECT_FALSE(std::wstring(message).empty()); } @@ -561,7 +576,7 @@ TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorStmtWarningODBCVer2) { EXPECT_EQ(1000100, native_error); // Verify string truncation warning is reported - EXPECT_EQ(std::wstring(L"01004"), std::wstring(sql_state)); + EXPECT_EQ(kErrorState01004, SqlWcharToString(sql_state)); EXPECT_FALSE(std::wstring(message).empty()); } 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 3115cd62754..5d18d2e50c2 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 @@ -236,10 +236,13 @@ static constexpr std::string_view kErrorStateHY106 = "HY106"; static constexpr std::string_view kErrorStateHY114 = "HY114"; static constexpr std::string_view kErrorStateHY118 = "HY118"; static constexpr std::string_view kErrorStateHYC00 = "HYC00"; +static constexpr std::string_view kErrorStateIM001 = "IM001"; +static constexpr std::string_view kErrorStateS1000 = "S1000"; static constexpr std::string_view kErrorStateS1002 = "S1002"; static constexpr std::string_view kErrorStateS1004 = "S1004"; static constexpr std::string_view kErrorStateS1010 = "S1010"; static constexpr std::string_view kErrorStateS1090 = "S1090"; +static constexpr std::string_view kErrorStateS1C00 = "S1C00"; /// Verify ODBC Error State void VerifyOdbcErrorState(SQLSMALLINT handle_type, SQLHANDLE handle, From 039954aa796fa0c618378b1be9ba4a52198134ec Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 11 Feb 2026 16:08:00 -0800 Subject: [PATCH 2/2] Update errors_test.cc Co-authored-by: justing-bq --- .../flight/sql/odbc/tests/errors_test.cc | 65 ++++++++++++------- 1 file changed, 42 insertions(+), 23 deletions(-) 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 56c92e36419..6acec2fbfbc 100644 --- a/cpp/src/arrow/flight/sql/odbc/tests/errors_test.cc +++ b/cpp/src/arrow/flight/sql/odbc/tests/errors_test.cc @@ -92,9 +92,12 @@ TYPED_TEST(ErrorsHandleTest, TestSQLGetDiagFieldWForConnectFailure) { SQLWCHAR message_text[kOdbcBufferSize]; SQLSMALLINT message_text_length; - EXPECT_EQ(SQL_SUCCESS, - SQLGetDiagField(SQL_HANDLE_DBC, this->conn, RECORD_1, SQL_DIAG_MESSAGE_TEXT, - message_text, kOdbcBufferSize, &message_text_length)); + SQLRETURN ret = + SQLGetDiagField(SQL_HANDLE_DBC, this->conn, RECORD_1, SQL_DIAG_MESSAGE_TEXT, + message_text, kOdbcBufferSize, &message_text_length); + + // dependent on the size of the message it could output SQL_SUCCESS_WITH_INFO + EXPECT_TRUE(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO); EXPECT_GT(message_text_length, 100); @@ -116,8 +119,7 @@ TYPED_TEST(ErrorsHandleTest, TestSQLGetDiagFieldWForConnectFailure) { EXPECT_EQ( SQL_SUCCESS, SQLGetDiagField(SQL_HANDLE_DBC, this->conn, RECORD_1, SQL_DIAG_SQLSTATE, sql_state, - sql_state_size * arrow::flight::sql::odbc::GetSqlWCharSize(), - &sql_state_length)); + sql_state_size * GetSqlWCharSize(), &sql_state_length)); EXPECT_EQ(kErrorState28000, SqlWcharToString(sql_state)); } @@ -158,6 +160,8 @@ TYPED_TEST(ErrorsHandleTest, DISABLED_TestSQLGetDiagFieldWForConnectFailureNTS) EXPECT_GT(message_text_length, 100); } +// iODBC does not support application allocated descriptors. +#ifndef __APPLE__ TYPED_TEST(ErrorsTest, TestSQLGetDiagFieldWForDescriptorFailureFromDriverManager) { SQLHDESC descriptor; @@ -254,6 +258,7 @@ TYPED_TEST(ErrorsTest, TestSQLGetDiagRecForDescriptorFailureFromDriverManager) { // Free descriptor handle EXPECT_EQ(SQL_SUCCESS, SQLFreeHandle(SQL_HANDLE_DESC, descriptor)); } +#endif // __APPLE__ TYPED_TEST(ErrorsHandleTest, TestSQLGetDiagRecForConnectFailure) { // Invalid connect string @@ -307,11 +312,17 @@ TYPED_TEST(ErrorsTest, TestSQLGetDiagRecInputData) { 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, SQLGetDiagRec(0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr)); +#endif // __APPLE__ } -TYPED_TEST(ErrorsTest, TestSQLErrorInputData) { +TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorInputData) { // Test ODBC 2.0 API SQLError. Driver manager maps SQLError to SQLGetDiagRec. // SQLError does not post diagnostic records for itself. @@ -322,8 +333,13 @@ TYPED_TEST(ErrorsTest, TestSQLErrorInputData) { EXPECT_EQ(SQL_NO_DATA, SQLError(nullptr, this->conn, nullptr, nullptr, nullptr, nullptr, 0, nullptr)); +#ifdef __APPLE__ + EXPECT_EQ(SQL_NO_DATA, SQLError(SQL_NULL_HENV, this->conn, this->stmt, nullptr, nullptr, + nullptr, 0, nullptr)); +#else EXPECT_EQ(SQL_NO_DATA, SQLError(nullptr, nullptr, this->stmt, nullptr, nullptr, nullptr, 0, nullptr)); +#endif // __APPLE__ // Invalid handle EXPECT_EQ(SQL_INVALID_HANDLE, @@ -364,9 +380,8 @@ TYPED_TEST(ErrorsTest, TestSQLErrorConnError) { // DM passes 512 as buffer length to SQLError. // Attempt to set unsupported attribute - SQLRETURN ret = SQLGetConnectAttr(this->conn, SQL_ATTR_TXN_ISOLATION, 0, 0, nullptr); - - ASSERT_EQ(SQL_ERROR, ret); + ASSERT_EQ(SQL_ERROR, + SQLGetConnectAttr(this->conn, SQL_ATTR_TXN_ISOLATION, 0, 0, nullptr)); SQLWCHAR sql_state[6] = {0}; SQLINTEGER native_error = 0; @@ -401,8 +416,10 @@ TYPED_TEST(ErrorsTest, TestSQLErrorStmtError) { SQLINTEGER native_error = 0; SQLWCHAR message[SQL_MAX_MESSAGE_LENGTH] = {0}; SQLSMALLINT message_length = 0; - ASSERT_EQ(SQL_SUCCESS, SQLError(nullptr, nullptr, this->stmt, sql_state, &native_error, - message, SQL_MAX_MESSAGE_LENGTH, &message_length)); + SQLRETURN ret = SQLError(nullptr, this->conn, this->stmt, sql_state, &native_error, + message, SQL_MAX_MESSAGE_LENGTH, &message_length); + + EXPECT_TRUE(ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO); EXPECT_GT(message_length, 70); @@ -436,8 +453,9 @@ TYPED_TEST(ErrorsTest, TestSQLErrorStmtWarning) { SQLINTEGER native_error = 0; SQLWCHAR message[SQL_MAX_MESSAGE_LENGTH] = {0}; SQLSMALLINT message_length = 0; - ASSERT_EQ(SQL_SUCCESS, SQLError(nullptr, nullptr, this->stmt, sql_state, &native_error, - message, SQL_MAX_MESSAGE_LENGTH, &message_length)); + ASSERT_EQ(SQL_SUCCESS, + SQLError(SQL_NULL_HENV, this->conn, this->stmt, sql_state, &native_error, + message, SQL_MAX_MESSAGE_LENGTH, &message_length)); EXPECT_GT(message_length, 50); @@ -449,7 +467,7 @@ TYPED_TEST(ErrorsTest, TestSQLErrorStmtWarning) { EXPECT_FALSE(std::wstring(message).empty()); } -TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorEnvErrorODBCVer2FromDriverManager) { +TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorEnvErrorFromDriverManager) { // Test ODBC 2.0 API SQLError with ODBC ver 2. // Known Windows Driver Manager (DM) behavior: // When application passes buffer length greater than SQL_MAX_MESSAGE_LENGTH (512), @@ -516,13 +534,13 @@ TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorConnError) { } #endif // __APPLE__ -TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorStmtErrorODBCVer2) { +TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorStmtError) { // Test ODBC 2.0 API SQLError with ODBC ver 2. // Known Windows Driver Manager (DM) behavior: // When application passes buffer length greater than SQL_MAX_MESSAGE_LENGTH (512), // DM passes 512 as buffer length to SQLError. - std::wstring wsql = L"1"; + std::wstring wsql = L"SELECT * from non_existent_table;"; std::vector sql0(wsql.begin(), wsql.end()); ASSERT_EQ(SQL_ERROR, @@ -530,11 +548,11 @@ TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorStmtErrorODBCVer2) { SQLWCHAR sql_state[6] = {0}; SQLINTEGER native_error = 0; - SQLWCHAR message[SQL_MAX_MESSAGE_LENGTH] = {0}; SQLSMALLINT message_length = 0; - ASSERT_EQ(SQL_SUCCESS, SQLError(nullptr, nullptr, this->stmt, sql_state, &native_error, - message, SQL_MAX_MESSAGE_LENGTH, &message_length)); - + SQLWCHAR message[SQL_MAX_MESSAGE_LENGTH] = {0}; + ASSERT_EQ(SQL_SUCCESS, + SQLError(SQL_NULL_HENV, this->conn, this->stmt, sql_state, &native_error, + message, SQL_MAX_MESSAGE_LENGTH, &message_length)); EXPECT_GT(message_length, 70); EXPECT_EQ(100, native_error); @@ -545,7 +563,7 @@ TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorStmtErrorODBCVer2) { EXPECT_FALSE(std::wstring(message).empty()); } -TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorStmtWarningODBCVer2) { +TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorStmtWarning) { // Test ODBC 2.0 API SQLError. std::wstring wsql = L"SELECT 'VERY LONG STRING here' AS string_col;"; @@ -568,8 +586,9 @@ TYPED_TEST(ErrorsOdbcV2Test, TestSQLErrorStmtWarningODBCVer2) { SQLINTEGER native_error = 0; SQLWCHAR message[SQL_MAX_MESSAGE_LENGTH] = {0}; SQLSMALLINT message_length = 0; - ASSERT_EQ(SQL_SUCCESS, SQLError(nullptr, nullptr, this->stmt, sql_state, &native_error, - message, SQL_MAX_MESSAGE_LENGTH, &message_length)); + ASSERT_EQ(SQL_SUCCESS, + SQLError(SQL_NULL_HENV, this->conn, this->stmt, sql_state, &native_error, + message, SQL_MAX_MESSAGE_LENGTH, &message_length)); EXPECT_GT(message_length, 50);