Beispiel #1
0
static void gen_request( qli_req* request)
{
/**************************************
 *
 *	g e n _ r e q u e s t
 *
 **************************************
 *
 * Functional description
 *	Prepare to generation and compile a request.
 *
 **************************************/
	qli_par* param;

	qli_rlb* rlb = CHECK_RLB(request->req_blr);

	STUFF(blr_version4);
	STUFF(blr_begin);

	// Build declarations for all messages.

	for (qli_msg* message = request->req_messages; message; message = message->msg_next)
	{
		message->msg_length = 0;
		for (param = message->msg_parameters; param; param = param->par_next)
		{
			const dsc* desc = &param->par_desc;
			param->par_parameter = message->msg_parameter++;
			const USHORT alignment = type_alignments[desc->dsc_dtype];
			if (alignment)
				message->msg_length = FB_ALIGN(message->msg_length, alignment);
			param->par_offset = message->msg_length;
			message->msg_length += desc->dsc_length;
			qli_par* missing_param = param->par_missing;
			if (missing_param)
			{
				missing_param->par_parameter = message->msg_parameter++;
				message->msg_length = FB_ALIGN(message->msg_length, sizeof(USHORT));
				desc = &missing_param->par_desc;
				missing_param->par_offset = message->msg_length;
				message->msg_length += desc->dsc_length;
			}
		}

		STUFF(blr_message);
		STUFF(message->msg_number);
		STUFF_WORD(message->msg_parameter);

		qli_str* string = (qli_str*) ALLOCDV(type_str, message->msg_length + FB_DOUBLE_ALIGN - 1);
		message->msg_buffer = (UCHAR*) FB_ALIGN((FB_UINT64)(U_IPTR) string->str_data, FB_DOUBLE_ALIGN);

		for (param = message->msg_parameters; param; param = param->par_next)
		{
			gen_descriptor(&param->par_desc, request);
			qli_par* missing_param = param->par_missing;
			if (missing_param)
				gen_descriptor(&missing_param->par_desc, request);
		}
	}
}
Beispiel #2
0
UCHAR* MSC_alloc(int size)
{
	size = FB_ALIGN(size, FB_ALIGNMENT);

	if (!space || size > space->spc_remaining)
	{
		const int n = MAX(size, 4096);
		gpre_space* next = (gpre_space*) gds__alloc((SLONG) (n + sizeof(gpre_space)));
		if (!next)
			CPR_error("virtual memory exhausted");
#ifdef DEBUG_GDS_ALLOC
		// For V4.0 we don't care about gpre specific memory leaks
		gds_alloc_flag_unfreed(next);
#endif
		next->spc_next = space;
		next->spc_remaining = n;
		space = next;
	}

	space->spc_remaining -= size;
	UCHAR* blk = ((UCHAR*) space + sizeof(gpre_space) + space->spc_remaining);
	memset(blk, 0, size);

	return blk;
}
Beispiel #3
0
void BlrFromMessage::buildBlr(IMessageMetadata* metadata)
{
	if (!metadata)
		return;

	LocalStatus st;

	expectedMessageLength = metadata->getMessageLength(&st);
	checkStatus(&st);

	getBlrData().clear();

	const unsigned count = metadata->getCount(&st);
	fb_assert(count < MAX_USHORT / 2);

	if (count == 0)
		return;	// If there isn't an SQLDA, don't bother with anything else.

	appendVersion();
	appendUChar(blr_begin);
	appendUChar(blr_message);
	appendUChar(0);
	appendUShort(count * 2);

	unsigned msgLen = 0;

	for (unsigned i = 0; i < count; ++i)
	{
		unsigned dtype = metadata->getType(&st, i) & ~1;
		checkStatus(&st);
		unsigned len = metadata->getLength(&st, i);
		checkStatus(&st);
		unsigned scale = metadata->getScale(&st, i);
		checkStatus(&st);
		unsigned charSet = metadata->getCharSet(&st, i);
		checkStatus(&st);

		switch (dtype)
		{
			case SQL_VARYING:
				appendUChar(blr_varying2);
				appendUShort(charSet);
				appendUShort(len);
				dtype = dtype_varying;
				len += sizeof(USHORT);
				break;

			case SQL_TEXT:
				appendUChar(blr_text2);
				appendUShort(charSet);
				appendUShort(len);
				dtype = dtype_text;
				break;

			case SQL_DOUBLE:
				appendUChar(blr_double);
				dtype = dtype_double;
				break;

			case SQL_FLOAT:
				appendUChar(blr_float);
				dtype = dtype_real;
				break;

			case SQL_D_FLOAT:
				appendUChar(blr_d_float);
				dtype = dtype_d_float;
				break;

			case SQL_TYPE_DATE:
				appendUChar(blr_sql_date);
				dtype = dtype_sql_date;
				break;

			case SQL_TYPE_TIME:
				appendUChar(blr_sql_time);
				dtype = dtype_sql_time;
				break;

			case SQL_TIMESTAMP:
				appendUChar(blr_timestamp);
				dtype = dtype_timestamp;
				break;

			case SQL_BLOB:
				appendUChar(blr_blob2);
				appendUShort(metadata->getSubType(&st, i));
				appendUShort(charSet);
				dtype = dtype_blob;
				break;

			case SQL_ARRAY:
				appendUChar(blr_quad);
				appendUChar(0);
				dtype = dtype_array;
				break;

			case SQL_LONG:
				appendUChar(blr_long);
				appendUChar(scale);
				dtype = dtype_long;
				break;

			case SQL_SHORT:
				appendUChar(blr_short);
				appendUChar(scale);
				dtype = dtype_short;
				break;

			case SQL_INT64:
				appendUChar(blr_int64);
				appendUChar(scale);
				dtype = dtype_int64;
				break;

			case SQL_QUAD:
				appendUChar(blr_quad);
				appendUChar(scale);
				dtype = dtype_quad;
				break;

			case SQL_BOOLEAN:
				appendUChar(blr_bool);
				dtype = dtype_boolean;
				break;

			case SQL_NULL:
				appendUChar(blr_text);
				appendUShort(len);
				dtype = dtype_text;
				break;

			default:
				Arg::Gds(isc_dsql_sqlda_value_err).raise();
				break;
		}

		appendUChar(blr_short);
		appendUChar(0);

		unsigned align = type_alignments[dtype];
		if (align)
			msgLen = FB_ALIGN(msgLen, align);

		msgLen += len;

		align = type_alignments[dtype_short];
		if (align)
			msgLen = FB_ALIGN(msgLen, align);

		msgLen += sizeof(SSHORT);
	}

	appendUChar(blr_end);
	appendUChar(blr_eoc);

	if (expectedMessageLength && msgLen && (expectedMessageLength != msgLen))
	{
		Arg::Gds(isc_wrong_message_length).raise();
	}
}
Beispiel #4
0
		void create()
		{
			static char place[sizeof(Firebird::Mutex) + FB_ALIGNMENT];
			mutex = new((void*) FB_ALIGN(place, FB_ALIGNMENT)) Firebird::Mutex;
		}
Beispiel #5
0
ULONG CAN_encode_decode(burp_rel* relation, lstring* buffer, UCHAR* data, bool_t direction)
{
/**************************************
 *
 *	C A N _ e n c o d e _ d e c o d e
 *
 **************************************
 *
 * Functional description
 *	encode and decode canonical backup.
 *
 **************************************/
	const burp_fld* field;
	SSHORT n;

	XDR xdr;
	XDR* xdrs = &xdr;

	xdr_init(xdrs, buffer, direction ? XDR_ENCODE : XDR_DECODE);

	RCRD_OFFSET offset = 0;
	for (field = relation->rel_fields; field; field = field->fld_next)
	{
		if (field->fld_flags & FLD_computed)
			continue;
		UCHAR* p = data + field->fld_offset;
		const bool array_fld = ((field->fld_flags & FLD_array) != 0);
		const FLD_LENGTH length = array_fld ? 8 : field->fld_length;
		if (field->fld_offset >= offset)
			offset = field->fld_offset + length;
		if (field->fld_type == blr_varying && !array_fld)
			offset += sizeof(SSHORT);
		SSHORT dtype;
		if (field->fld_type == blr_blob || array_fld)
			dtype = dtype_blob;
		else
			dtype = (SSHORT) gds_cvt_blr_dtype[field->fld_type];
		switch (dtype)
		{
		case dtype_text:
			if (!xdr_opaque(xdrs, reinterpret_cast<char*>(p), length))
			{
				return FALSE;
			}
			break;

		case dtype_varying:
			{
				vary* pVary = reinterpret_cast<vary*>(p);
				if (!xdr_short(xdrs, reinterpret_cast<SSHORT*>(&pVary->vary_length)))
				{
					return FALSE;
				}
				if (!xdr_opaque(xdrs, reinterpret_cast<SCHAR*>(pVary->vary_string),
								MIN(pVary->vary_length, length)))
				{
				  return FALSE;
				}
			}
			break;

		case dtype_cstring:
			if (xdrs->x_op == XDR_ENCODE)
				n = static_cast<SSHORT>(MIN(strlen(reinterpret_cast<const char*>(p)), length));
			if (!xdr_short(xdrs, &n))
				return FALSE;
			if (!xdr_opaque(xdrs, reinterpret_cast<SCHAR*>(p), n))
				  return FALSE;
			if (xdrs->x_op == XDR_DECODE)
				p[n] = 0;
			break;

		case dtype_short:
			if (!xdr_short(xdrs, (SSHORT *) p))
				return FALSE;
			break;

		case dtype_long:
		case dtype_sql_time:
		case dtype_sql_date:
			if (!xdr_long(xdrs, (SLONG *) p))
				return FALSE;
			break;

		case dtype_real:
			if (!xdr_float(xdrs, (float *) p))
				return FALSE;
			break;

		case dtype_double:
			if (!xdr_double(xdrs, (double *) p))
				return FALSE;
			break;

		case dtype_timestamp:
			if (!xdr_long(xdrs, &((SLONG*) p)[0]))
				return FALSE;
			if (!xdr_long(xdrs, &((SLONG*) p)[1]))
				return FALSE;
			break;

		case dtype_quad:
		case dtype_blob:
			if (!xdr_quad(xdrs, (SQUAD*) p))
				return FALSE;
			break;

		case dtype_int64:
			if (!xdr_hyper(xdrs, (SINT64*) p))
				return FALSE;
			break;

		case dtype_boolean:
			if (!xdr_opaque(xdrs, (SCHAR*) p, length))
				return FALSE;
			break;

		default:
			fb_assert(FALSE);
			return FALSE;
		}
	}

	// Next, get null flags

	for (field = relation->rel_fields; field; field = field->fld_next)
	{
		if (field->fld_flags & FLD_computed)
			continue;
		offset = FB_ALIGN(offset, sizeof(SSHORT));
		UCHAR* p = data + offset;
		if (!xdr_short(xdrs, (SSHORT*) p))
			return FALSE;
		offset += sizeof(SSHORT);
	}
	return (xdrs->x_private - xdrs->x_base);
}
Beispiel #6
0
// Parse the messages of a blr request. For specified message, allocate a format (Format) block.
void Routine::parseMessages(thread_db* tdbb, CompilerScratch* csb, BlrReader blrReader)
{
	if (blrReader.getLength() < 2)
		status_exception::raise(Arg::Gds(isc_metadata_corrupt));

	csb->csb_blr_reader = blrReader;

	const SSHORT version = csb->csb_blr_reader.getByte();

	switch (version)
	{
		case blr_version4:
		case blr_version5:
		//case blr_version6:
			break;

		default:
			status_exception::raise(
				Arg::Gds(isc_metadata_corrupt) <<
				Arg::Gds(isc_wroblrver2) << Arg::Num(blr_version4) << Arg::Num(blr_version5/*6*/) <<
					Arg::Num(version));
	}

	if (csb->csb_blr_reader.getByte() != blr_begin)
		status_exception::raise(Arg::Gds(isc_metadata_corrupt));

	while (csb->csb_blr_reader.getByte() == blr_message)
	{
		const USHORT msgNumber = csb->csb_blr_reader.getByte();
		USHORT count = csb->csb_blr_reader.getWord();
		Format* format = Format::newFormat(*tdbb->getDefaultPool(), count);

		USHORT padField;
		const bool shouldPad = csb->csb_message_pad.get(msgNumber, padField);

		USHORT maxAlignment = 0;
		ULONG offset = 0;
		USHORT i = 0;

		for (Format::fmt_desc_iterator desc = format->fmt_desc.begin(); i < count; ++i, ++desc)
		{
			const USHORT align = PAR_desc(tdbb, csb, &*desc);
			if (align)
				offset = FB_ALIGN(offset, align);

			desc->dsc_address = (UCHAR*)(IPTR) offset;
			offset += desc->dsc_length;

			maxAlignment = MAX(maxAlignment, align);

			if (maxAlignment && shouldPad && i + 1 == padField)
				offset = FB_ALIGN(offset, maxAlignment);
		}

		format->fmt_length = offset;

		switch (msgNumber)
		{
			case 0:
				setInputFormat(format);
				break;

			case 1:
				setOutputFormat(format);
				break;

			default:
				delete format;
		}
	}
}
Beispiel #7
0
RMessage* PARSE_messages(const UCHAR* blr, size_t blr_length)
{
/**************************************
 *
 *	P A R S E _ m e s s a g e s
 *
 **************************************
 *
 * Functional description
 *	Parse the messages of a blr request.  For each message, allocate
 *	a message (msg) and a format (fmt) block.  Return the number of
 *	messages found.  If an error occurs, return -1;
 *
 **************************************/

	if (blr_length < 2)
		return (RMessage*) -1;
	blr_length -= 2;

	const SSHORT version = *blr++;
	if (version != blr_version4 && version != blr_version5)
		return (RMessage*) -1;

	if (*blr++ != blr_begin)
		return 0;

	RMessage* message = NULL;
	ULONG net_length = 0;

	while (*blr++ == blr_message)
	{
		if (blr_length < 4)
			return parse_error(0, message);
		blr_length -= 4;

		const USHORT msg_number = *blr++;
		USHORT count = *blr++;
		count += (*blr++) << 8;
		rem_fmt* const format = new rem_fmt(count);
#ifdef DEBUG_REMOTE_MEMORY
		printf("PARSE_messages            allocate format  %x\n", format);
#endif
		ULONG offset = 0;
		for (dsc* desc = format->fmt_desc.begin(); count; --count, ++desc)
		{
			if (blr_length-- == 0)
				return parse_error(format, message);

			USHORT align = 4;
			switch (*blr++)
			{
			case blr_text:
				if (blr_length < 2)
					return parse_error(format, message);
				blr_length -= 2;
				desc->dsc_dtype = dtype_text;
				desc->dsc_length = *blr++;
				desc->dsc_length += (*blr++) << 8;
				align = type_alignments[dtype_text];
				break;

			case blr_varying:
				if (blr_length < 2)
					return parse_error(format, message);
				blr_length -= 2;
				desc->dsc_dtype = dtype_varying;
				desc->dsc_length = *blr++ + sizeof(SSHORT);
				desc->dsc_length += (*blr++) << 8;
				align = type_alignments[dtype_varying];
				break;

			case blr_cstring:
				if (blr_length < 2)
					return parse_error(format, message);
				blr_length -= 2;
				desc->dsc_dtype = dtype_cstring;
				desc->dsc_length = *blr++;
				desc->dsc_length += (*blr++) << 8;
				align = type_alignments[dtype_cstring];
				break;

				// Parse the tagged blr types correctly

			case blr_text2:
				if (blr_length < 4)
					return parse_error(format, message);
				blr_length -= 4;
				desc->dsc_dtype = dtype_text;
				desc->dsc_scale = *blr++;
				desc->dsc_scale += (*blr++) << 8;
				desc->dsc_length = *blr++;
				desc->dsc_length += (*blr++) << 8;
				align = type_alignments[dtype_text];
				break;

			case blr_varying2:
				if (blr_length < 4)
					return parse_error(format, message);
				blr_length -= 4;
				desc->dsc_dtype = dtype_varying;
				desc->dsc_scale = *blr++;
				desc->dsc_scale += (*blr++) << 8;
				desc->dsc_length = *blr++ + sizeof(SSHORT);
				desc->dsc_length += (*blr++) << 8;
				align = type_alignments[dtype_varying];
				break;

			case blr_cstring2:
				if (blr_length < 4)
					return parse_error(format, message);
				blr_length -= 4;
				desc->dsc_dtype = dtype_cstring;
				desc->dsc_scale = *blr++;
				desc->dsc_scale += (*blr++) << 8;
				desc->dsc_length = *blr++;
				desc->dsc_length += (*blr++) << 8;
				align = type_alignments[dtype_cstring];
				break;

			case blr_short:
				if (blr_length-- == 0)
					return parse_error(format, message);
				desc->dsc_dtype = dtype_short;
				desc->dsc_length = sizeof(SSHORT);
				desc->dsc_scale = *blr++;
				align = type_alignments[dtype_short];
				break;

			case blr_long:
				if (blr_length-- == 0)
					return parse_error(format, message);
				desc->dsc_dtype = dtype_long;
				desc->dsc_length = sizeof(SLONG);
				desc->dsc_scale = *blr++;
				align = type_alignments[dtype_long];
				break;

			case blr_int64:
				if (blr_length-- == 0)
					return parse_error(format, message);
				desc->dsc_dtype = dtype_int64;
				desc->dsc_length = sizeof(SINT64);
				desc->dsc_scale = *blr++;
				align = type_alignments[dtype_int64];
				break;

			case blr_quad:
				if (blr_length-- == 0)
					return parse_error(format, message);
				desc->dsc_dtype = dtype_quad;
				desc->dsc_length = sizeof(SLONG) * 2;
				desc->dsc_scale = *blr++;
				align = type_alignments[dtype_quad];
				break;

			case blr_float:
				desc->dsc_dtype = dtype_real;
				desc->dsc_length = sizeof(float);
				align = type_alignments[dtype_real];
				break;

			case blr_double:
			case blr_d_float:
				desc->dsc_dtype = dtype_double;
				desc->dsc_length = sizeof(double);
				align = type_alignments[dtype_double];
				break;

			// this case cannot occur as switch paramater is char and blr_blob
            // is 261. blob_ids are actually passed around as blr_quad.

		    //case blr_blob:
			//	desc->dsc_dtype = dtype_blob;
			//	desc->dsc_length = sizeof (SLONG) * 2;
			//	align = type_alignments [dtype_blob];
			//	break;

			case blr_blob2:
				{
					if (blr_length < 4)
						return parse_error(format, message);
					blr_length -= 4;
					desc->dsc_dtype = dtype_blob;
					desc->dsc_length = sizeof(SLONG) * 2;
					desc->dsc_sub_type = *blr++;
					desc->dsc_sub_type += (*blr++) << 8;

					USHORT textType = *blr++;
					textType += (*blr++) << 8;
					desc->setTextType(textType);

					align = type_alignments[dtype_blob];
				}
				break;

			case blr_timestamp:
				desc->dsc_dtype = dtype_timestamp;
				desc->dsc_length = sizeof(SLONG) * 2;
				align = type_alignments[dtype_timestamp];
				break;

			case blr_sql_date:
				desc->dsc_dtype = dtype_sql_date;
				desc->dsc_length = sizeof(SLONG);
				align = type_alignments[dtype_sql_date];
				break;

			case blr_sql_time:
				desc->dsc_dtype = dtype_sql_time;
				desc->dsc_length = sizeof(ULONG);
				align = type_alignments[dtype_sql_time];
				break;

			case blr_bool:
				desc->dsc_dtype = dtype_boolean;
				desc->dsc_length = sizeof(UCHAR);
				align = type_alignments[dtype_boolean];
				break;

			default:
				fb_assert(FALSE);
				return parse_error(format, message);
			}
			if (desc->dsc_dtype == dtype_varying)
				net_length += 4 + ((desc->dsc_length - 2 + 3) & ~3);
			else
				net_length += (desc->dsc_length + 3) & ~3;
			if (align > 1)
				offset = FB_ALIGN(offset, align);
			desc->dsc_address = (UCHAR*) (IPTR) offset;
			offset += desc->dsc_length;
		}
		format->fmt_length = offset;
		format->fmt_net_length = net_length;
		RMessage* next = new RMessage(format->fmt_length);
#ifdef DEBUG_REMOTE_MEMORY
		printf("PARSE_messages            allocate message %x\n", next);
#endif
		next->msg_next = message;
		message = next;
		message->msg_address = reinterpret_cast<UCHAR*>(format);
		message->msg_number = msg_number;
	}

	return message;
}