Commit f9a394db authored by unknown's avatar unknown
Browse files

InnoDB: Fix Bug #7350 without hard-coding charset-collation numbers.


innobase/data/data0type.c:
  Add mbminlen and mbmaxlen to dtype_t
innobase/include/data0type.h:
  Add mbminlen and mbmaxlen to dtype_t
  Add dtype_get_mbminlen() and dtype_get_mbmaxlen()
innobase/include/data0type.ic:
  Add dtype_set_mblen()
  Add dtype_get_mbminlen() and dtype_get_mbmaxlen()
  Replace innobase_is_mb_cset() with innobase_get_mb_cset()
innobase/include/row0mysql.h:
  Add mbminlen and mbmaxlen
innobase/include/row0mysql.ic:
  Detect UCS2 collations based on mbminlen
innobase/row/row0sel.c:
  Detect UCS2 collations based on mbminlen
sql/ha_innodb.cc:
  Replace innobase_is_mb_cset() with innobase_get_mb_cset()
  build_template(): Initialize templ->mbminlen and templ->mbmaxlen
parent 63bcbfc4
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ charset-collation code for them. */
ulint	data_mysql_default_charset_coll		= 99999999;
ulint	data_mysql_latin1_swedish_charset_coll	= 99999999;

dtype_t		dtype_binary_val = {DATA_BINARY, 0, 0, 0};
dtype_t		dtype_binary_val = {DATA_BINARY, 0, 0, 0, 0, 0};
dtype_t* 	dtype_binary 	= &dtype_binary_val;

/*************************************************************************
@@ -216,6 +216,8 @@ dtype_validate(
		ut_a((type->prtype & DATA_MYSQL_TYPE_MASK) < DATA_N_SYS_COLS);
	}

	ut_a(type->mbminlen <= type->mbmaxlen);

	return(TRUE);
}

+22 −1
Original line number Diff line number Diff line
@@ -271,6 +271,24 @@ dtype_get_prec(
/*===========*/
	dtype_t*	type);
/*************************************************************************
Gets the minimum length of a character, in bytes. */
UNIV_INLINE
ulint
dtype_get_mbminlen(
/*===============*/
				/* out: minimum length of a char, in bytes,
				or 0 if this is not a character type */
	const dtype_t*	type);	/* in: type */
/*************************************************************************
Gets the maximum length of a character, in bytes. */
UNIV_INLINE
ulint
dtype_get_mbmaxlen(
/*===============*/
				/* out: maximum length of a char, in bytes,
				or 0 if this is not a character type */
	const dtype_t*	type);	/* in: type */
/*************************************************************************
Gets the padding character code for the type. */
UNIV_INLINE
ulint
@@ -358,10 +376,13 @@ struct dtype_struct{
	ulint	mtype;		/* main data type */
	ulint	prtype;		/* precise type; MySQL data type */

	/* the remaining two fields do not affect alphabetical ordering: */
	/* the remaining fields do not affect alphabetical ordering: */

	ulint	len;		/* length */
	ulint	prec;		/* precision */

	ulint	mbminlen;	/* minimum length of a character, in bytes */
	ulint	mbmaxlen;	/* maximum length of a character, in bytes */
};

#ifndef UNIV_NONINL
+67 −19
Original line number Diff line number Diff line
@@ -9,15 +9,46 @@ Created 1/16/1996 Heikki Tuuri
#include "mach0data.h"

/**********************************************************************
Determines whether the given character set is of variable length.
Get the variable length bounds of the given character set.

NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
this function, you MUST change also the prototype here! */
extern
ibool
innobase_is_mb_cset(
/*================*/
	ulint	cset);	/* in: MySQL charset-collation code */
void
innobase_get_mb_cset(
/*=================*/
	ulint	cset,		/* in: MySQL charset-collation code */
	ulint*	mbminlen,	/* out: minimum length of a char (in bytes) */
	ulint*	mbmaxlen);	/* out: maximum length of a char (in bytes) */

/*************************************************************************
Gets the MySQL charset-collation code for MySQL string types. */
UNIV_INLINE
ulint
dtype_get_charset_coll(
/*===================*/
	ulint	prtype)	/* in: precise data type */
{
	return((prtype >> 16) & 0xFFUL);
}

/*************************************************************************
Sets the mbminlen and mbmaxlen members of a data type structure. */
UNIV_INLINE
void
dtype_set_mblen(
/*============*/
	dtype_t*	type)	/* in/out: type struct */
{
	ut_ad(type);
	if (dtype_is_string_type(type->mtype)) {
		innobase_get_mb_cset(dtype_get_charset_coll(type->prtype),
				&type->mbminlen, &type->mbmaxlen);
		ut_ad(type->mbminlen <= type->mbmaxlen);
	} else {
		type->mbminlen = type->mbmaxlen = 0;
	}
}

/*************************************************************************
Sets a data type structure. */
@@ -39,6 +70,7 @@ dtype_set(
	type->len = len;
	type->prec = prec;

	dtype_set_mblen(type);
	ut_ad(dtype_validate(type));
}

@@ -82,17 +114,6 @@ dtype_get_prtype(
	return(type->prtype);
}

/*************************************************************************
Gets the MySQL charset-collation code for MySQL string types. */
UNIV_INLINE
ulint
dtype_get_charset_coll(
/*===================*/
	ulint	prtype)	/* in: precise data type */
{
	return((prtype >> 16) & 0xFFUL);
}

/*************************************************************************
Gets the type length. */
UNIV_INLINE
@@ -119,6 +140,33 @@ dtype_get_prec(
	return(type->prec);
}

/*************************************************************************
Gets the minimum length of a character, in bytes. */
UNIV_INLINE
ulint
dtype_get_mbminlen(
/*===============*/
				/* out: minimum length of a char, in bytes,
				or 0 if this is not a character type */
	const dtype_t*	type)	/* in: type */
{
	ut_ad(type);
	return(type->mbminlen);
}
/*************************************************************************
Gets the maximum length of a character, in bytes. */
UNIV_INLINE
ulint
dtype_get_mbmaxlen(
/*===============*/
				/* out: maximum length of a char, in bytes,
				or 0 if this is not a character type */
	const dtype_t*	type)	/* in: type */
{
	ut_ad(type);
	return(type->mbmaxlen);
}

/*************************************************************************
Gets the padding character code for the type. */
UNIV_INLINE
@@ -211,6 +259,7 @@ dtype_read_for_order_and_null_size(
		
	type->prtype = dtype_form_prtype(type->prtype,
					data_mysql_default_charset_coll);
	dtype_set_mblen(type);
}	

/**************************************************************************
@@ -262,6 +311,7 @@ dtype_new_read_for_order_and_null_size(
		
		type->prtype = dtype_form_prtype(type->prtype, charset_coll);
	}						
	dtype_set_mblen(type);
}

/***************************************************************************
@@ -306,9 +356,7 @@ dtype_get_fixed_size(
	case DATA_DOUBLE:
	case DATA_MYSQL:
			if ((type->prtype & DATA_BINARY_TYPE)
					|| !innobase_is_mb_cset(
					dtype_get_charset_coll(
						type->prtype))) {
					|| type->mbminlen == type->mbmaxlen) {
				return(dtype_get_len(type));
			}
			/* fall through for variable-length charsets */
+4 −0
Original line number Diff line number Diff line
@@ -458,6 +458,10 @@ struct mysql_row_templ_struct {
					numbers DATA_CHAR... */
	ulint	charset;		/* MySQL charset-collation code
					of the column, or zero */
	ulint	mbminlen;		/* minimum length of a char, in bytes,
					or zero if not a char type */
	ulint	mbmaxlen;		/* maximum length of a char, in bytes,
					or zero if not a char type */
	ulint	is_unsigned;		/* if a column type is an integer
					type and this field is != 0, then
					it is an unsigned integer type */
+5 −10
Original line number Diff line number Diff line
@@ -93,17 +93,11 @@ row_mysql_store_col_in_innobase_format(
						|| type == DATA_BINARY) {
		/* Remove trailing spaces. */

		/* Handle UCS2 strings differently.  As no new
		collations will be introduced in 4.1, we hardcode the
		charset-collation codes here.  In 5.0, the logic will
		be based on mbminlen. */
		ulint	cset	= dtype_get_charset_coll(
				dtype_get_prtype(dfield_get_type(dfield)));
		/* Handle UCS2 strings differently. */
		ulint	mbminlen	= dtype_get_mbminlen(
						dfield_get_type(dfield));
		ptr = row_mysql_read_var_ref(&col_len, mysql_data);
		if (cset == 35/*ucs2_general_ci*/
				|| cset == 90/*ucs2_bin*/
				|| (cset >= 128/*ucs2_unicode_ci*/
				&& cset <= 144/*ucs2_persian_ci*/)) {
		if (mbminlen == 2) {
			/* space=0x0020 */
			/* Trim "half-chars", just in case. */
			col_len &= ~1;
@@ -113,6 +107,7 @@ row_mysql_store_col_in_innobase_format(
				col_len -= 2;
			}
		} else {
			ut_a(mbminlen == 1);
			/* space=0x20 */
			while (col_len > 0 && ptr[col_len - 1] == 0x20) {
				col_len--;
Loading