Skip to content
16 changes: 8 additions & 8 deletions cpp/src/arrow/flight/sql/odbc/entry_points.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ SQLRETURN SQL_API SQLGetDiagFieldW(SQLSMALLINT handleType, SQLHANDLE handle,
diagInfoPtr, bufferLength, stringLengthPtr);
}

SQLRETURN SQL_API SQLGetDiagRecW(SQLSMALLINT handleType, SQLHANDLE handle,
SQLSMALLINT recNumber, SQLWCHAR* sqlState,
SQLINTEGER* nativeErrorPtr, SQLWCHAR* messageText,
SQLSMALLINT bufferLength, SQLSMALLINT* textLengthPtr) {
return arrow::SQLGetDiagRecW(handleType, handle, recNumber, sqlState, nativeErrorPtr,
messageText, bufferLength, textLengthPtr);
}

SQLRETURN SQL_API SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER valuePtr,
SQLINTEGER bufferLen, SQLINTEGER* strLenPtr) {
return arrow::SQLGetEnvAttr(env, attr, valuePtr, bufferLen, strLenPtr);
Expand All @@ -81,14 +89,6 @@ SQLRETURN SQL_API SQLGetInfoW(SQLHDBC conn, SQLUSMALLINT infoType,
return arrow::SQLGetInfoW(conn, infoType, infoValuePtr, bufLen, length);
}

SQLRETURN SQL_API SQLGetDiagRecW(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT recNum,
SQLWCHAR* sqlState, SQLINTEGER* nativeError,
SQLWCHAR* msgBuffer, SQLSMALLINT msgBufferLen,
SQLSMALLINT* msgLen) {
// TODO implement SQLGetDiagRecW
return SQL_ERROR;
}

SQLRETURN SQL_API SQLDriverConnectW(SQLHDBC conn, SQLHWND windowHandle,
SQLWCHAR* inConnectionString,
SQLSMALLINT inConnectionStringLen,
Expand Down
79 changes: 79 additions & 0 deletions cpp/src/arrow/flight/sql/odbc/odbc_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,85 @@ SQLRETURN SQLGetDiagFieldW(SQLSMALLINT handleType, SQLHANDLE handle,
return SQL_ERROR;
}

SQLRETURN SQLGetDiagRecW(SQLSMALLINT handleType, SQLHANDLE handle, SQLSMALLINT recNumber,
SQLWCHAR* sqlState, SQLINTEGER* nativeErrorPtr,
SQLWCHAR* messageText, SQLSMALLINT bufferLength,
SQLSMALLINT* textLengthPtr) {
using driver::odbcabstraction::Diagnostics;
using ODBC::ConvertToSqlWChar;
using ODBC::GetStringAttribute;
using ODBC::ODBCConnection;
using ODBC::ODBCEnvironment;

if (!handle) {
return SQL_INVALID_HANDLE;
}

// Record number must be greater or equal to 1
if (recNumber < 1 || bufferLength < 0) {
return SQL_ERROR;
}

// Set character type to be Unicode by default
bool isUnicode = true;
Diagnostics* diagnostics = nullptr;

switch (handleType) {
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: {
return SQL_ERROR;
}

case SQL_HANDLE_STMT: {
return SQL_ERROR;
}

default:
return SQL_INVALID_HANDLE;
}

if (!diagnostics) {
return SQL_ERROR;
}

// Convert from ODBC 1 based record number to internal diagnostics 0 indexed storage
size_t recordIndex = static_cast<size_t>(recNumber - 1);
if (!diagnostics->HasRecord(recordIndex)) {
return SQL_NO_DATA;
}

if (sqlState) {
// The length of the sql state is always 5 characters plus null
SQLSMALLINT size = 6;
const std::string& state = diagnostics->GetSQLState(recordIndex);
GetStringAttribute(isUnicode, state, false, sqlState, bufferLength, &size,
*diagnostics);
}

if (nativeErrorPtr) {
*nativeErrorPtr = diagnostics->GetNativeError(recordIndex);
}

if (messageText || textLengthPtr) {
const std::string& message = diagnostics->GetMessageText(recordIndex);
return GetStringAttribute(isUnicode, message, false, messageText, bufferLength,
textLengthPtr, *diagnostics);
}

return SQL_SUCCESS;
}

SQLRETURN SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER valuePtr,
SQLINTEGER bufferLen, SQLINTEGER* strLenPtr) {
using driver::odbcabstraction::DriverException;
Expand Down
4 changes: 4 additions & 0 deletions cpp/src/arrow/flight/sql/odbc/odbc_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ SQLRETURN SQLGetDiagFieldW(SQLSMALLINT handleType, SQLHANDLE handle,
SQLSMALLINT recNumber, SQLSMALLINT diagIdentifier,
SQLPOINTER diagInfoPtr, SQLSMALLINT bufferLength,
SQLSMALLINT* stringLengthPtr);
SQLRETURN SQLGetDiagRecW(SQLSMALLINT handleType, SQLHANDLE handle, SQLSMALLINT recNumber,
SQLWCHAR* sqlState, SQLINTEGER* nativeErrorPtr,
SQLWCHAR* messageText, SQLSMALLINT bufferLength,
SQLSMALLINT* textLengthPtr);
SQLRETURN SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER valuePtr,
SQLINTEGER bufferLen, SQLINTEGER* strLenPtr);
SQLRETURN SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER valuePtr,
Expand Down