Repository: apache/arrow
File: cpp/src/arrow/flight/sql/odbc/odbc_api.cc (C++)

Code before:
  return SQL_INVALID_HANDLE;
}

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) {
  ARROW_LOG(DEBUG) << "SQLNativeSqlW called with connection_handle: " << conn
                   << ", in_statement_text: "
                   << static_cast<const void*>(in_statement_text)
                   << ", in_statement_text_length: " << in_statement_text_length
                   << ", out_statement_text: "
                   << static_cast<const void*>(out_statement_text)
                   << ", buffer_length: " << buffer_length
                   << ", out_statement_text_length: "
                   << static_cast<const void*>(out_statement_text_length);
  // GH-47723 TODO: Implement SQLNativeSql
  return SQL_INVALID_HANDLE;
}

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) {
  ARROW_LOG(DEBUG) << "SQLDescribeColW called with stmt: " << stmt
                   << ", column_number: " << column_number
                   << ", column_name: " << static_cast<const void*>(column_name)
                   << ", buffer_length: " << buffer_length
                   << ", name_length_ptr: " << static_cast<const void*>(name_length_ptr)
                   << ", data_type_ptr: " << static_cast<const void*>(data_type_ptr)
                   << ", column_size_ptr: " << static_cast<const void*>(column_size_ptr)
                   << ", decimal_digits_ptr: "
                   << static_cast<const void*>(decimal_digits_ptr)
                   << ", nullable_ptr: " << static_cast<const void*>(nullable_ptr);
  // GH-47724 TODO: Implement SQLDescribeCol
  return SQL_INVALID_HANDLE;
}

}  // namespace arrow::flight::sql::odbc


Review comment (suggestion):
we implemented SQLExecDirect to use prepare/execute to use prepared statements to align with the behavior with JDBC

Code after:
  using ODBC::ODBCStatement;

  return ODBCStatement::ExecuteWithDiagnostics(stmt, SQL_ERROR, [=]() {
    ODBCStatement* statement = reinterpret_cast<ODBCStatement*>(stmt);

    bool is_unicode = true;

    statement->SetStmtAttr(attribute, value_ptr, string_length, is_unicode);

    return SQL_SUCCESS;
  });
}

SQLRETURN SQLExecDirect(SQLHSTMT stmt, SQLWCHAR* query_text, SQLINTEGER text_length) {
  ARROW_LOG(DEBUG) << "SQLExecDirectW called with stmt: " << stmt
                   << ", query_text: " << static_cast<const void*>(query_text)
                   << ", text_length: " << text_length;

  using ODBC::ODBCStatement;
  // The driver is built to handle SELECT statements only.
  return ODBCStatement::ExecuteWithDiagnostics(stmt, SQL_ERROR, [=]() {
    ODBCStatement* statement = reinterpret_cast<ODBCStatement*>(stmt);
    std::string query = ODBC::SqlWcharToString(query_text, text_length);

    statement->Prepare(query);
    statement->ExecutePrepared();

    return SQL_SUCCESS;
  });
}

SQLRETURN SQLPrepare(SQLHSTMT stmt, SQLWCHAR* query_text, SQLINTEGER text_length) {
  ARROW_LOG(DEBUG) << "SQLPrepareW called with stmt: " << stmt
                   << ", query_text: " << static_cast<const void*>(query_text)
                   << ", text_length: " << text_length;

  using ODBC::ODBCStatement;
  // The driver is built to handle SELECT statements only.
  return ODBCStatement::ExecuteWithDiagnostics(stmt, SQL_ERROR, [=]() {
    ODBCStatement* statement = reinterpret_cast<ODBCStatement*>(stmt);
    std::string query = ODBC::SqlWcharToString(query_text, text_length);

    statement->Prepare(query);

    return SQL_SUCCESS;
  });
}

SQLRETURN SQLExecute(SQLHSTMT stmt) {
  ARROW_LOG(DEBUG) << "SQLExecute called with stmt: " << stmt;