예제 #1
0
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;
}
예제 #2
0
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;
}