SQLRETURN MNDBGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, SQLCHAR *SQLState, SQLINTEGER *NativeErrorPtr, SQLCHAR *MessageText, SQLSMALLINT BufferLength, SQLSMALLINT *TextLengthPtr) { ODBCError *err; SQLRETURN retCode; char *msg; SQLSMALLINT msgLen; switch (HandleType) { case SQL_HANDLE_ENV: /* Check if this struct is still valid/alive */ if (!isValidEnv((ODBCEnv *) Handle)) return SQL_INVALID_HANDLE; err = getEnvError((ODBCEnv *) Handle); break; case SQL_HANDLE_DBC: /* Check if this struct is still valid/alive */ if (!isValidDbc((ODBCDbc *) Handle)) return SQL_INVALID_HANDLE; err = getDbcError((ODBCDbc *) Handle); break; case SQL_HANDLE_STMT: /* Check if this struct is still valid/alive */ if (!isValidStmt((ODBCStmt *) Handle)) return SQL_INVALID_HANDLE; err = getStmtError((ODBCStmt *) Handle); break; case SQL_HANDLE_DESC: /* not yet supported */ return Handle ? SQL_NO_DATA : SQL_INVALID_HANDLE; default: return SQL_INVALID_HANDLE; } /* Note: BufferLength may be 0 !! */ if (BufferLength < 0) return SQL_ERROR; if (RecNumber <= 0) return SQL_ERROR; err = getErrorRec(err, RecNumber); /* Check the error object from the handle, it may be NULL when * no (more) errors are available */ if (err == NULL) return SQL_NO_DATA; /* Now fill the output parameters where possible */ if (SQLState) { char *state = getSqlState(err); assert(state); /* copy only the first SQL_SQLSTATE_SIZE (5) chars in * the buffer and make it null terminated */ strncpy((char *) SQLState, state, SQL_SQLSTATE_SIZE); SQLState[SQL_SQLSTATE_SIZE] = 0; } if (NativeErrorPtr) *NativeErrorPtr = getNativeErrorCode(err); msg = getMessage(err); msgLen = msg ? (SQLSMALLINT) strlen(msg) : 0; retCode = SQL_SUCCESS; if (MessageText && BufferLength > 0) { BufferLength--; /* reserve space for term NULL byte */ MessageText[BufferLength] = 0; /* write it already */ /* first write the error message prefix text: * [MonetDB][ODBC driver VERSION]; this is * required by the ODBC spec and used to * determine where the error originated */ if (BufferLength > 0) strncpy((char *) MessageText, ODBCErrorMsgPrefix, BufferLength); BufferLength -= ODBCErrorMsgPrefixLength; MessageText += ODBCErrorMsgPrefixLength; /* next append the error msg itself */ if (msg && BufferLength > 0) { strncpy((char *) MessageText, msg, BufferLength); BufferLength -= msgLen; } if (BufferLength < 0) { /* it didn't fit */ retCode = SQL_SUCCESS_WITH_INFO; } } else { /* There is no valid MessageText buffer or its * buffer size is 0. In these cases we cannot * write the prefix and message. We just set * the return code. */ retCode = SQL_SUCCESS_WITH_INFO; } if (TextLengthPtr) *TextLengthPtr = (SQLSMALLINT) (msgLen + ODBCErrorMsgPrefixLength); return retCode; }
static SQLRETURN MNDBGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier, SQLPOINTER DiagInfoPtr, SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr) { ODBCError *err; ODBCDbc *dbc = NULL; /* input & output parameters validity checks */ switch (HandleType) { case SQL_HANDLE_ENV: /* Check if this struct is still valid/alive */ if (!isValidEnv((ODBCEnv *) Handle)) return SQL_INVALID_HANDLE; err = ((ODBCEnv *) Handle)->Error; break; case SQL_HANDLE_DBC: /* Check if this struct is still valid/alive */ dbc = (ODBCDbc *) Handle; if (!isValidDbc(dbc)) return SQL_INVALID_HANDLE; err = dbc->Error; break; case SQL_HANDLE_STMT: /* Check if this struct is still valid/alive */ if (!isValidStmt((ODBCStmt *) Handle)) return SQL_INVALID_HANDLE; err = ((ODBCStmt *) Handle)->Error; dbc = ((ODBCStmt *) Handle)->Dbc; break; case SQL_HANDLE_DESC: /* Check if this struct is still valid/alive */ if (!isValidDesc((ODBCDesc *) Handle)) return SQL_INVALID_HANDLE; err = ((ODBCDesc *) Handle)->Error; dbc = ((ODBCDesc *) Handle)->Dbc; break; default: return SQL_INVALID_HANDLE; } /* header fields */ switch (DiagIdentifier) { case SQL_DIAG_CURSOR_ROW_COUNT: /* SQLLEN */ if (HandleType != SQL_HANDLE_STMT) return SQL_ERROR; *(SQLLEN *) DiagInfoPtr = (SQLLEN) ((ODBCStmt *) Handle)->rowSetSize; return SQL_SUCCESS; case SQL_DIAG_DYNAMIC_FUNCTION: /* SQLCHAR* */ if (HandleType != SQL_HANDLE_STMT) return SQL_ERROR; copyDiagString("", DiagInfoPtr, BufferLength, StringLengthPtr); return SQL_SUCCESS; case SQL_DIAG_DYNAMIC_FUNCTION_CODE: /* SQLINTEGER */ if (HandleType != SQL_HANDLE_STMT) return SQL_ERROR; *(SQLINTEGER *) DiagInfoPtr = SQL_DIAG_UNKNOWN_STATEMENT; return SQL_SUCCESS; case SQL_DIAG_NUMBER: /* SQLINTEGER */ *(SQLINTEGER *) DiagInfoPtr = getErrorRecCount(err); return SQL_SUCCESS; case SQL_DIAG_RETURNCODE: /* SQLRETURN */ *(SQLRETURN *) DiagInfoPtr = SQL_SUCCESS; return SQL_SUCCESS; case SQL_DIAG_ROW_COUNT: /* SQLLEN */ if (HandleType != SQL_HANDLE_STMT || ((ODBCStmt *) Handle)->State < EXECUTED0) return SQL_ERROR; *(SQLLEN *) DiagInfoPtr = (SQLLEN) ((ODBCStmt *) Handle)->rowcount; return SQL_SUCCESS; } /* record fields */ if (RecNumber <= 0) return SQL_ERROR; err = getErrorRec(err, RecNumber); if (err == NULL) return SQL_NO_DATA; switch (DiagIdentifier) { case SQL_DIAG_CLASS_ORIGIN:{ /* SQLCHAR* */ char *msg = strncmp(getSqlState(err), "IM", 2) == 0 ? "ODBC 3.0" : "ISO 9075"; copyDiagString(msg, DiagInfoPtr, BufferLength, StringLengthPtr); return SQL_SUCCESS; } case SQL_DIAG_COLUMN_NUMBER: /* SQLINTEGER */ if (HandleType != SQL_HANDLE_STMT) return SQL_ERROR; *(SQLINTEGER *) DiagInfoPtr = SQL_COLUMN_NUMBER_UNKNOWN; return SQL_SUCCESS; case SQL_DIAG_CONNECTION_NAME:{ /* SQLCHAR* */ char *msg = "MonetDB ODBC/Mapi"; copyDiagString(msg, DiagInfoPtr, BufferLength, StringLengthPtr); return SQL_SUCCESS; } #if 0 /* not clear yet what to return here */ case SQL_DIAG_MESSAGE_TEXT: { /* SQLCHAR* */ char msg[1024]; snprintf(msg, sizeof(msg), ""); copyDiagString(msg, DiagInfoPtr, BufferLength, StringLengthPtr); return SQL_SUCCESS; } #endif case SQL_DIAG_NATIVE: /* SQLINTEGER */ *(SQLINTEGER *) DiagInfoPtr = getNativeErrorCode(err); return SQL_SUCCESS; case SQL_DIAG_ROW_NUMBER: /* SQLLEN */ if (HandleType != SQL_HANDLE_STMT) return SQL_ERROR; *(SQLLEN *) DiagInfoPtr = SQL_ROW_NUMBER_UNKNOWN; return SQL_SUCCESS; case SQL_DIAG_SERVER_NAME:{ /* SQLCHAR* */ char *msg = dbc && dbc->Connected && dbc->dsn ? dbc->dsn : ""; copyDiagString(msg, DiagInfoPtr, BufferLength, StringLengthPtr); return SQL_SUCCESS; } case SQL_DIAG_SQLSTATE:{ /* SQLCHAR* */ char *msg = getSqlState(err); copyDiagString(msg, DiagInfoPtr, BufferLength, StringLengthPtr); return SQL_SUCCESS; } case SQL_DIAG_SUBCLASS_ORIGIN:{ /* SQLCHAR* */ char *state = getSqlState(err); char *msg; if (('0' <= state[0] && state[0] <= '4') || ('A' <= state[0] && state[0] <= 'H')) msg = "ISO 9075"; /* defined by standard */ else msg = "ODBC 3.0"; /* effectively just "IM" */ copyDiagString(msg, DiagInfoPtr, BufferLength, StringLengthPtr); return SQL_SUCCESS; } } /* Currently no Diagnostic Fields are supported. Hence we always return NO_DATA */ return SQL_NO_DATA; }