Beispiel #1
0
static dsc* execute_concatenate( qli_nod* node, const dsc* value1, const dsc* value2)
{
/**************************************
 *
 *	e x e c u t e _ c o n c a t e n a t e
 *
 **************************************
 *
 * Functional description
 *	Concatenate two strings.
 *
 **************************************/
	Firebird::VaryStr<32> temp1;
	const TEXT* address1;
	USHORT length1 = MOVQ_get_string(value1, &address1, &temp1, sizeof(temp1));

	Firebird::VaryStr<32> temp2;
	const TEXT* address2;
	USHORT length2 = MOVQ_get_string(value2, &address2, &temp2, sizeof(temp2));

	dsc* desc = &node->nod_desc;
	vary* avary = (vary*) desc->dsc_address;
	TEXT* p = avary->vary_string;
	length1 = MIN(length1, desc->dsc_length - 2);
	length2 = MAX(MIN(length2, desc->dsc_length - 2 - length1), 0);
	fb_assert(static_cast<ULONG>(length1) + length2 <= MAX_USHORT - 2);

	if (length1)
	{
		memcpy(p, address1, length1);
		p += length1;
	}

	if (length2)
		memcpy(p, address2, length2);

	avary->vary_length = length1 + length2;

	return desc;
}
Beispiel #2
0
static bool sleuth( qli_nod* node, const dsc* desc1, const dsc* desc2, const dsc* desc3)
{
/**************************************
 *
 *	s l e u t h
 *
 **************************************
 *
 * Functional description
 *	Return true if a string (p1, l1) matches a given pattern (p2, l2),
 *	using a pattern language defined in p3, l3.
 *
 **************************************/

	// Get operator definition string (control string)

	Firebird::VaryStr<TEMP_STR_LENGTH> temp1;
	const TEXT* p1;
	SSHORT l1 = MOVQ_get_string(desc3, &p1, &temp1, TEMP_STR_LENGTH);

	// Get address and length of search string

	Firebird::VaryStr<TEMP_STR_LENGTH> temp2;
	const TEXT* p2;
	SSHORT l2 = MOVQ_get_string(desc2, &p2, &temp2, TEMP_STR_LENGTH);

	// Merge search and control strings

	UCHAR control[256];
	l2 = sleuth_merge((const UCHAR*) p2, (const UCHAR*) p1, (const UCHAR*) (p1 + l1), control);

	// If source is not a blob, do a simple search

	if (desc1->dsc_dtype != dtype_blob)
	{
		l1 = MOVQ_get_string(desc1, &p1, &temp1, TEMP_STR_LENGTH);
		return sleuth_check(0, (const UCHAR*) p1, (const UCHAR*) (p1 + l1), control, control + l2);
	}

	// Source string is a blob, things get interesting

	bool result = false;

	FB_API_HANDLE blob = EXEC_open_blob(node->nod_arg[0]);

	TEXT fixed_buffer[512];
	USHORT buffer_length = sizeof(fixed_buffer);

	TEXT* buffer = make_blob_buffer( blob, &buffer_length);
	if (!buffer)
		buffer = fixed_buffer;

	ISC_STATUS_ARRAY status_vector;
	while (!isc_get_segment(status_vector, &blob, (USHORT*) &l1, buffer_length, buffer))
		if (sleuth_check(0, (UCHAR*) buffer, (UCHAR*) (buffer + l1), control, control + l2))
		{
			result = true;
			break;
		}

	if (buffer != fixed_buffer)
		gds__free(buffer);

	if (isc_close_blob(status_vector, &blob))
	{
		qli_ctx* context = (qli_ctx*) node->nod_arg[e_fld_context];
		qli_req* request = context->ctx_request;
		qli_dbb* dbb = request->req_database;
		ERRQ_database_error(dbb, status_vector);
	}

	return result;
}
Beispiel #3
0
static bool string_boolean( qli_nod* node)
{
/**************************************
 *
 *	s t r i n g _ b o o l e a n
 *
 **************************************
 *
 * Functional description
 *	Perform one of the complex string functions CONTAINING, MATCHES,
 *	or STARTS WITH.
 *
 **************************************/
	const DSC *desc1, *desc2, *desc3;

	if (!(desc1 = EVAL_value(node->nod_arg[0])) || (desc1->dsc_missing & DSC_missing) ||
		!(desc2 = EVAL_value(node->nod_arg[1])) || (desc2->dsc_missing & DSC_missing) ||
		(node->nod_arg[2] && (!(desc3 = EVAL_value(node->nod_arg[2])) ||
							  (desc3->dsc_missing & DSC_missing))))
	{
		return false;
	}

	if (node->nod_type == nod_sleuth)
		return sleuth(node, desc1, desc2, desc3);

	// Get address and length of strings

	const TEXT* p2;
	Firebird::VaryStr<TEMP_STR_LENGTH> temp2;
	SSHORT l2 = MOVQ_get_string(desc2, &p2, &temp2, TEMP_STR_LENGTH);

	// If source is not a blob, do a simple search

	if (desc1->dsc_dtype != dtype_blob)
	{
		Firebird::VaryStr<TEMP_STR_LENGTH> temp1;
		const TEXT* p1;
		SSHORT l1 = MOVQ_get_string(desc1, &p1, &temp1, TEMP_STR_LENGTH);
		return string_function(node, l1, p1, l2, p2);
	}

	// Source string is a blob, things get interesting

	bool result = false;
	FB_API_HANDLE blob = EXEC_open_blob(node->nod_arg[0]);

    TEXT fixed_buffer[512];
	USHORT buffer_length = sizeof(fixed_buffer);

	TEXT* buffer = make_blob_buffer( blob, &buffer_length);
	if (!buffer)
		buffer = fixed_buffer;

	ISC_STATUS_ARRAY status_vector;
	SSHORT l3 = 0;
	while (!isc_get_segment(status_vector, &blob, (USHORT*) &l3, buffer_length, buffer))
	{
		if (string_function(node, l3, buffer, l2, p2))
		{
			result = true;
			break;
		}
	}

	if (buffer != fixed_buffer)
		gds__free(buffer);

	if (isc_close_blob(status_vector, &blob))
	{
		qli_ctx* context = (qli_ctx*) node->nod_arg[e_fld_context];
		qli_req* request = context->ctx_request;
		qli_dbb* database = request->req_database;
		ERRQ_database_error(database, status_vector);
	}

	return result;
}
Beispiel #4
0
static bool string_function(qli_nod* node,
						   SSHORT l1, const TEXT* p1, SSHORT l2, const TEXT* p2)
{
/**************************************
 *
 *	s t r i n g _ f u n c t i o n
 *
 **************************************
 *
 * Functional description
 *	Perform one of the complex string functions CONTAINING, MATCHES,
 *	or STARTS WITH.
 *
 **************************************/

	// Handle "STARTS WITH"

	if (node->nod_type == nod_starts)
	{
		if (l1 < l2)
			return false;

		if (l2)
			return memcmp(p1, p2, l2) == 0;

		return true;
	}

	// Handle CONTAINS

	if (node->nod_type == nod_containing)
	{
		while (l1 >= l2)
		{
			--l1;
			const TEXT* q1 = p1++;
			const TEXT* q2 = p2;
			SSHORT l = l2;
			TEXT c1, c2;
			do {
				if (--l < 0)
					return true;
				c1 = *q1++;
				c2 = *q2++;
			} while (UPPER(c1) == UPPER(c2));
		}
		return false;
	}

	// Handle LIKE

	if (node->nod_type == nod_like)
	{
		TEXT c1 = 0;
		Firebird::VaryStr<16> temp;
		const TEXT* q1 = NULL;
		if (node->nod_count > 2 &&
			MOVQ_get_string(EVAL_value(node->nod_arg[2]), &q1, &temp, sizeof(temp)))
		{
			c1 = *q1;
		}
		if (like((const UCHAR*) p1, l1, (const UCHAR*) p2, l2, c1))
			return true;
		return false;
	}

	// Handle MATCHES

	return node->nod_type == nod_matches && matches(p1, l1, p2, l2);
}
static void edit_alpha(const dsc* desc,
					   pics* picture, TEXT** output, USHORT max_length)
{
/**************************************
 *
 *	e d i t _ a l p h a
 *
 **************************************
 *
 * Functional description
 *	Edit data from a descriptor through an edit string to a running
 *	output pointer.
 *
 **************************************/
	Firebird::VaryStr<512> temp;

	const TEXT* p = NULL;
	const USHORT l = MOVQ_get_string(desc, &p, &temp, sizeof(temp));
	const TEXT* const end = p + l;
	picture->pic_pointer = picture->pic_string;
	picture->pic_count = 0;
	TEXT* out = *output;

	while (p < end)
	{
		if ((out - *output) >= max_length)
			break;
		TEXT c = generate(picture);
		if (!c || c == '?')
			break;

		c = UPPER(c);

		switch (c)
		{
		case 'X':

			*out++ = *p++;
			break;

		case 'A':
			if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z'))
				*out++ = *p++;
			else
				IBERROR(69);	// Msg 69 conversion error
			break;

		case 'B':
			*out++ = ' ';
			break;

		case '"':
		case '\'':
		case '\\':
			literal(picture, c, &out);
			break;

		default:
			*out++ = c;
			break;
		}
	}

	*output = out;
}