summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/innodb/r/no_pad.result7
-rw-r--r--mysql-test/suite/innodb/t/no_pad.test10
-rw-r--r--storage/innobase/rem/rem0cmp.cc160
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.