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

kou 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 d0e098fca7 GH-46575: [C++][FlightRPC] ODBC Diagnostics Report (#47763)
d0e098fca7 is described below

commit d0e098fca7c4452a14b8e9fa22efee9f31454adb
Author: Alina (Xi) Li <[email protected]>
AuthorDate: Tue Oct 28 18:20:12 2025 -0700

    GH-46575: [C++][FlightRPC] ODBC Diagnostics Report (#47763)
    
    ### Rationale for this change
    ODBC needs to provide diagnostic information so users can debug the error
    
    ### What changes are included in this PR?
    - Implementation of  SQLGetDiagField and SQLGetDiagRec
    Tests are included in separate PR (see 
https://github.com/apache/arrow/pull/47764)
    
    ### Are these changes tested?
    Tests will be in a separate PR (see 
https://github.com/apache/arrow/pull/47764). Other APIs depend on 
SQLGetDiagField and SQLGetDiagRec to get error reporting functionality, and 
tests for SQLGetDiagField and SQLGetDiagRec depend on other APIs for creating 
errors, as these diagnostic APIs alone do not initiate any errors.
    
    Changes tested locally
    
    ### Are there any user-facing changes?
    No
    
    * GitHub Issue: #46575
    
    Authored-by: Alina (Xi) Li <[email protected]>
    Signed-off-by: Sutou Kouhei <[email protected]>
---
 cpp/src/arrow/flight/sql/odbc/odbc_api.cc         | 357 +++++++++++++++++++++-
 cpp/src/arrow/flight/sql/odbc/odbc_api_internal.h | 166 +++++-----
 2 files changed, 444 insertions(+), 79 deletions(-)

diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_api.cc 
b/cpp/src/arrow/flight/sql/odbc/odbc_api.cc
index ade3ecbe2b..01780f0efe 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_api.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_api.cc
@@ -218,6 +218,20 @@ SQLRETURN SQLFreeStmt(SQLHSTMT handle, SQLUSMALLINT 
option) {
   return SQL_INVALID_HANDLE;
 }
 
+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);
+  const bool has_valid_buffer =
+      buffer_length == SQL_NTS || (buffer_length >= 0 && buffer_length % 
char_size == 0);
+
+  // regardless of capacity return false if invalid
+  if (diag_info_ptr && !has_valid_buffer) {
+    return false;
+  }
+
+  return has_valid_buffer || string_length_ptr;
+}
+
 SQLRETURN SQLGetDiagField(SQLSMALLINT handle_type, SQLHANDLE handle,
                           SQLSMALLINT rec_number, SQLSMALLINT diag_identifier,
                           SQLPOINTER diag_info_ptr, SQLSMALLINT buffer_length,
@@ -229,8 +243,258 @@ SQLRETURN SQLGetDiagField(SQLSMALLINT handle_type, 
SQLHANDLE handle,
                    << ", diag_info_ptr: " << diag_info_ptr
                    << ", buffer_length: " << buffer_length << ", 
string_length_ptr: "
                    << static_cast<const void*>(string_length_ptr);
-  // GH-46575 TODO: Implement SQLGetDiagField
-  return SQL_INVALID_HANDLE;
+  // GH-46575 TODO: Add tests for SQLGetDiagField
+  using ODBC::GetStringAttribute;
+  using ODBC::ODBCConnection;
+  using ODBC::ODBCDescriptor;
+  using ODBC::ODBCEnvironment;
+  using ODBC::ODBCStatement;
+
+  if (!handle) {
+    return SQL_INVALID_HANDLE;
+  }
+
+  if (!diag_info_ptr && !string_length_ptr) {
+    return SQL_ERROR;
+  }
+
+  // If buffer length derived from null terminated string
+  if (diag_info_ptr && buffer_length == SQL_NTS) {
+    const wchar_t* str = reinterpret_cast<wchar_t*>(diag_info_ptr);
+    buffer_length = wcslen(str) * GetSqlWCharSize();
+  }
+
+  // Set character type to be Unicode by default
+  const bool is_unicode = true;
+  Diagnostics* diagnostics = nullptr;
+
+  switch (handle_type) {
+    case SQL_HANDLE_ENV: {
+      ODBCEnvironment* environment = 
reinterpret_cast<ODBCEnvironment*>(handle);
+      diagnostics = &environment->GetDiagnostics();
+      break;
+    }
+
+    case SQL_HANDLE_DBC: {
+      ODBCConnection* connection = reinterpret_cast<ODBCConnection*>(handle);
+      diagnostics = &connection->GetDiagnostics();
+      break;
+    }
+
+    case SQL_HANDLE_DESC: {
+      ODBCDescriptor* descriptor = reinterpret_cast<ODBCDescriptor*>(handle);
+      diagnostics = &descriptor->GetDiagnostics();
+      break;
+    }
+
+    case SQL_HANDLE_STMT: {
+      ODBCStatement* statement = reinterpret_cast<ODBCStatement*>(handle);
+      diagnostics = &statement->GetDiagnostics();
+      break;
+    }
+
+    default:
+      return SQL_ERROR;
+  }
+
+  if (!diagnostics) {
+    return SQL_ERROR;
+  }
+
+  // Retrieve and return if header level diagnostics
+  switch (diag_identifier) {
+    case SQL_DIAG_NUMBER: {
+      if (diag_info_ptr) {
+        *static_cast<SQLINTEGER*>(diag_info_ptr) =
+            static_cast<SQLINTEGER>(diagnostics->GetRecordCount());
+      }
+
+      if (string_length_ptr) {
+        *string_length_ptr = sizeof(SQLINTEGER);
+      }
+
+      return SQL_SUCCESS;
+    }
+
+    // Driver manager implements SQL_DIAG_RETURNCODE
+    case SQL_DIAG_RETURNCODE: {
+      return SQL_SUCCESS;
+    }
+
+    case SQL_DIAG_CURSOR_ROW_COUNT: {
+      if (handle_type == SQL_HANDLE_STMT) {
+        if (diag_info_ptr) {
+          // Will always be 0 if only SELECT supported
+          *static_cast<SQLLEN*>(diag_info_ptr) = 0;
+        }
+
+        if (string_length_ptr) {
+          *string_length_ptr = sizeof(SQLLEN);
+        }
+
+        return SQL_SUCCESS;
+      }
+
+      return SQL_ERROR;
+    }
+
+    // Not supported
+    case SQL_DIAG_DYNAMIC_FUNCTION:
+    case SQL_DIAG_DYNAMIC_FUNCTION_CODE: {
+      if (handle_type == SQL_HANDLE_STMT) {
+        return SQL_SUCCESS;
+      }
+
+      return SQL_ERROR;
+    }
+
+    case SQL_DIAG_ROW_COUNT: {
+      if (handle_type == SQL_HANDLE_STMT) {
+        if (diag_info_ptr) {
+          // Will always be 0 if only SELECT is supported
+          *static_cast<SQLLEN*>(diag_info_ptr) = 0;
+        }
+
+        if (string_length_ptr) {
+          *string_length_ptr = sizeof(SQLLEN);
+        }
+
+        return SQL_SUCCESS;
+      }
+
+      return SQL_ERROR;
+    }
+  }
+
+  // If not a diagnostic header field then the record number must be 1 or 
greater
+  if (rec_number < 1) {
+    return SQL_ERROR;
+  }
+
+  // Retrieve record level diagnostics from specified 1 based record
+  const uint32_t record_index = static_cast<uint32_t>(rec_number - 1);
+  if (!diagnostics->HasRecord(record_index)) {
+    return SQL_NO_DATA;
+  }
+
+  // Retrieve record field data
+  switch (diag_identifier) {
+    case SQL_DIAG_MESSAGE_TEXT: {
+      if (IsValidStringFieldArgs(diag_info_ptr, buffer_length, 
string_length_ptr,
+                                 is_unicode)) {
+        const std::string& message = diagnostics->GetMessageText(record_index);
+        return GetStringAttribute(is_unicode, message, true, diag_info_ptr, 
buffer_length,
+                                  string_length_ptr, *diagnostics);
+      }
+
+      return SQL_ERROR;
+    }
+
+    case SQL_DIAG_NATIVE: {
+      if (diag_info_ptr) {
+        *static_cast<SQLINTEGER*>(diag_info_ptr) =
+            diagnostics->GetNativeError(record_index);
+      }
+
+      if (string_length_ptr) {
+        *string_length_ptr = sizeof(SQLINTEGER);
+      }
+
+      return SQL_SUCCESS;
+    }
+
+    case SQL_DIAG_SERVER_NAME: {
+      if (IsValidStringFieldArgs(diag_info_ptr, buffer_length, 
string_length_ptr,
+                                 is_unicode)) {
+        switch (handle_type) {
+          case SQL_HANDLE_DBC: {
+            ODBCConnection* connection = 
reinterpret_cast<ODBCConnection*>(handle);
+            std::string dsn = connection->GetDSN();
+            return GetStringAttribute(is_unicode, dsn, true, diag_info_ptr, 
buffer_length,
+                                      string_length_ptr, *diagnostics);
+          }
+
+          case SQL_HANDLE_DESC: {
+            ODBCDescriptor* descriptor = 
reinterpret_cast<ODBCDescriptor*>(handle);
+            ODBCConnection* connection = &descriptor->GetConnection();
+            std::string dsn = connection->GetDSN();
+            return GetStringAttribute(is_unicode, dsn, true, diag_info_ptr, 
buffer_length,
+                                      string_length_ptr, *diagnostics);
+            break;
+          }
+
+          case SQL_HANDLE_STMT: {
+            ODBCStatement* statement = 
reinterpret_cast<ODBCStatement*>(handle);
+            ODBCConnection* connection = &statement->GetConnection();
+            std::string dsn = connection->GetDSN();
+            return GetStringAttribute(is_unicode, dsn, true, diag_info_ptr, 
buffer_length,
+                                      string_length_ptr, *diagnostics);
+          }
+
+          default:
+            return SQL_ERROR;
+        }
+      }
+
+      return SQL_ERROR;
+    }
+
+    case SQL_DIAG_SQLSTATE: {
+      if (IsValidStringFieldArgs(diag_info_ptr, buffer_length, 
string_length_ptr,
+                                 is_unicode)) {
+        const std::string& state = diagnostics->GetSQLState(record_index);
+        return GetStringAttribute(is_unicode, state, true, diag_info_ptr, 
buffer_length,
+                                  string_length_ptr, *diagnostics);
+      }
+
+      return SQL_ERROR;
+    }
+
+    // Return valid dummy variable for unimplemented field
+    case SQL_DIAG_COLUMN_NUMBER: {
+      if (diag_info_ptr) {
+        *static_cast<SQLINTEGER*>(diag_info_ptr) = SQL_NO_COLUMN_NUMBER;
+      }
+
+      if (string_length_ptr) {
+        *string_length_ptr = sizeof(SQLINTEGER);
+      }
+
+      return SQL_SUCCESS;
+    }
+
+    // Return empty string dummy variable for unimplemented fields
+    case SQL_DIAG_CLASS_ORIGIN:
+    case SQL_DIAG_CONNECTION_NAME:
+    case SQL_DIAG_SUBCLASS_ORIGIN: {
+      if (IsValidStringFieldArgs(diag_info_ptr, buffer_length, 
string_length_ptr,
+                                 is_unicode)) {
+        return GetStringAttribute(is_unicode, "", true, diag_info_ptr, 
buffer_length,
+                                  string_length_ptr, *diagnostics);
+      }
+
+      return SQL_ERROR;
+    }
+
+    // Return valid dummy variable for unimplemented field
+    case SQL_DIAG_ROW_NUMBER: {
+      if (diag_info_ptr) {
+        *static_cast<SQLLEN*>(diag_info_ptr) = SQL_NO_ROW_NUMBER;
+      }
+
+      if (string_length_ptr) {
+        *string_length_ptr = sizeof(SQLLEN);
+      }
+
+      return SQL_SUCCESS;
+    }
+
+    default: {
+      return SQL_ERROR;
+    }
+  }
+
+  return SQL_ERROR;
 }
 
 SQLRETURN SQLGetDiagRec(SQLSMALLINT handle_type, SQLHANDLE handle, SQLSMALLINT 
rec_number,
@@ -244,8 +508,93 @@ SQLRETURN SQLGetDiagRec(SQLSMALLINT handle_type, SQLHANDLE 
handle, SQLSMALLINT r
                    << ", message_text: " << static_cast<const 
void*>(message_text)
                    << ", buffer_length: " << buffer_length
                    << ", text_length_ptr: " << static_cast<const 
void*>(text_length_ptr);
-  // GH-46575 TODO: Implement SQLGetDiagRec
-  return SQL_INVALID_HANDLE;
+  // GH-46575 TODO: Add tests for SQLGetDiagRec
+  using arrow::flight::sql::odbc::Diagnostics;
+  using ODBC::GetStringAttribute;
+  using ODBC::ODBCConnection;
+  using ODBC::ODBCDescriptor;
+  using ODBC::ODBCEnvironment;
+  using ODBC::ODBCStatement;
+
+  if (!handle) {
+    return SQL_INVALID_HANDLE;
+  }
+
+  // Record number must be greater or equal to 1
+  if (rec_number < 1 || buffer_length < 0) {
+    return SQL_ERROR;
+  }
+
+  // Set character type to be Unicode by default
+  const bool is_unicode = true;
+  Diagnostics* diagnostics = nullptr;
+
+  switch (handle_type) {
+    case SQL_HANDLE_ENV: {
+      auto* environment = ODBCEnvironment::Of(handle);
+      diagnostics = &environment->GetDiagnostics();
+      break;
+    }
+
+    case SQL_HANDLE_DBC: {
+      auto* connection = ODBCConnection::Of(handle);
+      diagnostics = &connection->GetDiagnostics();
+      break;
+    }
+
+    case SQL_HANDLE_DESC: {
+      auto* descriptor = ODBCDescriptor::Of(handle);
+      diagnostics = &descriptor->GetDiagnostics();
+      break;
+    }
+
+    case SQL_HANDLE_STMT: {
+      auto* statement = ODBCStatement::Of(handle);
+      diagnostics = &statement->GetDiagnostics();
+      break;
+    }
+
+    default:
+      return SQL_INVALID_HANDLE;
+  }
+
+  if (!diagnostics) {
+    return SQL_ERROR;
+  }
+
+  // Convert from ODBC 1 based record number to internal diagnostics 0 indexed 
storage
+  const size_t record_index = static_cast<size_t>(rec_number - 1);
+  if (!diagnostics->HasRecord(record_index)) {
+    return SQL_NO_DATA;
+  }
+
+  if (sql_state) {
+    // The length of the sql state is always 5 characters plus null
+    SQLSMALLINT size = 6;
+    const std::string& state = diagnostics->GetSQLState(record_index);
+
+    // Microsoft documentation does not mention
+    // any SQLGetDiagRec return value that is associated with `sql_state` 
buffer, so
+    // the return value for writing `sql_state` buffer is ignored by the 
driver.
+    ARROW_UNUSED(GetStringAttribute(is_unicode, state, false, sql_state, size, 
&size,
+                                    *diagnostics));
+  }
+
+  if (native_error_ptr) {
+    *native_error_ptr = diagnostics->GetNativeError(record_index);
+  }
+
+  if (message_text || text_length_ptr) {
+    const std::string& message = diagnostics->GetMessageText(record_index);
+
+    // According to Microsoft documentation,
+    // SQL_SUCCESS_WITH_INFO should be returned if `*message_text` buffer was 
too
+    // small to hold the requested diagnostic message.
+    return GetStringAttribute(is_unicode, message, false, message_text, 
buffer_length,
+                              text_length_ptr, *diagnostics);
+  }
+
+  return SQL_SUCCESS;
 }
 
 SQLRETURN SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER value_ptr,
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 53273a5b6d..4fea8569ac 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_api_internal.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_api_internal.h
@@ -27,79 +27,95 @@
 //
 //  Define internal ODBC API function headers.
 namespace arrow::flight::sql::odbc {
-SQLRETURN SQLAllocHandle(SQLSMALLINT type, SQLHANDLE parent, SQLHANDLE* 
result);
-SQLRETURN SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle);
-SQLRETURN SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT option);
-SQLRETURN SQLGetDiagField(SQLSMALLINT handle_type, SQLHANDLE handle,
-                          SQLSMALLINT rec_number, SQLSMALLINT diag_identifier,
-                          SQLPOINTER diag_info_ptr, SQLSMALLINT buffer_length,
-                          SQLSMALLINT* string_length_ptr);
-SQLRETURN SQLGetDiagRec(SQLSMALLINT handle_type, SQLHANDLE handle, SQLSMALLINT 
rec_number,
-                        SQLWCHAR* sql_state, SQLINTEGER* native_error_ptr,
-                        SQLWCHAR* message_text, SQLSMALLINT buffer_length,
-                        SQLSMALLINT* text_length_ptr);
-SQLRETURN SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER value_ptr,
-                        SQLINTEGER buffer_len, SQLINTEGER* str_len_ptr);
-SQLRETURN SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER value_ptr,
-                        SQLINTEGER str_len);
-SQLRETURN SQLGetConnectAttr(SQLHDBC conn, SQLINTEGER attribute, SQLPOINTER 
value_ptr,
-                            SQLINTEGER buffer_length, SQLINTEGER* 
string_length_ptr);
-SQLRETURN SQLSetConnectAttr(SQLHDBC conn, SQLINTEGER attr, SQLPOINTER value,
-                            SQLINTEGER value_len);
-SQLRETURN SQLDriverConnect(SQLHDBC conn, SQLHWND window_handle,
-                           SQLWCHAR* in_connection_string,
-                           SQLSMALLINT in_connection_string_len,
-                           SQLWCHAR* out_connection_string,
-                           SQLSMALLINT out_connection_string_buffer_len,
-                           SQLSMALLINT* out_connection_string_len,
-                           SQLUSMALLINT driver_completion);
-SQLRETURN SQLConnect(SQLHDBC conn, SQLWCHAR* dsn_name, SQLSMALLINT 
dsn_name_len,
-                     SQLWCHAR* user_name, SQLSMALLINT user_name_len, SQLWCHAR* 
password,
-                     SQLSMALLINT password_len);
-SQLRETURN SQLDisconnect(SQLHDBC conn);
-SQLRETURN SQLGetInfo(SQLHDBC conn, SQLUSMALLINT info_type, SQLPOINTER 
info_value_ptr,
-                     SQLSMALLINT buf_len, SQLSMALLINT* length);
-SQLRETURN SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attribute, SQLPOINTER 
value_ptr,
-                         SQLINTEGER buffer_length, SQLINTEGER* 
string_length_ptr);
-SQLRETURN SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attribute, SQLPOINTER 
value_ptr,
-                         SQLINTEGER stringLength);
-SQLRETURN SQLExecDirect(SQLHSTMT stmt, SQLWCHAR* queryText, SQLINTEGER 
text_length);
-SQLRETURN SQLPrepare(SQLHSTMT stmt, SQLWCHAR* queryText, SQLINTEGER 
text_length);
-SQLRETURN SQLExecute(SQLHSTMT stmt);
-SQLRETURN SQLFetch(SQLHSTMT stmt);
-SQLRETURN SQLExtendedFetch(SQLHSTMT stmt, SQLUSMALLINT fetch_orientation,
-                           SQLLEN fetch_offset, SQLULEN* row_count_ptr,
-                           SQLUSMALLINT* row_status_array);
-SQLRETURN SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT fetch_orientation,
-                         SQLLEN fetch_offset);
-SQLRETURN SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT record_number, SQLSMALLINT 
c_type,
-                     SQLPOINTER data_ptr, SQLLEN buffer_length, SQLLEN* 
indicator_ptr);
-SQLRETURN SQLCloseCursor(SQLHSTMT stmt);
-SQLRETURN SQLGetData(SQLHSTMT stmt, SQLUSMALLINT record_number, SQLSMALLINT 
c_type,
-                     SQLPOINTER data_ptr, SQLLEN buffer_length, SQLLEN* 
indicator_ptr);
-SQLRETURN SQLMoreResults(SQLHSTMT stmt);
-SQLRETURN SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT* column_count_ptr);
-SQLRETURN SQLRowCount(SQLHSTMT stmt, SQLLEN* row_count_ptr);
-SQLRETURN SQLTables(SQLHSTMT stmt, SQLWCHAR* catalog_name,
-                    SQLSMALLINT catalog_name_length, SQLWCHAR* schema_name,
-                    SQLSMALLINT schema_name_length, SQLWCHAR* table_name,
-                    SQLSMALLINT table_name_length, SQLWCHAR* table_type,
-                    SQLSMALLINT table_type_length);
-SQLRETURN SQLColumns(SQLHSTMT stmt, SQLWCHAR* catalog_name,
-                     SQLSMALLINT catalog_name_length, SQLWCHAR* schema_name,
-                     SQLSMALLINT schema_name_length, SQLWCHAR* table_name,
-                     SQLSMALLINT table_name_length, SQLWCHAR* column_name,
-                     SQLSMALLINT column_name_length);
-SQLRETURN SQLColAttribute(SQLHSTMT stmt, SQLUSMALLINT record_number,
-                          SQLUSMALLINT field_identifier,
-                          SQLPOINTER character_attribute_ptr, SQLSMALLINT 
buffer_length,
-                          SQLSMALLINT* output_length, SQLLEN* 
numeric_attribute_ptr);
-SQLRETURN SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT dataType);
-SQLRETURN SQLNativeSql(SQLHDBC conn, SQLWCHAR* in_statement_text,
-                       SQLINTEGER in_statement_text_length, SQLWCHAR* 
out_statement_text,
-                       SQLINTEGER buffer_length, SQLINTEGER* 
out_statement_text_length);
-SQLRETURN SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT column_number, SQLWCHAR* 
column_name,
-                         SQLSMALLINT buffer_length, SQLSMALLINT* 
name_length_ptr,
-                         SQLSMALLINT* data_type_ptr, SQLULEN* column_size_ptr,
-                         SQLSMALLINT* decimal_digits_ptr, SQLSMALLINT* 
nullable_ptr);
+[[nodiscard]] SQLRETURN SQLAllocHandle(SQLSMALLINT type, SQLHANDLE parent,
+                                       SQLHANDLE* result);
+[[nodiscard]] SQLRETURN SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle);
+[[nodiscard]] SQLRETURN SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT option);
+[[nodiscard]] SQLRETURN SQLGetDiagField(SQLSMALLINT handle_type, SQLHANDLE 
handle,
+                                        SQLSMALLINT rec_number,
+                                        SQLSMALLINT diag_identifier,
+                                        SQLPOINTER diag_info_ptr,
+                                        SQLSMALLINT buffer_length,
+                                        SQLSMALLINT* string_length_ptr);
+[[nodiscard]] SQLRETURN SQLGetDiagRec(SQLSMALLINT handle_type, SQLHANDLE 
handle,
+                                      SQLSMALLINT rec_number, SQLWCHAR* 
sql_state,
+                                      SQLINTEGER* native_error_ptr,
+                                      SQLWCHAR* message_text, SQLSMALLINT 
buffer_length,
+                                      SQLSMALLINT* text_length_ptr);
+[[nodiscard]] SQLRETURN SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER 
value_ptr,
+                                      SQLINTEGER buffer_len, SQLINTEGER* 
str_len_ptr);
+[[nodiscard]] SQLRETURN SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER 
value_ptr,
+                                      SQLINTEGER str_len);
+[[nodiscard]] SQLRETURN SQLGetConnectAttr(SQLHDBC conn, SQLINTEGER attribute,
+                                          SQLPOINTER value_ptr, SQLINTEGER 
buffer_length,
+                                          SQLINTEGER* string_length_ptr);
+[[nodiscard]] SQLRETURN SQLSetConnectAttr(SQLHDBC conn, SQLINTEGER attr, 
SQLPOINTER value,
+                                          SQLINTEGER value_len);
+[[nodiscard]] SQLRETURN SQLDriverConnect(SQLHDBC conn, SQLHWND window_handle,
+                                         SQLWCHAR* in_connection_string,
+                                         SQLSMALLINT in_connection_string_len,
+                                         SQLWCHAR* out_connection_string,
+                                         SQLSMALLINT 
out_connection_string_buffer_len,
+                                         SQLSMALLINT* 
out_connection_string_len,
+                                         SQLUSMALLINT driver_completion);
+[[nodiscard]] SQLRETURN SQLConnect(SQLHDBC conn, SQLWCHAR* dsn_name,
+                                   SQLSMALLINT dsn_name_len, SQLWCHAR* 
user_name,
+                                   SQLSMALLINT user_name_len, SQLWCHAR* 
password,
+                                   SQLSMALLINT password_len);
+[[nodiscard]] SQLRETURN SQLDisconnect(SQLHDBC conn);
+[[nodiscard]] SQLRETURN SQLGetInfo(SQLHDBC conn, SQLUSMALLINT info_type,
+                                   SQLPOINTER info_value_ptr, SQLSMALLINT 
buf_len,
+                                   SQLSMALLINT* length);
+[[nodiscard]] SQLRETURN SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attribute,
+                                       SQLPOINTER value_ptr, SQLINTEGER 
buffer_length,
+                                       SQLINTEGER* string_length_ptr);
+[[nodiscard]] SQLRETURN SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attribute,
+                                       SQLPOINTER value_ptr, SQLINTEGER 
stringLength);
+[[nodiscard]] SQLRETURN SQLExecDirect(SQLHSTMT stmt, SQLWCHAR* queryText,
+                                      SQLINTEGER text_length);
+[[nodiscard]] SQLRETURN SQLPrepare(SQLHSTMT stmt, SQLWCHAR* queryText,
+                                   SQLINTEGER text_length);
+[[nodiscard]] SQLRETURN SQLExecute(SQLHSTMT stmt);
+[[nodiscard]] SQLRETURN SQLFetch(SQLHSTMT stmt);
+[[nodiscard]] SQLRETURN SQLExtendedFetch(SQLHSTMT stmt, SQLUSMALLINT 
fetch_orientation,
+                                         SQLLEN fetch_offset, SQLULEN* 
row_count_ptr,
+                                         SQLUSMALLINT* row_status_array);
+[[nodiscard]] SQLRETURN SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT 
fetch_orientation,
+                                       SQLLEN fetch_offset);
+[[nodiscard]] SQLRETURN SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT record_number,
+                                   SQLSMALLINT c_type, SQLPOINTER data_ptr,
+                                   SQLLEN buffer_length, SQLLEN* 
indicator_ptr);
+[[nodiscard]] SQLRETURN SQLCloseCursor(SQLHSTMT stmt);
+[[nodiscard]] SQLRETURN SQLGetData(SQLHSTMT stmt, SQLUSMALLINT record_number,
+                                   SQLSMALLINT c_type, SQLPOINTER data_ptr,
+                                   SQLLEN buffer_length, SQLLEN* 
indicator_ptr);
+[[nodiscard]] SQLRETURN SQLMoreResults(SQLHSTMT stmt);
+[[nodiscard]] SQLRETURN SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT* 
column_count_ptr);
+[[nodiscard]] SQLRETURN SQLRowCount(SQLHSTMT stmt, SQLLEN* row_count_ptr);
+[[nodiscard]] SQLRETURN SQLTables(SQLHSTMT stmt, SQLWCHAR* catalog_name,
+                                  SQLSMALLINT catalog_name_length, SQLWCHAR* 
schema_name,
+                                  SQLSMALLINT schema_name_length, SQLWCHAR* 
table_name,
+                                  SQLSMALLINT table_name_length, SQLWCHAR* 
table_type,
+                                  SQLSMALLINT table_type_length);
+[[nodiscard]] SQLRETURN SQLColumns(SQLHSTMT stmt, SQLWCHAR* catalog_name,
+                                   SQLSMALLINT catalog_name_length, SQLWCHAR* 
schema_name,
+                                   SQLSMALLINT schema_name_length, SQLWCHAR* 
table_name,
+                                   SQLSMALLINT table_name_length, SQLWCHAR* 
column_name,
+                                   SQLSMALLINT column_name_length);
+[[nodiscard]] SQLRETURN SQLColAttribute(SQLHSTMT stmt, SQLUSMALLINT 
record_number,
+                                        SQLUSMALLINT field_identifier,
+                                        SQLPOINTER character_attribute_ptr,
+                                        SQLSMALLINT buffer_length,
+                                        SQLSMALLINT* output_length,
+                                        SQLLEN* numeric_attribute_ptr);
+[[nodiscard]] SQLRETURN SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT dataType);
+[[nodiscard]] SQLRETURN SQLNativeSql(SQLHDBC conn, SQLWCHAR* in_statement_text,
+                                     SQLINTEGER in_statement_text_length,
+                                     SQLWCHAR* out_statement_text,
+                                     SQLINTEGER buffer_length,
+                                     SQLINTEGER* out_statement_text_length);
+[[nodiscard]] SQLRETURN SQLDescribeCol(
+    SQLHSTMT stmt, SQLUSMALLINT column_number, SQLWCHAR* column_name,
+    SQLSMALLINT buffer_length, SQLSMALLINT* name_length_ptr, SQLSMALLINT* 
data_type_ptr,
+    SQLULEN* column_size_ptr, SQLSMALLINT* decimal_digits_ptr, SQLSMALLINT* 
nullable_ptr);
 }  // namespace arrow::flight::sql::odbc

Reply via email to