This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new f83c5541b1 GH-49250: [C++][FlightRPC] ODBC: SQLError for macOS (#49251)
f83c5541b1 is described below

commit f83c5541b1198e250f78463b92daabbc2e2b22b3
Author: Alina (Xi) Li <[email protected]>
AuthorDate: Thu Mar 5 18:32:05 2026 -0800

    GH-49250: [C++][FlightRPC] ODBC: SQLError for macOS (#49251)
    
    ### Rationale for this change
    #49250
    ### What changes are included in this PR?
    - Implement SQLError for macOS
    - Update SQLError related tests for macOS
    
    ### Are these changes tested?
    - SQLError Tests are tested locally on macOS
    
    ### Are there any user-facing changes?
    N/A
    * GitHub Issue: #49250
    
    Authored-by: Alina (Xi) Li <[email protected]>
    Signed-off-by: David Li <[email protected]>
---
 cpp/src/arrow/flight/sql/odbc/entry_points.cc      |  12 +++
 cpp/src/arrow/flight/sql/odbc/odbc_api.cc          |  51 ++++++++++-
 cpp/src/arrow/flight/sql/odbc/odbc_api_internal.h  |   6 ++
 cpp/src/arrow/flight/sql/odbc/tests/errors_test.cc | 100 ++++++++++++++-------
 .../arrow/flight/sql/odbc/tests/odbc_test_suite.h  |   2 +
 5 files changed, 137 insertions(+), 34 deletions(-)

diff --git a/cpp/src/arrow/flight/sql/odbc/entry_points.cc 
b/cpp/src/arrow/flight/sql/odbc/entry_points.cc
index 8e7c2e2be7..c03089ffcc 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 5676b9b05e..75b35b688a 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<const void*>(sql_state)
+                   << ", native_error_ptr: " << static_cast<const 
void*>(native_error_ptr)
+                   << ", message_text: " << static_cast<const 
void*>(message_text)
+                   << ", buffer_length: " << buffer_length
+                   << ", text_length_ptr: " << static_cast<const 
void*>(text_length_ptr);
+
+  SQLSMALLINT handle_type;
+  SQLHANDLE handle;
+
+  if (env) {
+    handle_type = SQL_HANDLE_ENV;
+    handle = static_cast<SQLHANDLE>(env);
+  } else if (conn) {
+    handle_type = SQL_HANDLE_DBC;
+    handle = static_cast<SQLHANDLE>(conn);
+  } else if (stmt) {
+    handle_type = SQL_HANDLE_STMT;
+    handle = static_cast<SQLHANDLE>(stmt);
+  } else {
+    return static_cast<SQLRETURN>(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<SQLSMALLINT>(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<const void*>(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 4fea8569ac..f9d8d887cb 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 36f91f827e..6acec2fbfb 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<FlightSQLOdbcEnvConnHandleMockTestBase,
                                          
FlightSQLOdbcEnvConnHandleRemoteTestBase>;
 TYPED_TEST_SUITE(ErrorsHandleTest, TestTypesHandle);
 
+using ODBC::SqlWcharToString;
+
 TYPED_TEST(ErrorsHandleTest, TestSQLGetDiagFieldWForConnectFailure) {
   // Invalid connect string
   std::string connect_str = this->GetInvalidConnectionString();
@@ -90,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);
 
@@ -114,10 +119,9 @@ 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(std::wstring(L"28000"), std::wstring(sql_state));
+  EXPECT_EQ(kErrorState28000, SqlWcharToString(sql_state));
 }
 
 TYPED_TEST(ErrorsHandleTest, 
DISABLED_TestSQLGetDiagFieldWForConnectFailureNTS) {
@@ -156,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;
 
@@ -216,7 +222,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,13 +251,14 @@ 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());
 
   // Free descriptor handle
   EXPECT_EQ(SQL_SUCCESS, SQLFreeHandle(SQL_HANDLE_DESC, descriptor));
 }
+#endif  // __APPLE__
 
 TYPED_TEST(ErrorsHandleTest, TestSQLGetDiagRecForConnectFailure) {
   // Invalid connect string
@@ -282,7 +289,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());
 }
@@ -305,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.
 
@@ -320,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,
@@ -345,12 +363,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());
 }
@@ -362,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;
@@ -378,7 +395,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());
 }
@@ -399,14 +416,16 @@ 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);
 
   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());
 }
@@ -434,20 +453,21 @@ 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);
 
   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());
 }
 
-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),
@@ -464,22 +484,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,12 +528,13 @@ 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) {
+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),
@@ -525,12 +558,12 @@ 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());
 }
 
-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;";
@@ -553,15 +586,16 @@ 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);
 
   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 419f698c5d..5d18d2e50c 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
@@ -237,10 +237,12 @@ 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,

Reply via email to