diff options
-rw-r--r-- | mysql-test/suite/innodb/r/no_pad.result | 7 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/no_pad.test | 10 | ||||
-rw-r--r-- | storage/innobase/rem/rem0cmp.cc | 160 |
3 files changed, 75 insertions, 102 deletions
diff --git a/mysql-test/suite/innodb/r/no_pad.result b/mysql-test/suite/innodb/r/no_pad.result new file mode 100644 index 00000000000..0c039c30a5e --- /dev/null +++ b/mysql-test/suite/innodb/r/no_pad.result @@ -0,0 +1,7 @@ +CREATE TABLE t1 (a CHAR(8), id INT, PRIMARY KEY (a,id)) COLLATE utf8_nopad_bin +ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO t1 VALUES ('',1); +ALTER TABLE t1 ROW_FORMAT=DYNAMIC; +INSERT INTO t1 VALUES ('',2); +ALTER TABLE t1 ROW_FORMAT=REDUNDANT; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/no_pad.test b/mysql-test/suite/innodb/t/no_pad.test new file mode 100644 index 00000000000..1be1972c9ca --- /dev/null +++ b/mysql-test/suite/innodb/t/no_pad.test @@ -0,0 +1,10 @@ +--source include/have_innodb.inc + +CREATE TABLE t1 (a CHAR(8), id INT, PRIMARY KEY (a,id)) COLLATE utf8_nopad_bin +ENGINE=InnoDB ROW_FORMAT=REDUNDANT; + +INSERT INTO t1 VALUES ('',1); +ALTER TABLE t1 ROW_FORMAT=DYNAMIC; +INSERT INTO t1 VALUES ('',2); +ALTER TABLE t1 ROW_FORMAT=REDUNDANT; +DROP TABLE t1; diff --git a/storage/innobase/rem/rem0cmp.cc b/storage/innobase/rem/rem0cmp.cc index df74175c483..3259a1572be 100644 --- a/storage/innobase/rem/rem0cmp.cc +++ b/storage/innobase/rem/rem0cmp.cc @@ -49,49 +49,25 @@ At the present, the comparison functions return 0 in the case, where two records disagree only in the way that one has more fields than the other. */ -/** Compare two data fields. -@param[in] prtype precise type -@param[in] a data field -@param[in] a_length length of a, in bytes (not UNIV_SQL_NULL) -@param[in] b data field -@param[in] b_length length of b, in bytes (not UNIV_SQL_NULL) -@return positive, 0, negative, if a is greater, equal, less than b, -respectively */ -UNIV_INLINE -int -innobase_mysql_cmp( - ulint prtype, - const byte* a, - unsigned int a_length, - const byte* b, - unsigned int b_length) +#ifndef DBUG_OFF +/** @return whether a data type is compatible with strnncoll() functions */ +static bool is_strnncoll_compatible(ulint type) { -#ifdef UNIV_DEBUG - switch (prtype & DATA_MYSQL_TYPE_MASK) { - case MYSQL_TYPE_BIT: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_VARCHAR: - break; - default: - ut_error; - } -#endif /* UNIV_DEBUG */ - - uint cs_num = (uint) dtype_get_charset_coll(prtype); - - if (CHARSET_INFO* cs = get_charset(cs_num, MYF(MY_WME))) { - return(cs->coll->strnncollsp( - cs, a, a_length, b, b_length)); - } - - ib::fatal() << "Unable to find charset-collation " << cs_num; - return(0); + switch (type) { + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_VARCHAR: + return true; + default: + return false; + } } +#endif /* DBUG_OFF */ /*************************************************************//** Returns TRUE if two columns are equal for comparison purposes. @@ -309,68 +285,48 @@ cmp_gis_field( @param[in] b_length length of b, in bytes (not UNIV_SQL_NULL) @return positive, 0, negative, if a is greater, equal, less than b, respectively */ -static -int -cmp_whole_field( - ulint mtype, - ulint prtype, - const byte* a, - unsigned int a_length, - const byte* b, - unsigned int b_length) +static int cmp_whole_field(ulint mtype, ulint prtype, + const byte *a, unsigned a_length, + const byte *b, unsigned b_length) { - float f_1; - float f_2; - double d_1; - double d_2; - - switch (mtype) { - case DATA_DECIMAL: - return(cmp_decimal(a, a_length, b, b_length)); - case DATA_DOUBLE: - d_1 = mach_double_read(a); - d_2 = mach_double_read(b); - - if (d_1 > d_2) { - return(1); - } else if (d_2 > d_1) { - return(-1); - } - - return(0); - - case DATA_FLOAT: - f_1 = mach_float_read(a); - f_2 = mach_float_read(b); - - if (f_1 > f_2) { - return(1); - } else if (f_2 > f_1) { - return(-1); - } - - return(0); - case DATA_VARCHAR: - case DATA_CHAR: - return(my_charset_latin1.coll->strnncollsp( - &my_charset_latin1, - a, a_length, b, b_length)); - case DATA_BLOB: - if (prtype & DATA_BINARY_TYPE) { - ib::error() << "Comparing a binary BLOB" - " using a character set collation!"; - ut_ad(0); - } - /* fall through */ - case DATA_VARMYSQL: - case DATA_MYSQL: - return(innobase_mysql_cmp(prtype, - a, a_length, b, b_length)); - default: - ib::fatal() << "Unknown data type number " << mtype; - } - - return(0); + switch (mtype) { + default: + ib::fatal() << "Unknown data type number " << mtype; + return 0; + case DATA_DECIMAL: + return cmp_decimal(a, a_length, b, b_length); + case DATA_DOUBLE: + { + const double af= mach_double_read(a), bf= mach_double_read(b); + return af > bf ? 1 : bf > af ? -1 : 0; + } + case DATA_FLOAT: + { + const float af= mach_float_read(a), bf= mach_float_read(b); + return af > bf ? 1 : bf > af ? -1 : 0; + } + case DATA_VARCHAR: + case DATA_CHAR: + return my_charset_latin1.coll->strnncollsp(&my_charset_latin1, + a, a_length, b, b_length); + case DATA_BLOB: + ut_ad(!(prtype & DATA_BINARY_TYPE)); /* our only caller tested this */ + /* fall through */ + case DATA_VARMYSQL: + DBUG_ASSERT(is_strnncoll_compatible(prtype & DATA_MYSQL_TYPE_MASK)); + if (CHARSET_INFO *cs= get_charset(dtype_get_charset_coll(prtype), + MYF(MY_WME))) + return cs->coll->strnncollsp(cs, a, a_length, b, b_length); + break; + case DATA_MYSQL: + DBUG_ASSERT(is_strnncoll_compatible(prtype & DATA_MYSQL_TYPE_MASK)); + if (CHARSET_INFO *cs= get_charset(dtype_get_charset_coll(prtype), + MYF(MY_WME))) + return cs->coll->strnncollsp_nchars(cs, a, a_length, b, b_length, + std::max(a_length, b_length)); + } + + ib::fatal() << "Unable to find charset-collation for " << prtype; } /** Compare two data fields. |