Exemple #1
0
/*************************************************************//**
Used in debug checking of cmp_dtuple_... .
This function is used to compare a data tuple to a physical record. If
dtuple has n fields then rec must have either m >= n fields, or it must
differ from dtuple in some of the m fields rec has. If encounters an
externally stored field, returns 0.
@return 1, 0, -1, if dtuple is greater, equal, less than rec,
respectively, when only the common first fields are compared */
static
int
cmp_debug_dtuple_rec_with_match(
/*============================*/
	const dtuple_t*	dtuple,	/*!< in: data tuple */
	const rec_t*	rec,	/*!< in: physical record which differs from
				dtuple in some of the common fields, or which
				has an equal number or more fields than
				dtuple */
	const ulint*	offsets,/*!< in: array returned by rec_get_offsets() */
	ulint*		matched_fields) /*!< in/out: number of already
				completely matched fields; when function
				returns, contains the value for current
				comparison */
{
	const dfield_t*	dtuple_field;	/* current field in logical record */
	ulint		dtuple_f_len;	/* the length of the current field
					in the logical record */
	const byte*	dtuple_f_data;	/* pointer to the current logical
					field data */
	ulint		rec_f_len;	/* length of current field in rec */
	const byte*	rec_f_data;	/* pointer to the current rec field */
	int		ret = 3333;	/* return value */
	ulint		cur_field;	/* current field number */

	ut_ad(dtuple && rec && matched_fields);
	ut_ad(dtuple_check_typed(dtuple));
	ut_ad(rec_offs_validate(rec, NULL, offsets));

	ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple));
	ut_ad(*matched_fields <= rec_offs_n_fields(offsets));

	cur_field = *matched_fields;

	if (cur_field == 0) {
		if (UNIV_UNLIKELY
		    (rec_get_info_bits(rec, rec_offs_comp(offsets))
		     & REC_INFO_MIN_REC_FLAG)) {

			ret = !(dtuple_get_info_bits(dtuple)
				& REC_INFO_MIN_REC_FLAG);

			goto order_resolved;
		}

		if (UNIV_UNLIKELY
		    (dtuple_get_info_bits(dtuple) & REC_INFO_MIN_REC_FLAG)) {
			ret = -1;

			goto order_resolved;
		}
	}

	/* Match fields in a loop; stop if we run out of fields in dtuple */

	while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {

		ulint	mtype;
		ulint	prtype;

		dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
		{
			const dtype_t*	type
				= dfield_get_type(dtuple_field);

			mtype = type->mtype;
			prtype = type->prtype;
		}

		dtuple_f_data = dfield_get_data(dtuple_field);
		dtuple_f_len = dfield_get_len(dtuple_field);

		rec_f_data = rec_get_nth_field(rec, offsets,
					       cur_field, &rec_f_len);

		if (rec_offs_nth_extern(offsets, cur_field)) {
			/* We do not compare to an externally stored field */

			ret = 0;

			goto order_resolved;
		}

		ret = cmp_data_data(mtype, prtype, dtuple_f_data, dtuple_f_len,
				    rec_f_data, rec_f_len);
		if (ret != 0) {
			goto order_resolved;
		}

		cur_field++;
	}

	ret = 0;	/* If we ran out of fields, dtuple was equal to rec
			up to the common fields */
order_resolved:
	ut_ad((ret >= - 1) && (ret <= 1));

	*matched_fields = cur_field;

	return(ret);
}
Exemple #2
0
/*************************************************************//**
This function is used to compare a data tuple to a physical record.
Only dtuple->n_fields_cmp first fields are taken into account for
the data tuple! If we denote by n = n_fields_cmp, then rec must
have either m >= n fields, or it must differ from dtuple in some of
the m fields rec has. If rec has an externally stored field we do not
compare it but return with value 0 if such a comparison should be
made.
@return 1, 0, -1, if dtuple is greater, equal, less than rec,
respectively, when only the common first fields are compared, or until
the first externally stored field in rec */
UNIV_INTERN
int
cmp_dtuple_rec_with_match(
/*======================*/
	const dtuple_t*	dtuple,	/*!< in: data tuple */
	const rec_t*	rec,	/*!< in: physical record which differs from
				dtuple in some of the common fields, or which
				has an equal number or more fields than
				dtuple */
	const ulint*	offsets,/*!< in: array returned by rec_get_offsets() */
	ulint*		matched_fields, /*!< in/out: number of already completely
				matched fields; when function returns,
				contains the value for current comparison */
	ulint*		matched_bytes) /*!< in/out: number of already matched
				bytes within the first field not completely
				matched; when function returns, contains the
				value for current comparison */
{
	const dfield_t*	dtuple_field;	/* current field in logical record */
	ulint		dtuple_f_len;	/* the length of the current field
					in the logical record */
	const byte*	dtuple_b_ptr;	/* pointer to the current byte in
					logical field data */
	ulint		dtuple_byte;	/* value of current byte to be compared
					in dtuple*/
	ulint		rec_f_len;	/* length of current field in rec */
	const byte*	rec_b_ptr;	/* pointer to the current byte in
					rec field */
	ulint		rec_byte;	/* value of current byte to be
					compared in rec */
	ulint		cur_field;	/* current field number */
	ulint		cur_bytes;	/* number of already matched bytes
					in current field */
	int		ret = 3333;	/* return value */

	ut_ad(dtuple && rec && matched_fields && matched_bytes);
	ut_ad(dtuple_check_typed(dtuple));
	ut_ad(rec_offs_validate(rec, NULL, offsets));

	cur_field = *matched_fields;
	cur_bytes = *matched_bytes;

	ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
	ut_ad(cur_field <= rec_offs_n_fields(offsets));

	if (cur_bytes == 0 && cur_field == 0) {
		ulint	rec_info = rec_get_info_bits(rec,
						     rec_offs_comp(offsets));
		ulint	tup_info = dtuple_get_info_bits(dtuple);

		if (UNIV_UNLIKELY(rec_info & REC_INFO_MIN_REC_FLAG)) {
			ret = !(tup_info & REC_INFO_MIN_REC_FLAG);
			goto order_resolved;
		} else if (UNIV_UNLIKELY(tup_info & REC_INFO_MIN_REC_FLAG)) {
			ret = -1;
			goto order_resolved;
		}
	}

	/* Match fields in a loop; stop if we run out of fields in dtuple
	or find an externally stored field */

	while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {

		ulint	mtype;
		ulint	prtype;

		dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
		{
			const dtype_t*	type
				= dfield_get_type(dtuple_field);

			mtype = type->mtype;
			prtype = type->prtype;
		}

		dtuple_f_len = dfield_get_len(dtuple_field);

		rec_b_ptr = rec_get_nth_field(rec, offsets,
					      cur_field, &rec_f_len);

		/* If we have matched yet 0 bytes, it may be that one or
		both the fields are SQL null, or the record or dtuple may be
		the predefined minimum record, or the field is externally
		stored */

		if (UNIV_LIKELY(cur_bytes == 0)) {
			if (rec_offs_nth_extern(offsets, cur_field)) {
				/* We do not compare to an externally
				stored field */

				ret = 0;

				goto order_resolved;
			}

			if (dtuple_f_len == UNIV_SQL_NULL) {
				if (rec_f_len == UNIV_SQL_NULL) {

					goto next_field;
				}

				ret = -1;
				goto order_resolved;
			} else if (rec_f_len == UNIV_SQL_NULL) {
				/* We define the SQL null to be the
				smallest possible value of a field
				in the alphabetical order */

				ret = 1;
				goto order_resolved;
			}
		}

		if (mtype >= DATA_FLOAT
		    || (mtype == DATA_BLOB
			&& 0 == (prtype & DATA_BINARY_TYPE)
			&& dtype_get_charset_coll(prtype)
			!= DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {

			ret = cmp_whole_field(mtype, prtype,
					      dfield_get_data(dtuple_field),
					      (unsigned) dtuple_f_len,
					      rec_b_ptr, (unsigned) rec_f_len);

			if (ret != 0) {
				cur_bytes = 0;

				goto order_resolved;
			} else {
				goto next_field;
			}
		}

		/* Set the pointers at the current byte */

		rec_b_ptr = rec_b_ptr + cur_bytes;
		dtuple_b_ptr = (byte*)dfield_get_data(dtuple_field)
			+ cur_bytes;
		/* Compare then the fields */

		for (;;) {
			if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) {
				if (dtuple_f_len <= cur_bytes) {

					goto next_field;
				}

				rec_byte = dtype_get_pad_char(mtype, prtype);

				if (rec_byte == ULINT_UNDEFINED) {
					ret = 1;

					goto order_resolved;
				}
			} else {
				rec_byte = *rec_b_ptr;
			}

			if (UNIV_UNLIKELY(dtuple_f_len <= cur_bytes)) {
				dtuple_byte = dtype_get_pad_char(mtype,
								 prtype);

				if (dtuple_byte == ULINT_UNDEFINED) {
					ret = -1;

					goto order_resolved;
				}
			} else {
				dtuple_byte = *dtuple_b_ptr;
			}

			if (dtuple_byte == rec_byte) {
				/* If the bytes are equal, they will
				remain such even after the collation
				transformation below */

				goto next_byte;
			}

			if (mtype <= DATA_CHAR
			    || (mtype == DATA_BLOB
				&& !(prtype & DATA_BINARY_TYPE))) {

				rec_byte = cmp_collate(rec_byte);
				dtuple_byte = cmp_collate(dtuple_byte);
			}

			ret = (int) (dtuple_byte - rec_byte);
			if (UNIV_LIKELY(ret)) {
				if (ret < 0) {
					ret = -1;
					goto order_resolved;
				} else {
					ret = 1;
					goto order_resolved;
				}
			}
next_byte:
			/* Next byte */
			cur_bytes++;
			rec_b_ptr++;
			dtuple_b_ptr++;
		}

next_field:
		cur_field++;
		cur_bytes = 0;
	}

	ut_ad(cur_bytes == 0);

	ret = 0;	/* If we ran out of fields, dtuple was equal to rec
			up to the common fields */
order_resolved:
	ut_ad((ret >= - 1) && (ret <= 1));
	ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec, offsets,
						     matched_fields));
	ut_ad(*matched_fields == cur_field); /* In the debug version, the
					     above cmp_debug_... sets
					     *matched_fields to a value */
	*matched_fields = cur_field;
	*matched_bytes = cur_bytes;

	return(ret);
}
Exemple #3
0
rec_t* 	
rec_convert_dtuple_to_rec_low(
/*==========================*/			
				/* out: pointer to the origin of physical
				record */
	byte*	destination,	/* in: start address of the physical record */
	dtuple_t* dtuple,	/* in: data tuple */
	ulint	data_size)	/* in: data size of dtuple */
{
	dfield_t* 	field;
	ulint		n_fields;
	rec_t* 		rec;
	ulint		end_offset;
	ulint		ored_offset;
	byte*		data;
	ulint		len;
	ulint		i;
	
	ut_ad(destination && dtuple);
	ut_ad(dtuple_validate(dtuple));
	ut_ad(dtuple_check_typed(dtuple));
	ut_ad(dtuple_get_data_size(dtuple) == data_size);

	n_fields = dtuple_get_n_fields(dtuple);

	ut_ad(n_fields > 0);

	/* Calculate the offset of the origin in the physical record */	

	rec = destination + rec_get_converted_extra_size(data_size, n_fields);
	
	/* Store the number of fields */
	rec_set_n_fields(rec, n_fields);

	/* Set the info bits of the record */
	rec_set_info_bits(rec, dtuple_get_info_bits(dtuple));

	/* Store the data and the offsets */

	end_offset = 0;

	if (data_size <= REC_1BYTE_OFFS_LIMIT) {

	    rec_set_1byte_offs_flag(rec, TRUE);

	    for (i = 0; i < n_fields; i++) {

		field = dtuple_get_nth_field(dtuple, i);

		data = dfield_get_data(field);
		len = dfield_get_len(field);
		
		if (len == UNIV_SQL_NULL) {
			len = dtype_get_sql_null_size(dfield_get_type(field));
			data_write_sql_null(rec + end_offset, len);
		
			end_offset += len;
			ored_offset = end_offset | REC_1BYTE_SQL_NULL_MASK;
		} else {
			/* If the data is not SQL null, store it */
			ut_memcpy(rec + end_offset, data, len);

			end_offset += len;
			ored_offset = end_offset;
		}

		rec_1_set_field_end_info(rec, i, ored_offset);
	    }
	} else {
	    rec_set_1byte_offs_flag(rec, FALSE);

	    for (i = 0; i < n_fields; i++) {

		field = dtuple_get_nth_field(dtuple, i);

		data = dfield_get_data(field);
		len = dfield_get_len(field);
		
		if (len == UNIV_SQL_NULL) {
			len = dtype_get_sql_null_size(dfield_get_type(field));
			data_write_sql_null(rec + end_offset, len);
		
			end_offset += len;
			ored_offset = end_offset | REC_2BYTE_SQL_NULL_MASK;
		} else {
			/* If the data is not SQL null, store it */
			ut_memcpy(rec + end_offset, data, len);

			end_offset += len;
			ored_offset = end_offset;
		}

		rec_2_set_field_end_info(rec, i, ored_offset);
	    }
	}

	ut_ad(rec_validate(rec));

	return(rec);
}