Commit bbd402dc authored by unknown's avatar unknown
Browse files

Fixed unique prefix key bug for multibyte character sets (BUG #4521) for

InnoDB. This fixes also a second part of the same problem with prefix keys
on a multibyte string column for InnoDB.


innobase/btr/btr0btr.c:
  Multibyte character set prefix indexes are not any more fixed size. Therefore,
  we have to chect that length of the index field in not greater than
  prefix length.
innobase/rem/rem0cmp.c:
  Remove unnecessary changes.
innobase/row/row0ins.c:
  Fixed unique prefix key or prefix key using multibyte character set bugs for
  InnoDB (BUG #4521). For prefix keys we have to get the storage length
  for the prefix length of characters in the key.
innobase/row/row0row.c:
  Fixed unique prefix key or prefix key using multibyte character set bugs for
  InnoDB (BUG #4521). For prefix keys we have to get the storage length
  for the prefix length of characters in the key.
innobase/row/row0sel.c:
  Fixed unique prefix key or prefix key using multibyte character set bugs for
  InnoDB (BUG #4521). For prefix keys we have to get the storage length
  for the prefix length of characters in the key.
innobase/row/row0upd.c:
  Fixed unique prefix key or prefix key using multibyte character set bugs for
  InnoDB (BUG #4521). For prefix keys we have to get the storage length
  for the prefix length of characters in the key.
mysql-test/r/ctype_utf8.result:
  Added utf8 character test cases for InnoDB.
mysql-test/t/ctype_utf8.test:
  Added utf8 character expected test results for InnoDB.
sql/ha_innodb.cc:
  Added function innobase_get_at_most_n_mbchars to return position of
  the nth character in the multibyte character string.
sql/ha_innodb.h:
  Remove unnecessary changes.
parent 3e3981b5
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -2401,13 +2401,16 @@ btr_index_rec_validate(

		rec_get_nth_field(rec, i, &len);

		/* Note that prefix indexes are not fixed size even when
		their type is CHAR. */

		if ((dict_index_get_nth_field(index, i)->prefix_len == 0
		    && len != UNIV_SQL_NULL && dtype_is_fixed_size(type)
		    && len != dtype_get_fixed_size(type))
		   ||
		   (dict_index_get_nth_field(index, i)->prefix_len > 0
		    && len != UNIV_SQL_NULL && dtype_is_fixed_size(type)
		    && len !=
		    && len != UNIV_SQL_NULL
		    && len >
			   dict_index_get_nth_field(index, i)->prefix_len)) {

			btr_index_rec_validate_report(page, rec, index);
+2 −32
Original line number Diff line number Diff line
@@ -14,9 +14,6 @@ Created 7/1/1994 Heikki Tuuri

#include "srv0srv.h"

#include <m_ctype.h>
#include <my_sys.h>

/*		ALPHABETICAL ORDER
		==================
		
@@ -456,8 +453,6 @@ cmp_dtuple_rec_with_match(
					in current field */
	int		ret = 3333;	/* return value */

	CHARSET_INFO*   charset;        /* charset used in the field */

	ut_ad(dtuple && rec && matched_fields && matched_bytes);
	ut_ad(dtuple_check_typed(dtuple));

@@ -546,33 +541,8 @@ cmp_dtuple_rec_with_match(
			&& dtype_get_charset_coll(cur_type->prtype) !=
				data_mysql_latin1_swedish_charset_coll)) {

		  	/* If character set is not latin1_swedish
			we have to devide character length by the
			maximum bytes needed for that character
			set. For example if we have unique prefix
			index for 1 utf8 character then we have
			actually 3 bytes allocated in the index.
			Therefore, we have to divide that with
			maximum bytes needed for utf8 character i.e.
			3 byges.*/

                        if ( dtuple_f_len > 0) {
			  charset = get_charset(
				dtype_get_charset_coll(cur_type->prtype), 
				MYF(MY_WME));

			  ut_ad(charset);
			  ut_ad(charset->mbmaxlen);

			  dtuple_f_len = dtuple_f_len / charset->mbmaxlen;

                          if ( dtuple_f_len == 0)
			    dtuple_f_len = 1;

			  rec_f_len = dtuple_f_len;
			} 

			ret = cmp_whole_field(cur_type,
			ret = cmp_whole_field(
				cur_type,
				dfield_get_data(dtuple_field), dtuple_f_len,
				rec_b_ptr, rec_f_len);

+13 −4
Original line number Diff line number Diff line
@@ -1999,6 +1999,7 @@ row_ins_index_entry_set_vals(
	dfield_t*	row_field;
	ulint		n_fields;
	ulint		i;
	dtype_t*        cur_type;

	ut_ad(entry && row);

@@ -2012,10 +2013,18 @@ row_ins_index_entry_set_vals(

		/* Check column prefix indexes */
		if (ind_field->prefix_len > 0
		    && dfield_get_len(row_field) != UNIV_SQL_NULL
		    && dfield_get_len(row_field) > ind_field->prefix_len) {
		    && dfield_get_len(row_field) != UNIV_SQL_NULL) {

		        field->len = ind_field->prefix_len;
			/* For prefix keys get the storage length
			for the prefix_len characters. */

			cur_type = dict_col_get_type(
				dict_field_get_col(ind_field));

			field->len = innobase_get_at_most_n_mbchars(
				dtype_get_charset_coll(cur_type->prtype),
				ind_field->prefix_len,
				dfield_get_len(field),row_field->data);
		} else {
		        field->len = row_field->len;
		}
+27 −6
Original line number Diff line number Diff line
@@ -113,6 +113,8 @@ row_build_index_entry(
	dfield_t*	dfield2;
	dict_col_t*	col;
	ulint		i;
        ulint           storage_len;
	dtype_t*	cur_type;

	ut_ad(row && index && heap);
	ut_ad(dtuple_check_typed(row));
@@ -139,10 +141,20 @@ row_build_index_entry(

		/* If a column prefix index, take only the prefix */
		if (ind_field->prefix_len > 0
		    && dfield_get_len(dfield2) != UNIV_SQL_NULL
		    && dfield_get_len(dfield2) > ind_field->prefix_len) {
		    && dfield_get_len(dfield2) != UNIV_SQL_NULL) {
			
			dfield_set_len(dfield, ind_field->prefix_len);
			/* For prefix keys get the storage length
			for the prefix_len characters. */

			cur_type = dict_col_get_type(
				dict_field_get_col(ind_field));

			storage_len = innobase_get_at_most_n_mbchars(
				dtype_get_charset_coll(cur_type->prtype),
				ind_field->prefix_len,
				dfield_get_len(dfield2),dfield2->data);

			dfield_set_len(dfield,storage_len);
		}
	}

@@ -460,6 +472,7 @@ row_build_row_ref_from_row(
	dict_col_t*	col;
	ulint		ref_len;
	ulint		i;
	dtype_t*	cur_type;
	
	ut_ad(ref && table && row);
		
@@ -481,10 +494,18 @@ row_build_row_ref_from_row(
		dfield_copy(dfield, dfield2);

		if (field->prefix_len > 0
		    && dfield->len != UNIV_SQL_NULL
		    && dfield->len > field->prefix_len) {
		    && dfield->len != UNIV_SQL_NULL) {

			/* For prefix keys get the storage length
			for the prefix_len characters. */

			cur_type = dict_col_get_type(
				dict_field_get_col(field));

		        dfield->len = field->prefix_len;
			dfield->len = innobase_get_at_most_n_mbchars(
				dtype_get_charset_coll(cur_type->prtype),
				field->prefix_len,
				dfield->len,dfield->data);
		}
	}

+12 −3
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ row_sel_sec_rec_is_for_clust_rec(
        ulint           clust_len;
        ulint           n;
        ulint           i;
	dtype_t*	cur_type;

	UT_NOT_USED(clust_index);

@@ -91,10 +92,18 @@ row_sel_sec_rec_is_for_clust_rec(
                sec_field = rec_get_nth_field(sec_rec, i, &sec_len);

		if (ifield->prefix_len > 0
		    && clust_len != UNIV_SQL_NULL
		    && clust_len > ifield->prefix_len) {
		    && clust_len != UNIV_SQL_NULL) {

		       clust_len = ifield->prefix_len;
			/* For prefix keys get the storage length
			for the prefix_len characters. */

			cur_type = dict_col_get_type(
				dict_field_get_col(ifield));

			clust_len = innobase_get_at_most_n_mbchars(
				dtype_get_charset_coll(cur_type->prtype),
				ifield->prefix_len,
				clust_len,clust_field);
		}

                if (0 != cmp_data_data(dict_col_get_type(col),
Loading