summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/mysqltest.cc12
-rw-r--r--mysql-test/r/create_or_replace.result12
-rw-r--r--mysql-test/r/ctype_partitions.result51
-rw-r--r--mysql-test/suite/multi_source/gtid.result2
-rw-r--r--mysql-test/suite/multi_source/gtid.test2
-rw-r--r--mysql-test/suite/multi_source/gtid_ignore_duplicates.result2
-rw-r--r--mysql-test/suite/multi_source/gtid_ignore_duplicates.test4
-rw-r--r--mysql-test/suite/multi_source/load_data.result2
-rw-r--r--mysql-test/suite/multi_source/load_data.test1
-rw-r--r--mysql-test/suite/rpl/r/create_or_replace2.result31
-rw-r--r--mysql-test/suite/rpl/t/create_or_replace2.test44
-rw-r--r--mysql-test/t/create_or_replace.test32
-rw-r--r--mysql-test/t/ctype_partitions.test29
-rw-r--r--mysql-test/valgrind.supp11
-rw-r--r--sql/slave.cc12
-rw-r--r--sql/sql_base.cc7
-rw-r--r--sql/sql_class.cc11
-rw-r--r--sql/sql_table.cc7
-rw-r--r--storage/heap/hp_write.c3
-rw-r--r--storage/maria/ma_check.c2
-rw-r--r--strings/ctype-bin.c8
-rw-r--r--strings/ctype-latin1.c10
-rw-r--r--strings/ctype-mb.c8
-rw-r--r--strings/ctype-simple.c46
-rw-r--r--strings/ctype-uca.c38
-rw-r--r--strings/ctype-ucs2.c56
-rw-r--r--strings/ctype-utf8.c28
-rw-r--r--strings/strings_def.h16
28 files changed, 396 insertions, 91 deletions
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 41f1d074dd9..80bb24765a7 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -7719,6 +7719,7 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
{
uint count;
MYSQL_RES *warn_res;
+ DYNAMIC_STRING res;
DBUG_ENTER("append_warnings");
if (!(count= mysql_warning_count(mysql)))
@@ -7738,11 +7739,18 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
die("Warning count is %u but didn't get any warnings",
count);
- append_result(ds, warn_res);
+ init_dynamic_string(&res, "", 1024, 1024);
+
+ append_result(&res, warn_res);
mysql_free_result(warn_res);
- DBUG_PRINT("warnings", ("%s", ds->str));
+ DBUG_PRINT("warnings", ("%s", res.str));
+ if (display_result_sorted)
+ dynstr_append_sorted(ds, &res, 0);
+ else
+ dynstr_append_mem(ds, res.str, res.length);
+ dynstr_free(&res);
DBUG_RETURN(count);
}
diff --git a/mysql-test/r/create_or_replace.result b/mysql-test/r/create_or_replace.result
index e6589807c2b..0403e1a0a35 100644
--- a/mysql-test/r/create_or_replace.result
+++ b/mysql-test/r/create_or_replace.result
@@ -427,4 +427,16 @@ THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME
# MDL_SHARED_READ MDL_EXPLICIT Table metadata lock test t2
drop table t1;
unlock tables;
+#
+# MDEV-6560
+# Assertion `! is_set() ' failed in Diagnostics_area::set_ok_status
+#
+CREATE TABLE t1 (col_int_nokey INT) ENGINE=InnoDB;
+CREATE OR REPLACE TEMPORARY TABLE tmp LIKE t1;
+LOCK TABLE t1 WRITE;
+CREATE OR REPLACE TABLE t1 LIKE tmp;;
+KILL QUERY 3;
+CREATE OR REPLACE TABLE t1 (a int);;
+KILL QUERY 3;
+drop table t1;
DROP TABLE t2;
diff --git a/mysql-test/r/ctype_partitions.result b/mysql-test/r/ctype_partitions.result
new file mode 100644
index 00000000000..a39ecc11529
--- /dev/null
+++ b/mysql-test/r/ctype_partitions.result
@@ -0,0 +1,51 @@
+#
+# MDEV-6255 DUPLICATE KEY Errors on SELECT .. GROUP BY that uses temporary and filesort
+#
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET cp1251 COLLATE cp1251_ukrainian_ci);
+INSERT INTO t1 VALUES (0x20),(0x60),(0x6060),(0x606060);
+SELECT HEX(a) FROM t1 WHERE a=0x60;
+HEX(a)
+20
+60
+6060
+606060
+ALTER TABLE t1 PARTITION BY KEY(a) PARTITIONS 3;
+SELECT HEX(a) FROM t1 WHERE a=0x60;
+HEX(a)
+20
+60
+6060
+606060
+DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET koi8u COLLATE koi8u_general_ci);
+INSERT INTO t1 VALUES (0x20),(0x60),(0x6060),(0x606060);
+SELECT HEX(a) FROM t1 WHERE a=0x60;
+HEX(a)
+20
+60
+6060
+606060
+ALTER TABLE t1 PARTITION BY KEY(a) PARTITIONS 3;
+SELECT HEX(a) FROM t1 WHERE a=0x60;
+HEX(a)
+20
+60
+6060
+606060
+DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET cp1250 COLLATE cp1250_general_ci);
+INSERT INTO t1 VALUES (0x20),(0xA0),(0xA0A0),(0xA0A0A0);
+SELECT HEX(a) FROM t1 WHERE a=0xA0;
+HEX(a)
+20
+A0
+A0A0
+A0A0A0
+ALTER TABLE t1 PARTITION BY KEY(a) PARTITIONS 3;
+SELECT HEX(a) FROM t1 WHERE a=0xA0;
+HEX(a)
+20
+A0
+A0A0
+A0A0A0
+DROP TABLE t1;
diff --git a/mysql-test/suite/multi_source/gtid.result b/mysql-test/suite/multi_source/gtid.result
index 8e6028afa17..ce926ddc995 100644
--- a/mysql-test/suite/multi_source/gtid.result
+++ b/mysql-test/suite/multi_source/gtid.result
@@ -141,8 +141,8 @@ include/reset_master_slave.inc
SET GLOBAL gtid_domain_id=0;
STOP ALL SLAVES;
Warnings:
-Note 1938 SLAVE 'slave2' stopped
Note 1938 SLAVE 'slave1' stopped
+Note 1938 SLAVE 'slave2' stopped
include/reset_master_slave.inc
SET GLOBAL gtid_domain_id=0;
include/reset_master_slave.inc
diff --git a/mysql-test/suite/multi_source/gtid.test b/mysql-test/suite/multi_source/gtid.test
index 0ab486b1f41..7a085823693 100644
--- a/mysql-test/suite/multi_source/gtid.test
+++ b/mysql-test/suite/multi_source/gtid.test
@@ -141,12 +141,14 @@ DROP TABLE t3;
SET GLOBAL gtid_domain_id=0;
--let $wait_condition= SELECT COUNT(*)=0 FROM information_schema.tables WHERE table_name IN ("t1", "t2", "t3") AND table_schema = "test"
--source include/wait_condition.inc
+--sorted_result
STOP ALL SLAVES;
--source reset_master_slave.inc
--disconnect slave1
--connection slave2
SET GLOBAL gtid_domain_id=0;
+--sorted_result
STOP ALL SLAVES;
--source reset_master_slave.inc
--disconnect slave2
diff --git a/mysql-test/suite/multi_source/gtid_ignore_duplicates.result b/mysql-test/suite/multi_source/gtid_ignore_duplicates.result
index 9bd09330ae7..5426091b635 100644
--- a/mysql-test/suite/multi_source/gtid_ignore_duplicates.result
+++ b/mysql-test/suite/multi_source/gtid_ignore_duplicates.result
@@ -245,8 +245,8 @@ a
SET GLOBAL gtid_domain_id=0;
STOP ALL SLAVES;
Warnings:
-Note 1938 SLAVE 'c2a' stopped
Note 1938 SLAVE 'b2a' stopped
+Note 1938 SLAVE 'c2a' stopped
SET GLOBAL slave_parallel_threads= @old_parallel;
SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates;
SET GLOBAL gtid_domain_id=0;
diff --git a/mysql-test/suite/multi_source/gtid_ignore_duplicates.test b/mysql-test/suite/multi_source/gtid_ignore_duplicates.test
index 3e98d7c76cb..cf1c750fc19 100644
--- a/mysql-test/suite/multi_source/gtid_ignore_duplicates.test
+++ b/mysql-test/suite/multi_source/gtid_ignore_duplicates.test
@@ -261,24 +261,28 @@ SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
# Clean up.
--connection server_1
SET GLOBAL gtid_domain_id=0;
+--sorted_result
STOP ALL SLAVES;
SET GLOBAL slave_parallel_threads= @old_parallel;
SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates;
--connection server_2
SET GLOBAL gtid_domain_id=0;
+--sorted_result
STOP ALL SLAVES;
SET GLOBAL slave_parallel_threads= @old_parallel;
SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates;
--connection server_3
SET GLOBAL gtid_domain_id=0;
+--sorted_result
STOP ALL SLAVES;
SET GLOBAL slave_parallel_threads= @old_parallel;
SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates;
--connection server_4
SET GLOBAL gtid_domain_id=0;
+--sorted_result
STOP ALL SLAVES;
SET GLOBAL slave_parallel_threads= @old_parallel;
SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates;
diff --git a/mysql-test/suite/multi_source/load_data.result b/mysql-test/suite/multi_source/load_data.result
index ef55abc5321..3a04156ce6a 100644
--- a/mysql-test/suite/multi_source/load_data.result
+++ b/mysql-test/suite/multi_source/load_data.result
@@ -23,8 +23,8 @@ drop table t1;
drop table t2;
stop all slaves;
Warnings:
-Note 1938 SLAVE 'master2' stopped
Note 1938 SLAVE '' stopped
+Note 1938 SLAVE 'master2' stopped
include/reset_master_slave.inc
include/reset_master_slave.inc
include/reset_master_slave.inc
diff --git a/mysql-test/suite/multi_source/load_data.test b/mysql-test/suite/multi_source/load_data.test
index e6e1399cbf3..ca2391a9c8d 100644
--- a/mysql-test/suite/multi_source/load_data.test
+++ b/mysql-test/suite/multi_source/load_data.test
@@ -58,6 +58,7 @@ drop table t2;
--sync_with_master 0,'master2'
--connection slave
+--sorted_result
stop all slaves;
--source reset_master_slave.inc
diff --git a/mysql-test/suite/rpl/r/create_or_replace2.result b/mysql-test/suite/rpl/r/create_or_replace2.result
new file mode 100644
index 00000000000..b96a0f8ae13
--- /dev/null
+++ b/mysql-test/suite/rpl/r/create_or_replace2.result
@@ -0,0 +1,31 @@
+include/master-slave.inc
+[connection master]
+#
+# MDEV-6525 ; Problems with CREATE OR REPLACE under lock
+#
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE FUNCTION f1() RETURNS INT RETURN ( SELECT MAX(a) FROM t1 );
+connect con1,localhost,root,,test;
+CREATE TEMPORARY TABLE tmp (b INT) ENGINE=InnoDB;
+LOCK TABLE t1 WRITE;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+CREATE OR REPLACE TABLE t1 LIKE tmp;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+connection default;
+set session lock_wait_timeout=1;
+SELECT f1();
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+set session lock_wait_timeout=@@global.lock_wait_timeout;
+SELECT f1();
+connection con1;
+unlock tables;
+connection default;
+ERROR 42S22: Unknown column 'a' in 'field list'
+disconnect con1;
+drop function f1;
+drop table t1;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/create_or_replace2.test b/mysql-test/suite/rpl/t/create_or_replace2.test
new file mode 100644
index 00000000000..79c92a7ec5b
--- /dev/null
+++ b/mysql-test/suite/rpl/t/create_or_replace2.test
@@ -0,0 +1,44 @@
+--source include/have_innodb.inc
+--source include/have_binlog_format_row_or_statement.inc
+--source include/have_metadata_lock_info.inc
+--source include/master-slave.inc
+--enable_connect_log
+
+--echo #
+--echo # MDEV-6525 ; Problems with CREATE OR REPLACE under lock
+--echo #
+
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE FUNCTION f1() RETURNS INT RETURN ( SELECT MAX(a) FROM t1 );
+
+--connect (con1,localhost,root,,test)
+
+CREATE TEMPORARY TABLE tmp (b INT) ENGINE=InnoDB;
+LOCK TABLE t1 WRITE;
+
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+
+CREATE OR REPLACE TABLE t1 LIKE tmp;
+SHOW CREATE TABLE t1;
+
+--connection default
+set session lock_wait_timeout=1;
+--error 1205
+SELECT f1();
+
+set session lock_wait_timeout=@@global.lock_wait_timeout;
+--send SELECT f1()
+--connection con1
+# This is here just in case, any timeout should be ok
+--sleep 1
+unlock tables;
+--connection default
+--error 1054
+--reap
+--disconnect con1
+
+# Cleanup
+drop function f1;
+drop table t1;
+--disable_connect_log
+--source include/rpl_end.inc
diff --git a/mysql-test/t/create_or_replace.test b/mysql-test/t/create_or_replace.test
index 384768a87d5..c7b980f9107 100644
--- a/mysql-test/t/create_or_replace.test
+++ b/mysql-test/t/create_or_replace.test
@@ -332,6 +332,38 @@ select * from information_schema.metadata_lock_info;
drop table t1;
unlock tables;
+--echo #
+--echo # MDEV-6560
+--echo # Assertion `! is_set() ' failed in Diagnostics_area::set_ok_status
+--echo #
+
+CREATE TABLE t1 (col_int_nokey INT) ENGINE=InnoDB;
+
+--let $con_id = `SELECT CONNECTION_ID()`
+CREATE OR REPLACE TEMPORARY TABLE tmp LIKE t1;
+LOCK TABLE t1 WRITE;
+
+--connect (con1,localhost,root,,test)
+
+--connection default
+--send CREATE OR REPLACE TABLE t1 LIKE tmp;
+--connection con1
+eval KILL QUERY $con_id;
+
+--connection default
+--error 0,ER_QUERY_INTERRUPTED
+--reap
+--send CREATE OR REPLACE TABLE t1 (a int);
+
+--connection con1
+eval KILL QUERY $con_id;
+
+--connection default
+--error 0,ER_QUERY_INTERRUPTED
+--reap
+--disconnect con1
+drop table t1;
+
#
# Cleanup
#
diff --git a/mysql-test/t/ctype_partitions.test b/mysql-test/t/ctype_partitions.test
new file mode 100644
index 00000000000..f80a2c98a1b
--- /dev/null
+++ b/mysql-test/t/ctype_partitions.test
@@ -0,0 +1,29 @@
+--source include/have_partition.inc
+
+--echo #
+--echo # MDEV-6255 DUPLICATE KEY Errors on SELECT .. GROUP BY that uses temporary and filesort
+--echo #
+
+# cp1251_ukrainian_ci: 0x20 SPACE is equal to 0x60 GRAVE ACCENT
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET cp1251 COLLATE cp1251_ukrainian_ci);
+INSERT INTO t1 VALUES (0x20),(0x60),(0x6060),(0x606060);
+SELECT HEX(a) FROM t1 WHERE a=0x60;
+ALTER TABLE t1 PARTITION BY KEY(a) PARTITIONS 3;
+SELECT HEX(a) FROM t1 WHERE a=0x60;
+DROP TABLE t1;
+
+# koi8u_general_ci: 0x20 SPACE is equal to 0x60 GRAVE ACCENT
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET koi8u COLLATE koi8u_general_ci);
+INSERT INTO t1 VALUES (0x20),(0x60),(0x6060),(0x606060);
+SELECT HEX(a) FROM t1 WHERE a=0x60;
+ALTER TABLE t1 PARTITION BY KEY(a) PARTITIONS 3;
+SELECT HEX(a) FROM t1 WHERE a=0x60;
+DROP TABLE t1;
+
+# cp1250_general_ci: 0x20 SPACE is equal to 0xA0 NO-BREAK SPACE
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET cp1250 COLLATE cp1250_general_ci);
+INSERT INTO t1 VALUES (0x20),(0xA0),(0xA0A0),(0xA0A0A0);
+SELECT HEX(a) FROM t1 WHERE a=0xA0;
+ALTER TABLE t1 PARTITION BY KEY(a) PARTITIONS 3;
+SELECT HEX(a) FROM t1 WHERE a=0xA0;
+DROP TABLE t1;
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
index f1bc19e27eb..ca190104d79 100644
--- a/mysql-test/valgrind.supp
+++ b/mysql-test/valgrind.supp
@@ -412,6 +412,17 @@
fun:__libc_start_main
}
+#
+# dl_init reports leaked memory in memalign on OpenSuse 12.3
+
+{
+ memory "loss" from _dl_init
+ Memcheck:Leak
+ fun:memalign
+ ...
+ fun:call_init
+ fun:_dl_init
+}
#
# dlclose can allocate memory for error message, the memory will be
diff --git a/sql/slave.cc b/sql/slave.cc
index b9f06c15fd4..edfc92a1666 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2230,6 +2230,7 @@ slave_killed_err:
static bool wait_for_relay_log_space(Relay_log_info* rli)
{
bool slave_killed=0;
+ bool ignore_log_space_limit;
Master_info* mi = rli->mi;
PSI_stage_info old_stage;
THD* thd = mi->io_thd;
@@ -2245,6 +2246,11 @@ static bool wait_for_relay_log_space(Relay_log_info* rli)
!rli->ignore_log_space_limit)
mysql_cond_wait(&rli->log_space_cond, &rli->log_space_lock);
+ ignore_log_space_limit= rli->ignore_log_space_limit;
+ rli->ignore_log_space_limit= 0;
+
+ thd->EXIT_COND(&old_stage);
+
/*
Makes the IO thread read only one event at a time
until the SQL thread is able to purge the relay
@@ -2268,7 +2274,8 @@ static bool wait_for_relay_log_space(Relay_log_info* rli)
thread sleeps waiting for events.
*/
- if (rli->ignore_log_space_limit)
+
+ if (ignore_log_space_limit)
{
#ifndef DBUG_OFF
{
@@ -2290,11 +2297,8 @@ static bool wait_for_relay_log_space(Relay_log_info* rli)
mysql_mutex_unlock(&mi->data_lock);
rli->sql_force_rotate_relay= false;
}
-
- rli->ignore_log_space_limit= false;
}
- thd->EXIT_COND(&old_stage);
DBUG_RETURN(slave_killed);
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 342a45247c5..5dd8a5b8abc 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2925,6 +2925,7 @@ Locked_tables_list::reopen_tables(THD *thd)
size_t reopen_count= 0;
MYSQL_LOCK *lock;
MYSQL_LOCK *merged_lock;
+ DBUG_ENTER("Locked_tables_list::reopen_tables");
for (TABLE_LIST *table_list= m_locked_tables;
table_list; table_list= table_list->next_global)
@@ -2936,7 +2937,7 @@ Locked_tables_list::reopen_tables(THD *thd)
if (open_table(thd, table_list, thd->mem_root, &ot_ctx))
{
unlink_all_closed_tables(thd, 0, reopen_count);
- return TRUE;
+ DBUG_RETURN(TRUE);
}
table_list->table->pos_in_locked_tables= table_list;
/* See also the comment on lock type in init_locked_tables(). */
@@ -2968,11 +2969,11 @@ Locked_tables_list::reopen_tables(THD *thd)
unlink_all_closed_tables(thd, lock, reopen_count);
if (! thd->killed)
my_error(ER_LOCK_DEADLOCK, MYF(0));
- return TRUE;
+ DBUG_RETURN(TRUE);
}
thd->lock= merged_lock;
}
- return FALSE;
+ DBUG_RETURN(FALSE);
}
/**
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index a4aeb24a326..b429772613e 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -4453,9 +4453,18 @@ extern "C" bool thd_binlog_filter_ok(const MYSQL_THD thd)
return binlog_filter->db_ok(thd->db);
}
+/*
+ This is similar to sqlcom_can_generate_row_events, with the expection
+ that we only return 1 if we are going to generate row events in a
+ transaction.
+ CREATE OR REPLACE is always safe to do as this will run in it's own
+ transaction.
+*/
+
extern "C" bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd)
{
- return sqlcom_can_generate_row_events(thd);
+ return (sqlcom_can_generate_row_events(thd) && thd->lex->sql_command !=
+ SQLCOM_CREATE_TABLE);
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index ca1290b2753..f4412512522 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5029,7 +5029,10 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
*/
thd->locked_tables_list.add_back_last_deleted_lock(pos_in_locked_tables);
if (thd->locked_tables_list.reopen_tables(thd))
+ {
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
+ result= 1;
+ }
else
{
TABLE *table= pos_in_locked_tables->table;
@@ -5292,6 +5295,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
if (res)
{
+ /* is_error() may be 0 if table existed and we generated a warning */
res= thd->is_error();
goto err;
}
@@ -5374,7 +5378,10 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
*/
thd->locked_tables_list.add_back_last_deleted_lock(pos_in_locked_tables);
if (thd->locked_tables_list.reopen_tables(thd))
+ {
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
+ res= 1; // We got an error
+ }
else
{
/*
diff --git a/storage/heap/hp_write.c b/storage/heap/hp_write.c
index 6b96e1c31a3..c6205508a90 100644
--- a/storage/heap/hp_write.c
+++ b/storage/heap/hp_write.c
@@ -385,7 +385,8 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
pos=empty;
do
{
- if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 1))
+ if (pos->hash_of_key == hash_of_key &&
+ ! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 1))
{
DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
}
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index 4ac267ffb8a..0a89babb205 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -5515,6 +5515,8 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const uchar *a)
}
if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
{
+ DBUG_EXECUTE("key", _ma_print_keydata(DBUG_FILE, sort_param->seg, a,
+ USE_WHOLE_KEY););
sort_info->dupp++;
sort_info->info->cur_row.lastpos= get_record_for_key(sort_param->keyinfo,
a);
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 4beb7047d00..3ca4ba2b430 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -288,9 +288,7 @@ void my_hash_sort_8bit_bin(CHARSET_INFO *cs __attribute__((unused)),
for (; key < end ; key++)
{
- tmp1^= (ulong) ((((uint) tmp1 & 63) + tmp2) *
- ((uint) *key)) + (tmp1 << 8);
- tmp2+= 3;
+ MY_HASH_ADD(tmp1, tmp2, (uint) *key);
}
*nr1= tmp1;
@@ -307,9 +305,7 @@ void my_hash_sort_bin(CHARSET_INFO *cs __attribute__((unused)),
for (; key < end ; key++)
{
- tmp1^= (ulong) ((((uint) tmp1 & 63) + tmp2) *
- ((uint) *key)) + (tmp1 << 8);
- tmp2+= 3;
+ MY_HASH_ADD(tmp1, tmp2, (uint) *key);
}
*nr1= tmp1;
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index 2c84f86fad0..babf74599ea 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -691,6 +691,8 @@ void my_hash_sort_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
ulong *nr1, ulong *nr2)
{
const uchar *end;
+ register ulong m1= *nr1, m2= *nr2;
+
/*
Remove end space. We have to do this to be able to compare
'AE' and 'Ä' as identical
@@ -700,14 +702,14 @@ void my_hash_sort_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
for (; key < end ; key++)
{
uint X= (uint) combo1map[(uint) *key];
- nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * X) + (nr1[0] << 8);
- nr2[0]+=3;
+ MY_HASH_ADD(m1, m2, X);
if ((X= combo2map[*key]))
{
- nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * X) + (nr1[0] << 8);
- nr2[0]+=3;
+ MY_HASH_ADD(m1, m2, X);
}
}
+ *nr1= m1;
+ *nr2= m2;
}
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index f4e70fd1dd5..1ef772e1d5e 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -680,6 +680,8 @@ void
my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
const uchar *key, size_t len,ulong *nr1, ulong *nr2)
{
+ register ulong m1= *nr1, m2= *nr2;
+
/*
Remove trailing spaces. We have to do this to be able to compare
'A ' and 'A' as identical
@@ -688,10 +690,10 @@ my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
for (; key < end ; key++)
{
- nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
- ((uint)*key)) + (nr1[0] << 8);
- nr2[0]+=3;
+ MY_HASH_ADD(m1, m2, (uint)*key);
}
+ *nr1= m1;
+ *nr2= m2;
}
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index f5484965314..0785ba35700 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -306,24 +306,48 @@ void my_hash_sort_simple(CHARSET_INFO *cs,
{
register const uchar *sort_order=cs->sort_order;
const uchar *end;
- ulong n1, n2;
+ register ulong m1= *nr1, m2= *nr2;
+ uint16 space_weight= sort_order[' '];
/*
- Remove end space. We have to do this to be able to compare
- 'A ' and 'A' as identical
+ Remove all trailing characters that are equal to space.
+ We have to do this to be able to compare 'A ' and 'A' as identical.
+
+ If the key is long enough, cut the trailing spaces (0x20) using an
+ optimized function implemented in skip_trailing_spaces().
+
+ "len > 16" is just some heuristic here.
+ Calling skip_triling_space() for short values is not desirable,
+ because its initialization block may be more expensive than the
+ performance gained.
+ */
+
+ end= len > 16 ? skip_trailing_space(key, len) : key + len;
+
+ /*
+ We removed all trailing characters that are binary equal to space 0x20.
+ Now remove all trailing characters that have weights equal to space.
+ Some 8bit simple collations may have such characters:
+ - cp1250_general_ci 0xA0 NO-BREAK SPACE == 0x20 SPACE
+ - cp1251_ukrainian_ci 0x60 GRAVE ACCENT == 0x20 SPACE
+ - koi8u_general_ci 0x60 GRAVE ACCENT == 0x20 SPACE
*/
- end= skip_trailing_space(key, len);
- n1= *nr1;
- n2= *nr2;
+ for ( ; key < end ; )
+ {
+ if (sort_order[*--end] != space_weight)
+ {
+ end++;
+ break;
+ }
+ }
+
for (; key < (uchar*) end ; key++)
{
- n1^=(ulong) ((((uint) n1 & 63)+n2) *
- ((uint) sort_order[(uint) *key])) + (n1 << 8);
- n2+=3;
+ MY_HASH_ADD(m1, m2, (uint) sort_order[(uint) *key]);
}
- *nr1= n1;
- *nr2= n2;
+ *nr1= m1;
+ *nr2= m2;
}
diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c
index 5165a43e852..19ce17c3856 100644
--- a/strings/ctype-uca.c
+++ b/strings/ctype-uca.c
@@ -20873,21 +20873,45 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs,
static void my_hash_sort_uca(CHARSET_INFO *cs,
my_uca_scanner_handler *scanner_handler,
const uchar *s, size_t slen,
- ulong *n1, ulong *n2)
+ ulong *nr1, ulong *nr2)
{
int s_res;
my_uca_scanner scanner;
-
- slen= cs->cset->lengthsp(cs, (char*) s, slen);
+ int space_weight= my_space_weight(cs);
+ register ulong m1= *nr1, m2= *nr2;
+
scanner_handler->init(&scanner, cs, &cs->uca->level[0], s, slen);
while ((s_res= scanner_handler->next(&scanner)) >0)
{
- n1[0]^= (((n1[0] & 63)+n2[0])*(s_res >> 8))+ (n1[0] << 8);
- n2[0]+=3;
- n1[0]^= (((n1[0] & 63)+n2[0])*(s_res & 0xFF))+ (n1[0] << 8);
- n2[0]+=3;
+ if (s_res == space_weight)
+ {
+ /* Combine all spaces to be able to skip end spaces */
+ uint count= 0;
+ do
+ {
+ count++;
+ if ((s_res= scanner_handler->next(&scanner)) <= 0)
+ {
+ /* Skip strings at end of string */
+ goto end;
+ }
+ }
+ while (s_res == space_weight);
+
+ /* Add back that has for the space characters */
+ do
+ {
+ MY_HASH_ADD_16(m1, m2, space_weight);
+ }
+ while (--count != 0);
+
+ }
+ MY_HASH_ADD_16(m1, m2, s_res);
}
+end:
+ *nr1= m1;
+ *nr2= m2;
}
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index d2f7d34f0aa..593f9a12950 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -1222,23 +1222,23 @@ my_caseup_utf16(CHARSET_INFO *cs, char *src, size_t srclen,
static void
my_hash_sort_utf16(CHARSET_INFO *cs, const uchar *s, size_t slen,
- ulong *n1, ulong *n2)
+ ulong *nr1, ulong *nr2)
{
my_wc_t wc;
my_charset_conv_mb_wc mb_wc= cs->cset->mb_wc;
int res;
const uchar *e= s + cs->cset->lengthsp(cs, (const char *) s, slen);
MY_UNICASE_INFO *uni_plane= cs->caseinfo;
+ register ulong m1= *nr1, m2= *nr2;
while ((s < e) && (res= mb_wc(cs, &wc, (uchar *) s, (uchar *) e)) > 0)
{
my_tosort_utf16(uni_plane, &wc);
- n1[0]^= (((n1[0] & 63) + n2[0]) * (wc & 0xFF)) + (n1[0] << 8);
- n2[0]+= 3;
- n1[0]^= (((n1[0] & 63) + n2[0]) * (wc >> 8)) + (n1[0] << 8);
- n2[0]+= 3;
+ MY_HASH_ADD_16(m1, m2, wc);
s+= res;
}
+ *nr1= m1;
+ *nr2= m2;
}
@@ -1611,12 +1611,14 @@ my_hash_sort_utf16_bin(CHARSET_INFO *cs,
const uchar *pos, size_t len, ulong *nr1, ulong *nr2)
{
const uchar *end= pos + cs->cset->lengthsp(cs, (const char *) pos, len);
+ register ulong m1= *nr1, m2= *nr2;
+
for ( ; pos < end ; pos++)
{
- nr1[0]^= (ulong) ((((uint) nr1[0] & 63) + nr2[0]) *
- ((uint)*pos)) + (nr1[0] << 8);
- nr2[0]+= 3;
+ MY_HASH_ADD(m1, m2, (uint)*pos);
}
+ *nr1= m1;
+ *nr2= m2;
}
@@ -2007,22 +2009,15 @@ my_caseup_utf32(CHARSET_INFO *cs, char *src, size_t srclen,
}
-static inline void
-my_hash_add(ulong *n1, ulong *n2, uint ch)
-{
- n1[0]^= (((n1[0] & 63) + n2[0]) * (ch)) + (n1[0] << 8);
- n2[0]+= 3;
-}
-
-
static void
my_hash_sort_utf32(CHARSET_INFO *cs, const uchar *s, size_t slen,
- ulong *n1, ulong *n2)
+ ulong *nr1, ulong *nr2)
{
my_wc_t wc;
int res;
const uchar *e= s + slen;
MY_UNICASE_INFO *uni_plane= cs->caseinfo;
+ register ulong m1= *nr1, m2= *nr2;
/* Skip trailing spaces */
while (e > s + 3 && e[-1] == ' ' && !e[-2] && !e[-3] && !e[-4])
@@ -2031,12 +2026,14 @@ my_hash_sort_utf32(CHARSET_INFO *cs, const uchar *s, size_t slen,
while ((res= my_utf32_uni(cs, &wc, (uchar*) s, (uchar*) e)) > 0)
{
my_tosort_utf32(uni_plane, &wc);
- my_hash_add(n1, n2, (uint) (wc >> 24));
- my_hash_add(n1, n2, (uint) (wc >> 16) & 0xFF);
- my_hash_add(n1, n2, (uint) (wc >> 8) & 0xFF);
- my_hash_add(n1, n2, (uint) (wc & 0xFF));
+ MY_HASH_ADD(m1, m2, (uint) (wc >> 24));
+ MY_HASH_ADD(m1, m2, (uint) (wc >> 16) & 0xFF);
+ MY_HASH_ADD(m1, m2, (uint) (wc >> 8) & 0xFF);
+ MY_HASH_ADD(m1, m2, (uint) (wc & 0xFF));
s+= res;
}
+ *nr1= m1;
+ *nr2= m2;
}
@@ -2976,12 +2973,13 @@ static size_t my_caseup_ucs2(CHARSET_INFO *cs, char *src, size_t srclen,
static void my_hash_sort_ucs2(CHARSET_INFO *cs, const uchar *s, size_t slen,
- ulong *n1, ulong *n2)
+ ulong *nr1, ulong *nr2)
{
my_wc_t wc;
int res;
const uchar *e=s+slen;
MY_UNICASE_INFO *uni_plane= cs->caseinfo;
+ register ulong m1= *nr1, m2= *nr2;
while (e > s+1 && e[-1] == ' ' && e[-2] == '\0')
e-= 2;
@@ -2989,12 +2987,11 @@ static void my_hash_sort_ucs2(CHARSET_INFO *cs, const uchar *s, size_t slen,
while ((s < e) && (res=my_ucs2_uni(cs,&wc, (uchar *)s, (uchar*)e)) >0)
{
my_tosort_ucs2(uni_plane, &wc);
- n1[0]^= (((n1[0] & 63)+n2[0])*(wc & 0xFF))+ (n1[0] << 8);
- n2[0]+=3;
- n1[0]^= (((n1[0] & 63)+n2[0])*(wc >> 8))+ (n1[0] << 8);
- n2[0]+=3;
+ MY_HASH_ADD_16(m1, m2, wc);
s+=res;
}
+ *nr1= m1;
+ *nr2= m2;
}
@@ -3312,16 +3309,17 @@ void my_hash_sort_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)),
const uchar *key, size_t len,ulong *nr1, ulong *nr2)
{
const uchar *end = key + len;
+ register ulong m1= *nr1, m2= *nr2;
while (end > key+1 && end[-1] == ' ' && end[-2] == '\0')
end-= 2;
for (; key < (uchar*) end ; key++)
{
- nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
- ((uint)*key)) + (nr1[0] << 8);
- nr2[0]+=3;
+ MY_HASH_ADD(m1, m2, (uint)*key);
}
+ *nr1= m1;
+ *nr2= m2;
}
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index 96d5ea26a3c..d0a64d11c84 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -5087,12 +5087,13 @@ static size_t my_caseup_utf8(CHARSET_INFO *cs, char *src, size_t srclen,
static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, size_t slen,
- ulong *n1, ulong *n2)
+ ulong *nr1, ulong *nr2)
{
my_wc_t wc;
int res;
const uchar *e=s+slen;
MY_UNICASE_INFO *uni_plane= cs->caseinfo;
+ register ulong m1= *nr1, m2= *nr2;
/*
Remove end space. We have to do this to be able to compare
@@ -5104,12 +5105,11 @@ static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, size_t slen,
while ((s < e) && (res=my_utf8_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 )
{
my_tosort_unicode(uni_plane, &wc, cs->state);
- n1[0]^= (((n1[0] & 63)+n2[0])*(wc & 0xFF))+ (n1[0] << 8);
- n2[0]+=3;
- n1[0]^= (((n1[0] & 63)+n2[0])*(wc >> 8))+ (n1[0] << 8);
- n2[0]+=3;
+ MY_HASH_ADD_16(m1, m2, wc);
s+=res;
}
+ *nr1= m1;
+ *nr2= m2;
}
@@ -7597,22 +7597,15 @@ my_caseup_utf8mb4(CHARSET_INFO *cs, char *src, size_t srclen,
}
-static inline void
-my_hash_add(ulong *n1, ulong *n2, uint ch)
-{
- n1[0]^= (((n1[0] & 63) + n2[0]) * (ch)) + (n1[0] << 8);
- n2[0]+= 3;
-}
-
-
static void
my_hash_sort_utf8mb4(CHARSET_INFO *cs, const uchar *s, size_t slen,
- ulong *n1, ulong *n2)
+ ulong *nr1, ulong *nr2)
{
my_wc_t wc;
int res;
const uchar *e= s + slen;
MY_UNICASE_INFO *uni_plane= cs->caseinfo;
+ register ulong m1= *nr1, m2= *nr2;
/*
Remove end space. We do this to be able to compare
@@ -7624,8 +7617,7 @@ my_hash_sort_utf8mb4(CHARSET_INFO *cs, const uchar *s, size_t slen,
while ((res= my_mb_wc_utf8mb4(cs, &wc, (uchar*) s, (uchar*) e)) > 0)
{
my_tosort_unicode(uni_plane, &wc, cs->state);
- my_hash_add(n1, n2, (uint) (wc & 0xFF));
- my_hash_add(n1, n2, (uint) (wc >> 8) & 0xFF);
+ MY_HASH_ADD_16(m1, m2, (uint) (wc & 0xFFFF));
if (wc > 0xFFFF)
{
/*
@@ -7635,10 +7627,12 @@ my_hash_sort_utf8mb4(CHARSET_INFO *cs, const uchar *s, size_t slen,
This is useful to keep order of records in
test results, e.g. for "SHOW GRANTS".
*/
- my_hash_add(n1, n2, (uint) (wc >> 16) & 0xFF);
+ MY_HASH_ADD(m1, m2, (uint) ((wc >> 16) & 0xFF));
}
s+= res;
}
+ *nr1= m1;
+ *nr2= m2;
}
diff --git a/strings/strings_def.h b/strings/strings_def.h
index 6bd8e8f5575..d601f5ca697 100644
--- a/strings/strings_def.h
+++ b/strings/strings_def.h
@@ -100,4 +100,20 @@ static inline const uchar *skip_trailing_space(const uchar *ptr,size_t len)
end--;
return (end);
}
+
+/* Macros for hashing characters */
+
+#define MY_HASH_ADD(A, B, value) \
+ do { A^= (((A & 63)+B)*((value)))+ (A << 8); B+=3; } while(0)
+
+#define MY_HASH_ADD_16(A, B, value) \
+ do { MY_HASH_ADD(A, B, ((value) & 0xFF)) ; MY_HASH_ADD(A, B, ((value >>8 ))); } while(0)
+
+/*
+ This one is needed to ensure we get the exact same hash as MariaDB 5.1
+ This is needed to ensure that old partitioned tables still work as before.
+*/
+#define MY_HASH_ADD_16_INV(A, B, value) \
+ do { MY_HASH_ADD(A, B, ((value >> 8))) ; MY_HASH_ADD(A, B, ((value & 0xFF ))); } while(0)
+
#endif