SQLRETURN EsSQLGetDiagFieldW()

in driver/info.c [861:1080]


SQLRETURN EsSQLGetDiagFieldW(
	SQLSMALLINT HandleType,
	SQLHANDLE Handle,
	SQLSMALLINT RecNumber,
	SQLSMALLINT DiagIdentifier,
	_Out_writes_opt_(_Inexpressible_(BufferLength)) SQLPOINTER DiagInfoPtr,
	SQLSMALLINT BufferLength,
	_Out_opt_ SQLSMALLINT *StringLengthPtr)
{
	esodbc_dbc_st *dbc;
	esodbc_diag_st *diag, bak;
	esodbc_env_st dummy;
	SQLSMALLINT used;
	size_t len;
	void *srcptr;
	wstr_st *wstrp, wstr;
	SQLRETURN ret;

	if (RecNumber <= 0) {
		ERRH(Handle, "record number must be >=1; received: %d.", RecNumber);
		return SQL_ERROR;
	} else if (1 < RecNumber) {
		return SQL_NO_DATA;
	}

	if (! Handle) {
		ERR("null handle provided.");
		return SQL_INVALID_HANDLE;
	}
	diag = &HDRH(Handle)->diag;
	/* GetDiagField can't set diagnostics itself, so use a dummy */
	*HDRH(&dummy) = *HDRH(Handle); /* need a valid hhdr struct */

	/*INDENT-OFF*/
	switch (DiagIdentifier) {
		/* Header Fields */
		case SQL_DIAG_NUMBER:
			if (! DiagInfoPtr) {
				ERRH(Handle, "NULL DiagInfo with SQL_DIAG_NUMBER");
				return SQL_ERROR;
			}
			*(SQLINTEGER *)DiagInfoPtr =
				(diag->state != SQL_STATE_00000) ? 1 : 0;
			DBGH(Handle, "available diagnostics count: %ld.",
					*(SQLINTEGER *)DiagInfoPtr);
			return SQL_SUCCESS;

		case SQL_DIAG_CURSOR_ROW_COUNT:
		case SQL_DIAG_DYNAMIC_FUNCTION:
		case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
		case SQL_DIAG_ROW_COUNT:
			/* should be handled by DM */
			if (HandleType != SQL_HANDLE_STMT) {
				ERRH(Handle, "DiagIdentifier %d called with non-statement "
						"handle type %d.", DiagIdentifier, HandleType);
				return SQL_ERROR;
			}
			ERRH(Handle, "DiagIdentifier %hd is not supported.");
			return SQL_ERROR;

		/* case SQL_DIAG_RETURNCODE: break; -- DM only */

		/* Record Fields */
		do {
		case SQL_DIAG_CLASS_ORIGIN:
			len = (sizeof(ORIG_DISCRIM) - 1) * sizeof (SQLWCHAR);
			assert(len <= sizeof(esodbc_errors[diag->state].code));
			if (memcmp(esodbc_errors[diag->state].code, MK_WPTR(ORIG_DISCRIM),
						len) == 0) {
				wstrp = &MK_WSTR(ORIG_CLASS_ODBC);
			} else {
				wstrp = &MK_WSTR(ORIG_CLASS_ISO);
			}
			break;
		case SQL_DIAG_SUBCLASS_ORIGIN:
			switch (diag->state) {
				case SQL_STATE_01S00:
				case SQL_STATE_01S01:
				case SQL_STATE_01S02:
				case SQL_STATE_01S06:
				case SQL_STATE_01S07:
				case SQL_STATE_07S01:
				case SQL_STATE_08S01:
				case SQL_STATE_21S01:
				case SQL_STATE_21S02:
				case SQL_STATE_25S01:
				case SQL_STATE_25S02:
				case SQL_STATE_25S03:
				case SQL_STATE_42S01:
				case SQL_STATE_42S02:
				case SQL_STATE_42S11:
				case SQL_STATE_42S12:
				case SQL_STATE_42S21:
				case SQL_STATE_42S22:
				case SQL_STATE_HY095:
				case SQL_STATE_HY097:
				case SQL_STATE_HY098:
				case SQL_STATE_HY099:
				case SQL_STATE_HY100:
				case SQL_STATE_HY101:
				case SQL_STATE_HY105:
				case SQL_STATE_HY107:
				case SQL_STATE_HY109:
				case SQL_STATE_HY110:
				case SQL_STATE_HY111:
				case SQL_STATE_HYT00:
				case SQL_STATE_HYT01:
				case SQL_STATE_IM001:
				case SQL_STATE_IM002:
				case SQL_STATE_IM003:
				case SQL_STATE_IM004:
				case SQL_STATE_IM005:
				case SQL_STATE_IM006:
				case SQL_STATE_IM007:
				case SQL_STATE_IM008:
				case SQL_STATE_IM010:
				case SQL_STATE_IM011:
				case SQL_STATE_IM012:
					wstrp = &MK_WSTR(ORIG_CLASS_ODBC);
					break;
				default:
					wstrp = &MK_WSTR(ORIG_CLASS_ISO);
			}
			break;
		} while (0);
			DBGH(Handle, "diagnostic code '"LWPD"' is of class '" LWPDL "'.",
					esodbc_errors[diag->state].code, LWSTR(wstrp));
			return write_wstr(&dummy, DiagInfoPtr, wstrp, BufferLength,
					StringLengthPtr);

		do {
		case SQL_DIAG_CONNECTION_NAME:
		case SQL_DIAG_SERVER_NAME:
			switch (HandleType) {
				case SQL_HANDLE_DBC:
					dbc = DBCH(Handle);
					break;
				case SQL_HANDLE_STMT:
					dbc = STMH(Handle)->hdr.dbc;
					break;
				case SQL_HANDLE_DESC:
					dbc = DSCH(Handle)->hdr.stmt->hdr.dbc;
					break;
				default:
					ERR("unknown handle type %hd, @0x%p.", HandleType, Handle);
					return SQL_ERROR; // SQL_INVALID_HANDLE?
			}
		} while (0);
			/* save (and then restore) the diag state, since this call mustn't
			 * change it */
			bak = dbc->hdr.diag;
			ret = EsSQLGetInfoW(dbc,
					DiagIdentifier == SQL_DIAG_CONNECTION_NAME ?
							SQL_DATA_SOURCE_NAME : SQL_SERVER_NAME,
					DiagInfoPtr, BufferLength, StringLengthPtr);
			dbc->hdr.diag = bak;
			return ret;

		case SQL_DIAG_MESSAGE_TEXT:
			wstr.str = diag->text;
			wstr.cnt = diag->text_len;
			return write_wstr(Handle, DiagInfoPtr, &wstr,
					BufferLength * sizeof(*diag->text), StringLengthPtr);

		do {
		case SQL_DIAG_NATIVE:
			len = sizeof(diag->native_code);
			srcptr = &diag->native_code;
			break;
		case SQL_DIAG_COLUMN_NUMBER:
			len = sizeof(diag->column_number);
			srcptr = &diag->column_number;
			break;
		case SQL_DIAG_ROW_NUMBER:
			len = sizeof(diag->row_number);
			srcptr = &diag->row_number;
			break;
		} while (0);
			if (BufferLength != SQL_IS_POINTER) {
				WARNH(Handle, "BufferLength param not indicating a ptr type.");
			}
			if (! DiagInfoPtr) {
				ERRH(Handle, "integer diagnostic field %hd asked for, but "
						"NULL destination provided.");
				RET_HDIAGS(Handle, SQL_STATE_HY009);
			} else {
				memcpy(DiagInfoPtr, srcptr, len);
			}
			return SQL_SUCCESS;

		case SQL_DIAG_SQLSTATE:
			if (diag->state == SQL_STATE_00000) {
				DBGH(Handle, "no diagnostic available for handle type %d.",
						HandleType);
				/* "The function also returns SQL_NO_DATA for any positive
				 * RecNumber if there are no diagnostic records for Handle" */
				return SQL_NO_DATA;
			}
			wstr.str = esodbc_errors[diag->state].code;
			wstr.cnt = wcslen(wstr.str);
			ret = write_wstr(&dummy, DiagInfoPtr, &wstr, BufferLength, &used);
			if (StringLengthPtr) {
				*StringLengthPtr = used;
			} else {
				/* SQLSTATE is always on 5 chars, but this Identifier sticks
				 * out, by not being given a buffer to write this into */
				WARNH(Handle, "SQLSTATE writen on %uB, but no output buffer "
						"provided.", used);
			}
			return ret;

		default:
			ERRH(Handle, "unknown DiagIdentifier: %d.", DiagIdentifier);
			return SQL_ERROR;
	}
	/*INDENT-ON*/

	assert(0); // FIXME: shouldn't get here
	return SQL_ERROR;
}