diff -rpu storage/innobase/data/data0type.c storage/innobase/data/data0type.c --- storage/innobase/data/data0type.c 2008-09-11 11:36:30.000000000 +0300 +++ storage/innobase/data/data0type.c 2008-10-28 10:09:43.000000000 +0200 @@ -51,9 +51,7 @@ dtype_get_at_most_n_mbchars( /* out: length of the prefix, in bytes */ ulint prtype, /* in: precise type */ - ulint mbminlen, /* in: minimum length of a - multi-byte character */ - ulint mbmaxlen, /* in: maximum length of a + ulint mbminmaxlen, /* in: minimum and maximum length of a multi-byte character */ ulint prefix_len, /* in: length of the requested prefix, in characters, multiplied by @@ -63,6 +61,9 @@ dtype_get_at_most_n_mbchars( length is being determined */ { #ifndef UNIV_HOTBACKUP + ulint mbminlen = mbminmaxlen % DATA_MBMAX; + ulint mbmaxlen = mbminmaxlen / DATA_MBMAX; + ut_a(data_len != UNIV_SQL_NULL); ut_ad(!mbmaxlen || !(prefix_len % mbmaxlen)); @@ -197,7 +198,7 @@ dtype_validate( ut_a((type->prtype & DATA_MYSQL_TYPE_MASK) < DATA_N_SYS_COLS); } - ut_a(type->mbminlen <= type->mbmaxlen); + ut_a(dtype_get_mbminlen(type) <= dtype_get_mbmaxlen(type)); return(TRUE); } diff -rpu storage/innobase/dict/dict0mem.c storage/innobase/dict/dict0mem.c --- storage/innobase/dict/dict0mem.c 2008-09-11 11:36:30.000000000 +0300 +++ storage/innobase/dict/dict0mem.c 2008-10-28 09:35:58.000000000 +0200 @@ -217,9 +217,7 @@ dict_mem_table_add_col( col->len = (unsigned int) len; dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen); - - col->mbminlen = (unsigned int) mbminlen; - col->mbmaxlen = (unsigned int) mbmaxlen; + dict_col_set_mbminmaxlen(col, mbminlen, mbmaxlen); } /************************************************************************** diff -rpu storage/innobase/handler/ha_innodb.cc storage/innobase/handler/ha_innodb.cc --- storage/innobase/handler/ha_innodb.cc 2008-10-24 11:10:56.000000000 +0300 +++ storage/innobase/handler/ha_innodb.cc 2008-10-28 09:45:19.000000000 +0200 @@ -3170,6 +3170,7 @@ build_template( 'fields'. */ for (i = 0; i < n_fields; i++) { + const dict_col_t* col = &index->table->cols[i]; templ = prebuilt->mysql_template + n_requested_fields; field = table->field[i]; @@ -3224,7 +3225,7 @@ include_field: if (index == clust_index) { templ->rec_field_no = dict_col_get_clust_pos_noninline( - &index->table->cols[i], index); + col, index); } else { templ->rec_field_no = dict_index_get_nth_col_pos( index, i); @@ -3253,7 +3254,7 @@ include_field: mysql_prefix_len = templ->mysql_col_offset + templ->mysql_col_len; } - templ->type = index->table->cols[i].mtype; + templ->type = col->mtype; templ->mysql_type = (ulint)field->type(); if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) { @@ -3262,11 +3263,10 @@ include_field: } templ->charset = dtype_get_charset_coll_noninline( - index->table->cols[i].prtype); - templ->mbminlen = index->table->cols[i].mbminlen; - templ->mbmaxlen = index->table->cols[i].mbmaxlen; - templ->is_unsigned = index->table->cols[i].prtype - & DATA_UNSIGNED; + col->prtype); + templ->mbminlen = dict_col_get_mbminlen(col); + templ->mbmaxlen = dict_col_get_mbmaxlen(col); + templ->is_unsigned = col->prtype & DATA_UNSIGNED; if (templ->type == DATA_BLOB) { prebuilt->templ_contains_blob = TRUE; } diff -rpu storage/innobase/include/data0type.h storage/innobase/include/data0type.h --- storage/innobase/include/data0type.h 2008-09-11 11:36:31.000000000 +0300 +++ storage/innobase/include/data0type.h 2008-10-28 10:06:49.000000000 +0200 @@ -54,6 +54,7 @@ binary strings */ can also be latin1_swedish_ci */ #define DATA_MTYPE_MAX 63 /* dtype_store_for_order_and_null_size() requires the values are <= 63 */ + /*-------------------------------------------*/ /* The 'PRECISE TYPE' of a column */ /* @@ -149,6 +150,9 @@ SQL null*/ store the charset-collation number; one byte is left unused, though */ #define DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 6 +/* Maximum multi-byte character length in bytes, plus 1 */ +#define DATA_MBMAX 5 + /************************************************************************* Gets the MySQL type code from a dtype. */ UNIV_INLINE @@ -169,9 +173,7 @@ dtype_get_at_most_n_mbchars( /* out: length of the prefix, in bytes */ ulint prtype, /* in: precise type */ - ulint mbminlen, /* in: minimum length of a - multi-byte character */ - ulint mbmaxlen, /* in: maximum length of a + ulint mbminmaxlen, /* in: minimum and maximum length of a multi-byte character */ ulint prefix_len, /* in: length of the requested prefix, in characters, multiplied by @@ -305,6 +307,19 @@ dtype_get_mbmaxlen( or 0 if this is not a character type */ const dtype_t* type); /* in: type */ /************************************************************************* +Sets the minimum and maximum length of a character, in bytes. */ +UNIV_INLINE +void +dtype_set_mbminmaxlen( +/*==================*/ + dtype_t* type, /* in/out: type */ + ulint mbminlen, /* in: minimum length of a char, + in bytes, or 0 if this is not + a character type */ + ulint mbmaxlen); /* in: maximum length of a char, + in bytes, or 0 if this is not + a character type */ +/************************************************************************* Gets the padding character code for the type. */ UNIV_INLINE ulint @@ -437,10 +452,8 @@ struct dtype_struct{ the string, MySQL uses 1 or 2 bytes to store the string length) */ - unsigned mbminlen:2; /* minimum length of a - character, in bytes */ - unsigned mbmaxlen:3; /* maximum length of a - character, in bytes */ + unsigned mbminmaxlen:5; /* minimum and maximum length of a + character */ }; #ifndef UNIV_NONINL diff -rpu storage/innobase/include/data0type.ic storage/innobase/include/data0type.ic --- storage/innobase/include/data0type.ic 2008-09-11 11:36:31.000000000 +0300 +++ storage/innobase/include/data0type.ic 2008-10-28 10:02:30.000000000 +0200 @@ -65,8 +65,8 @@ dtype_get_mblen( innobase_get_cset_width(dtype_get_charset_coll(prtype), mbminlen, mbmaxlen); ut_ad(*mbminlen <= *mbmaxlen); - ut_ad(*mbminlen <= 2); /* mbminlen in dtype_t is 0..3 */ - ut_ad(*mbmaxlen < 1 << 3); /* mbmaxlen in dtype_t is 0..7 */ + ut_ad(*mbminlen < DATA_MBMAX); + ut_ad(*mbmaxlen < DATA_MBMAX); #else /* !UNIV_HOTBACKUP */ ut_a(mtype <= DATA_BINARY); *mbminlen = *mbmaxlen = 1; @@ -77,6 +77,27 @@ dtype_get_mblen( } /************************************************************************* +Sets the minimum and maximum length of a character, in bytes. */ +UNIV_INLINE +void +dtype_set_mbminmaxlen( +/*==================*/ + dtype_t* type, /* in/out: type */ + ulint mbminlen, /* in: minimum length of a char, + in bytes, or 0 if this is not + a character type */ + ulint mbmaxlen) /* in: maximum length of a char, + in bytes, or 0 if this is not + a character type */ +{ + ut_ad(mbminlen < DATA_MBMAX); + ut_ad(mbmaxlen < DATA_MBMAX); + ut_ad(mbminlen <= mbmaxlen); + + type->mbminmaxlen = mbmaxlen * DATA_MBMAX + mbminlen; +} + +/************************************************************************* Compute the mbminlen and mbmaxlen members of a data type structure. */ UNIV_INLINE void @@ -88,8 +109,7 @@ dtype_set_mblen( ulint mbmaxlen; dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen); - type->mbminlen = mbminlen; - type->mbmaxlen = mbmaxlen; + dtype_set_mbminmaxlen(type, mbminlen, mbmaxlen); ut_ad(dtype_validate(type)); } @@ -179,7 +199,7 @@ dtype_get_mbminlen( const dtype_t* type) /* in: type */ { ut_ad(type); - return(type->mbminlen); + return(UNIV_EXPECT(type->mbminmaxlen % DATA_MBMAX, 1)); } /************************************************************************* Gets the maximum length of a character, in bytes. */ @@ -192,7 +212,7 @@ dtype_get_mbmaxlen( const dtype_t* type) /* in: type */ { ut_ad(type); - return(type->mbmaxlen); + return(type->mbminmaxlen / DATA_MBMAX); } /************************************************************************* @@ -558,5 +578,6 @@ dtype_get_sql_null_size( const dtype_t* type) /* in: type */ { return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, - type->mbminlen, type->mbmaxlen) > 0); + dtype_get_mbminlen(type), + dtype_get_mbmaxlen(type)) > 0); } diff -rpu storage/innobase/include/dict0dict.h storage/innobase/include/dict0dict.h --- storage/innobase/include/dict0dict.h 2008-09-11 11:36:31.000000000 +0300 +++ storage/innobase/include/dict0dict.h 2008-10-28 10:04:52.000000000 +0200 @@ -77,6 +77,31 @@ void dict_load_space_id_list(void); /*=========================*/ /************************************************************************* +Gets the minimum number of bytes per character. */ +UNIV_INLINE +ulint +dict_col_get_mbminlen( +/*==================*/ + /* out: minimum multi-byte char size */ + const dict_col_t* col); /* in: column */ +/************************************************************************* +Gets the maximum number of bytes per character. */ +UNIV_INLINE +ulint +dict_col_get_mbmaxlen( +/*==================*/ + /* out: maximum multi-byte char size */ + const dict_col_t* col); /* in: column */ +/************************************************************************* +Sets the minimum and maximum number of bytes per character. */ +UNIV_INLINE +void +dict_col_set_mbminmaxlen( +/*=====================*/ + dict_col_t* col, /* in/out: column */ + ulint mbminlen, /* in: minimum multi-byte char size */ + ulint mbmaxlen); /* in: minimum multi-byte char size */ +/************************************************************************* Gets the column data type. */ UNIV_INLINE void diff -rpu storage/innobase/include/dict0dict.ic storage/innobase/include/dict0dict.ic --- storage/innobase/include/dict0dict.ic 2008-09-11 11:36:31.000000000 +0300 +++ storage/innobase/include/dict0dict.ic 2008-10-28 10:04:41.000000000 +0200 @@ -13,6 +13,44 @@ Created 1/8/1996 Heikki Tuuri #include "data0type.h" /************************************************************************* +Gets the minimum number of bytes per character. */ +UNIV_INLINE +ulint +dict_col_get_mbminlen( +/*==================*/ + /* out: minimum multi-byte char size */ + const dict_col_t* col) /* in: column */ +{ + return(UNIV_EXPECT(col->mbminmaxlen % DATA_MBMAX, 1)); +} +/************************************************************************* +Gets the maximum number of bytes per character. */ +UNIV_INLINE +ulint +dict_col_get_mbmaxlen( +/*==================*/ + /* out: maximum multi-byte char size */ + const dict_col_t* col) /* in: column */ +{ + return(col->mbminmaxlen / DATA_MBMAX); +} +/************************************************************************* +Sets the minimum and maximum number of bytes per character. */ +UNIV_INLINE +void +dict_col_set_mbminmaxlen( +/*=====================*/ + dict_col_t* col, /* in/out: column */ + ulint mbminlen, /* in: minimum multi-byte char size */ + ulint mbmaxlen) /* in: minimum multi-byte char size */ +{ + ut_ad(mbminlen < DATA_MBMAX); + ut_ad(mbmaxlen < DATA_MBMAX); + ut_ad(mbminlen <= mbmaxlen); + + col->mbminmaxlen = mbmaxlen * DATA_MBMAX + mbminlen; +} +/************************************************************************* Gets the column data type. */ UNIV_INLINE void @@ -26,8 +64,7 @@ dict_col_copy_type( type->mtype = col->mtype; type->prtype = col->prtype; type->len = col->len; - type->mbminlen = col->mbminlen; - type->mbmaxlen = col->mbmaxlen; + type->mbminmaxlen = col->mbminmaxlen; } #ifdef UNIV_DEBUG @@ -47,8 +84,7 @@ dict_col_type_assert_equal( ut_ad(col->mtype == type->mtype); ut_ad(col->prtype == type->prtype); ut_ad(col->len == type->len); - ut_ad(col->mbminlen == type->mbminlen); - ut_ad(col->mbmaxlen == type->mbmaxlen); + ut_ad(col->mbminmaxlen == type->mbminmaxlen); return(TRUE); } @@ -64,7 +100,8 @@ dict_col_get_min_size( const dict_col_t* col) /* in: column */ { return(dtype_get_min_size_low(col->mtype, col->prtype, col->len, - col->mbminlen, col->mbmaxlen)); + dict_col_get_mbminlen(col), + dict_col_get_mbmaxlen(col))); } /*************************************************************************** Returns the maximum size of the column. */ @@ -87,7 +124,8 @@ dict_col_get_fixed_size( const dict_col_t* col) /* in: column */ { return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len, - col->mbminlen, col->mbmaxlen)); + dict_col_get_mbminlen(col), + dict_col_get_mbmaxlen(col))); } /*************************************************************************** Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column. diff -rpu storage/innobase/include/dict0mem.h storage/innobase/include/dict0mem.h --- storage/innobase/include/dict0mem.h 2008-09-11 11:36:31.000000000 +0300 +++ storage/innobase/include/dict0mem.h 2008-10-28 09:53:07.000000000 +0200 @@ -145,10 +145,8 @@ struct dict_col_struct{ the string, MySQL uses 1 or 2 bytes to store the string length) */ - unsigned mbminlen:2; /* minimum length of a - character, in bytes */ - unsigned mbmaxlen:3; /* maximum length of a - character, in bytes */ + unsigned mbminmaxlen:5; /* minimum and maximum length of a + character */ /*----------------------*/ /* End of definitions copied from dtype_t */ diff -rpu storage/innobase/row/row0ins.c storage/innobase/row/row0ins.c --- storage/innobase/row/row0ins.c 2008-09-11 11:36:32.000000000 +0300 +++ storage/innobase/row/row0ins.c 2008-10-28 10:11:32.000000000 +0200 @@ -499,8 +499,7 @@ row_ins_cascade_calc_update_vec( if (ufield->new_val.len != UNIV_SQL_NULL && dtype_get_at_most_n_mbchars( - col->prtype, - col->mbminlen, col->mbmaxlen, + col->prtype, col->mbminmaxlen, col->len, ufield->new_val.len, ufield->new_val.data) @@ -535,7 +534,7 @@ row_ins_cascade_calc_update_vec( parent_ufield->new_val.data, parent_ufield->new_val.len); - switch (UNIV_EXPECT(col->mbminlen,1)) { + switch (dict_col_get_mbminlen(col)) { default: ut_error; case 1: @@ -2226,7 +2225,7 @@ row_ins_index_entry_set_vals( = dict_field_get_col(ind_field); field->len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminlen, col->mbmaxlen, + col->prtype, col->mbminmaxlen, ind_field->prefix_len, row_field->len, row_field->data); } else { diff -rpu storage/innobase/row/row0row.c storage/innobase/row/row0row.c --- storage/innobase/row/row0row.c 2008-09-11 11:36:33.000000000 +0300 +++ storage/innobase/row/row0row.c 2008-10-28 10:12:18.000000000 +0200 @@ -146,7 +146,7 @@ row_build_index_entry( && dfield_get_len(dfield2) != UNIV_SQL_NULL) { storage_len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminlen, col->mbmaxlen, + col->prtype, col->mbminmaxlen, ind_field->prefix_len, dfield_get_len(dfield2), dfield2->data); @@ -426,8 +426,7 @@ row_build_row_ref( dfield_set_len(dfield, dtype_get_at_most_n_mbchars( dtype->prtype, - dtype->mbminlen, - dtype->mbmaxlen, + dtype->mbminmaxlen, clust_col_prefix_len, len, (char*) field)); } @@ -530,8 +529,7 @@ notfound: dfield_set_len(dfield, dtype_get_at_most_n_mbchars( dtype->prtype, - dtype->mbminlen, - dtype->mbmaxlen, + dtype->mbminmaxlen, clust_col_prefix_len, len, (char*) field)); } @@ -591,7 +589,7 @@ row_build_row_ref_from_row( && dfield->len != UNIV_SQL_NULL) { dfield->len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminlen, col->mbmaxlen, + col->prtype, col->mbminmaxlen, field->prefix_len, dfield->len, dfield->data); } } diff -rpu storage/innobase/row/row0sel.c storage/innobase/row/row0sel.c --- storage/innobase/row/row0sel.c 2008-09-11 11:36:33.000000000 +0300 +++ storage/innobase/row/row0sel.c 2008-10-28 10:12:30.000000000 +0200 @@ -107,7 +107,7 @@ row_sel_sec_rec_is_for_clust_rec( if (ifield->prefix_len > 0 && clust_len != UNIV_SQL_NULL) { clust_len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminlen, col->mbmaxlen, + col->prtype, col->mbminmaxlen, ifield->prefix_len, clust_len, (char*) clust_field); } diff -rpu storage/innobase/row/row0upd.c storage/innobase/row/row0upd.c --- storage/innobase/row/row0upd.c 2008-09-11 11:36:33.000000000 +0300 +++ storage/innobase/row/row0upd.c 2008-10-28 10:13:22.000000000 +0200 @@ -929,8 +929,7 @@ row_upd_index_replace_new_col_vals_index dfield->len = dtype_get_at_most_n_mbchars( col->prtype, - col->mbminlen, - col->mbmaxlen, + col->mbminmaxlen, field->prefix_len, new_val->len, new_val->data); @@ -1005,8 +1004,7 @@ row_upd_index_replace_new_col_vals( dfield->len = dtype_get_at_most_n_mbchars( col->prtype, - col->mbminlen, - col->mbmaxlen, + col->mbminmaxlen, field->prefix_len, new_val->len, new_val->data);