Automatic merge

This commit is contained in:
Michael Widenius 2014-09-11 23:50:31 +03:00
commit c6051a4beb
28 changed files with 397 additions and 92 deletions

View File

@ -7719,6 +7719,7 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
{ {
uint count; uint count;
MYSQL_RES *warn_res; MYSQL_RES *warn_res;
DYNAMIC_STRING res;
DBUG_ENTER("append_warnings"); DBUG_ENTER("append_warnings");
if (!(count= mysql_warning_count(mysql))) 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", die("Warning count is %u but didn't get any warnings",
count); count);
append_result(ds, warn_res); init_dynamic_string(&res, "", 1024, 1024);
append_result(&res, warn_res);
mysql_free_result(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); DBUG_RETURN(count);
} }

View File

@ -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 # MDL_SHARED_READ MDL_EXPLICIT Table metadata lock test t2
drop table t1; drop table t1;
unlock tables; 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; DROP TABLE t2;

View File

@ -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;

View File

@ -141,8 +141,8 @@ include/reset_master_slave.inc
SET GLOBAL gtid_domain_id=0; SET GLOBAL gtid_domain_id=0;
STOP ALL SLAVES; STOP ALL SLAVES;
Warnings: Warnings:
Note 1938 SLAVE 'slave2' stopped
Note 1938 SLAVE 'slave1' stopped Note 1938 SLAVE 'slave1' stopped
Note 1938 SLAVE 'slave2' stopped
include/reset_master_slave.inc include/reset_master_slave.inc
SET GLOBAL gtid_domain_id=0; SET GLOBAL gtid_domain_id=0;
include/reset_master_slave.inc include/reset_master_slave.inc

View File

@ -141,12 +141,14 @@ DROP TABLE t3;
SET GLOBAL gtid_domain_id=0; 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" --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 --source include/wait_condition.inc
--sorted_result
STOP ALL SLAVES; STOP ALL SLAVES;
--source reset_master_slave.inc --source reset_master_slave.inc
--disconnect slave1 --disconnect slave1
--connection slave2 --connection slave2
SET GLOBAL gtid_domain_id=0; SET GLOBAL gtid_domain_id=0;
--sorted_result
STOP ALL SLAVES; STOP ALL SLAVES;
--source reset_master_slave.inc --source reset_master_slave.inc
--disconnect slave2 --disconnect slave2

View File

@ -245,8 +245,8 @@ a
SET GLOBAL gtid_domain_id=0; SET GLOBAL gtid_domain_id=0;
STOP ALL SLAVES; STOP ALL SLAVES;
Warnings: Warnings:
Note 1938 SLAVE 'c2a' stopped
Note 1938 SLAVE 'b2a' stopped Note 1938 SLAVE 'b2a' stopped
Note 1938 SLAVE 'c2a' stopped
SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL slave_parallel_threads= @old_parallel;
SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates;
SET GLOBAL gtid_domain_id=0; SET GLOBAL gtid_domain_id=0;

View File

@ -261,24 +261,28 @@ SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
# Clean up. # Clean up.
--connection server_1 --connection server_1
SET GLOBAL gtid_domain_id=0; SET GLOBAL gtid_domain_id=0;
--sorted_result
STOP ALL SLAVES; STOP ALL SLAVES;
SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL slave_parallel_threads= @old_parallel;
SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates;
--connection server_2 --connection server_2
SET GLOBAL gtid_domain_id=0; SET GLOBAL gtid_domain_id=0;
--sorted_result
STOP ALL SLAVES; STOP ALL SLAVES;
SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL slave_parallel_threads= @old_parallel;
SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates;
--connection server_3 --connection server_3
SET GLOBAL gtid_domain_id=0; SET GLOBAL gtid_domain_id=0;
--sorted_result
STOP ALL SLAVES; STOP ALL SLAVES;
SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL slave_parallel_threads= @old_parallel;
SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates;
--connection server_4 --connection server_4
SET GLOBAL gtid_domain_id=0; SET GLOBAL gtid_domain_id=0;
--sorted_result
STOP ALL SLAVES; STOP ALL SLAVES;
SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL slave_parallel_threads= @old_parallel;
SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates;

View File

@ -23,8 +23,8 @@ drop table t1;
drop table t2; drop table t2;
stop all slaves; stop all slaves;
Warnings: Warnings:
Note 1938 SLAVE 'master2' stopped
Note 1938 SLAVE '' 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 include/reset_master_slave.inc
include/reset_master_slave.inc include/reset_master_slave.inc

View File

@ -58,6 +58,7 @@ drop table t2;
--sync_with_master 0,'master2' --sync_with_master 0,'master2'
--connection slave --connection slave
--sorted_result
stop all slaves; stop all slaves;
--source reset_master_slave.inc --source reset_master_slave.inc

View File

@ -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

View File

@ -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

View File

@ -332,6 +332,38 @@ select * from information_schema.metadata_lock_info;
drop table t1; drop table t1;
unlock tables; 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 # Cleanup
# #

View File

@ -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;

View File

@ -412,6 +412,17 @@
fun:__libc_start_main 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 # dlclose can allocate memory for error message, the memory will be

View File

@ -2230,6 +2230,7 @@ slave_killed_err:
static bool wait_for_relay_log_space(Relay_log_info* rli) static bool wait_for_relay_log_space(Relay_log_info* rli)
{ {
bool slave_killed=0; bool slave_killed=0;
bool ignore_log_space_limit;
Master_info* mi = rli->mi; Master_info* mi = rli->mi;
PSI_stage_info old_stage; PSI_stage_info old_stage;
THD* thd = mi->io_thd; 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) !rli->ignore_log_space_limit)
mysql_cond_wait(&rli->log_space_cond, &rli->log_space_lock); 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 Makes the IO thread read only one event at a time
until the SQL thread is able to purge the relay 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. thread sleeps waiting for events.
*/ */
if (rli->ignore_log_space_limit)
if (ignore_log_space_limit)
{ {
#ifndef DBUG_OFF #ifndef DBUG_OFF
{ {
@ -2290,11 +2297,8 @@ static bool wait_for_relay_log_space(Relay_log_info* rli)
mysql_mutex_unlock(&mi->data_lock); mysql_mutex_unlock(&mi->data_lock);
rli->sql_force_rotate_relay= false; rli->sql_force_rotate_relay= false;
} }
rli->ignore_log_space_limit= false;
} }
thd->EXIT_COND(&old_stage);
DBUG_RETURN(slave_killed); DBUG_RETURN(slave_killed);
} }

View File

@ -2925,6 +2925,7 @@ Locked_tables_list::reopen_tables(THD *thd)
size_t reopen_count= 0; size_t reopen_count= 0;
MYSQL_LOCK *lock; MYSQL_LOCK *lock;
MYSQL_LOCK *merged_lock; MYSQL_LOCK *merged_lock;
DBUG_ENTER("Locked_tables_list::reopen_tables");
for (TABLE_LIST *table_list= m_locked_tables; for (TABLE_LIST *table_list= m_locked_tables;
table_list; table_list= table_list->next_global) 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)) if (open_table(thd, table_list, thd->mem_root, &ot_ctx))
{ {
unlink_all_closed_tables(thd, 0, reopen_count); unlink_all_closed_tables(thd, 0, reopen_count);
return TRUE; DBUG_RETURN(TRUE);
} }
table_list->table->pos_in_locked_tables= table_list; table_list->table->pos_in_locked_tables= table_list;
/* See also the comment on lock type in init_locked_tables(). */ /* 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); unlink_all_closed_tables(thd, lock, reopen_count);
if (! thd->killed) if (! thd->killed)
my_error(ER_LOCK_DEADLOCK, MYF(0)); my_error(ER_LOCK_DEADLOCK, MYF(0));
return TRUE; DBUG_RETURN(TRUE);
} }
thd->lock= merged_lock; thd->lock= merged_lock;
} }
return FALSE; DBUG_RETURN(FALSE);
} }
/** /**

View File

@ -4453,9 +4453,18 @@ extern "C" bool thd_binlog_filter_ok(const MYSQL_THD thd)
return binlog_filter->db_ok(thd->db); 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) 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);
} }

View File

@ -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); thd->locked_tables_list.add_back_last_deleted_lock(pos_in_locked_tables);
if (thd->locked_tables_list.reopen_tables(thd)) if (thd->locked_tables_list.reopen_tables(thd))
{
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0); thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
result= 1;
}
else else
{ {
TABLE *table= pos_in_locked_tables->table; TABLE *table= pos_in_locked_tables->table;
@ -5292,6 +5295,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
if (res) if (res)
{ {
/* is_error() may be 0 if table existed and we generated a warning */
res= thd->is_error(); res= thd->is_error();
goto err; 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); thd->locked_tables_list.add_back_last_deleted_lock(pos_in_locked_tables);
if (thd->locked_tables_list.reopen_tables(thd)) if (thd->locked_tables_list.reopen_tables(thd))
{
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0); thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
res= 1; // We got an error
}
else else
{ {
/* /*

View File

@ -385,7 +385,8 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
pos=empty; pos=empty;
do 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); DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
} }

View File

@ -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) 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->dupp++;
sort_info->info->cur_row.lastpos= get_record_for_key(sort_param->keyinfo, sort_info->info->cur_row.lastpos= get_record_for_key(sort_param->keyinfo,
a); a);

View File

@ -288,9 +288,7 @@ void my_hash_sort_8bit_bin(CHARSET_INFO *cs __attribute__((unused)),
for (; key < end ; key++) for (; key < end ; key++)
{ {
tmp1^= (ulong) ((((uint) tmp1 & 63) + tmp2) * MY_HASH_ADD(tmp1, tmp2, (uint) *key);
((uint) *key)) + (tmp1 << 8);
tmp2+= 3;
} }
*nr1= tmp1; *nr1= tmp1;
@ -307,9 +305,7 @@ void my_hash_sort_bin(CHARSET_INFO *cs __attribute__((unused)),
for (; key < end ; key++) for (; key < end ; key++)
{ {
tmp1^= (ulong) ((((uint) tmp1 & 63) + tmp2) * MY_HASH_ADD(tmp1, tmp2, (uint) *key);
((uint) *key)) + (tmp1 << 8);
tmp2+= 3;
} }
*nr1= tmp1; *nr1= tmp1;

View File

@ -691,6 +691,8 @@ void my_hash_sort_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
ulong *nr1, ulong *nr2) ulong *nr1, ulong *nr2)
{ {
const uchar *end; const uchar *end;
register ulong m1= *nr1, m2= *nr2;
/* /*
Remove end space. We have to do this to be able to compare Remove end space. We have to do this to be able to compare
'AE' and 'Ä' as identical 'AE' and 'Ä' as identical
@ -700,14 +702,14 @@ void my_hash_sort_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
for (; key < end ; key++) for (; key < end ; key++)
{ {
uint X= (uint) combo1map[(uint) *key]; uint X= (uint) combo1map[(uint) *key];
nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * X) + (nr1[0] << 8); MY_HASH_ADD(m1, m2, X);
nr2[0]+=3;
if ((X= combo2map[*key])) if ((X= combo2map[*key]))
{ {
nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * X) + (nr1[0] << 8); MY_HASH_ADD(m1, m2, X);
nr2[0]+=3;
} }
} }
*nr1= m1;
*nr2= m2;
} }

View File

@ -680,6 +680,8 @@ void
my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)), my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
const uchar *key, size_t len,ulong *nr1, ulong *nr2) 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 Remove trailing spaces. We have to do this to be able to compare
'A ' and 'A' as identical 'A ' and 'A' as identical
@ -688,10 +690,10 @@ my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
for (; key < end ; key++) for (; key < end ; key++)
{ {
nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * MY_HASH_ADD(m1, m2, (uint)*key);
((uint)*key)) + (nr1[0] << 8);
nr2[0]+=3;
} }
*nr1= m1;
*nr2= m2;
} }

View File

@ -306,24 +306,48 @@ void my_hash_sort_simple(CHARSET_INFO *cs,
{ {
register const uchar *sort_order=cs->sort_order; register const uchar *sort_order=cs->sort_order;
const uchar *end; 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 Remove all trailing characters that are equal to space.
'A ' and 'A' as identical We have to do this to be able to compare 'A ' and 'A' as identical.
*/
end= skip_trailing_space(key, len); 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
*/
for ( ; key < end ; )
{
if (sort_order[*--end] != space_weight)
{
end++;
break;
}
}
n1= *nr1;
n2= *nr2;
for (; key < (uchar*) end ; key++) for (; key < (uchar*) end ; key++)
{ {
n1^=(ulong) ((((uint) n1 & 63)+n2) * MY_HASH_ADD(m1, m2, (uint) sort_order[(uint) *key]);
((uint) sort_order[(uint) *key])) + (n1 << 8);
n2+=3;
} }
*nr1= n1; *nr1= m1;
*nr2= n2; *nr2= m2;
} }

View File

@ -20873,21 +20873,45 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs,
static void my_hash_sort_uca(CHARSET_INFO *cs, static void my_hash_sort_uca(CHARSET_INFO *cs,
my_uca_scanner_handler *scanner_handler, my_uca_scanner_handler *scanner_handler,
const uchar *s, size_t slen, const uchar *s, size_t slen,
ulong *n1, ulong *n2) ulong *nr1, ulong *nr2)
{ {
int s_res; int s_res;
my_uca_scanner scanner; my_uca_scanner scanner;
int space_weight= my_space_weight(cs);
register ulong m1= *nr1, m2= *nr2;
slen= cs->cset->lengthsp(cs, (char*) s, slen);
scanner_handler->init(&scanner, cs, &cs->uca->level[0], s, slen); scanner_handler->init(&scanner, cs, &cs->uca->level[0], s, slen);
while ((s_res= scanner_handler->next(&scanner)) >0) while ((s_res= scanner_handler->next(&scanner)) >0)
{ {
n1[0]^= (((n1[0] & 63)+n2[0])*(s_res >> 8))+ (n1[0] << 8); if (s_res == space_weight)
n2[0]+=3; {
n1[0]^= (((n1[0] & 63)+n2[0])*(s_res & 0xFF))+ (n1[0] << 8); /* Combine all spaces to be able to skip end spaces */
n2[0]+=3; 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;
} }

View File

@ -1222,23 +1222,23 @@ my_caseup_utf16(CHARSET_INFO *cs, char *src, size_t srclen,
static void static void
my_hash_sort_utf16(CHARSET_INFO *cs, const uchar *s, size_t slen, 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_wc_t wc;
my_charset_conv_mb_wc mb_wc= cs->cset->mb_wc; my_charset_conv_mb_wc mb_wc= cs->cset->mb_wc;
int res; int res;
const uchar *e= s + cs->cset->lengthsp(cs, (const char *) s, slen); const uchar *e= s + cs->cset->lengthsp(cs, (const char *) s, slen);
MY_UNICASE_INFO *uni_plane= cs->caseinfo; 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) while ((s < e) && (res= mb_wc(cs, &wc, (uchar *) s, (uchar *) e)) > 0)
{ {
my_tosort_utf16(uni_plane, &wc); my_tosort_utf16(uni_plane, &wc);
n1[0]^= (((n1[0] & 63) + n2[0]) * (wc & 0xFF)) + (n1[0] << 8); MY_HASH_ADD_16(m1, m2, wc);
n2[0]+= 3;
n1[0]^= (((n1[0] & 63) + n2[0]) * (wc >> 8)) + (n1[0] << 8);
n2[0]+= 3;
s+= res; 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 *pos, size_t len, ulong *nr1, ulong *nr2)
{ {
const uchar *end= pos + cs->cset->lengthsp(cs, (const char *) pos, len); const uchar *end= pos + cs->cset->lengthsp(cs, (const char *) pos, len);
register ulong m1= *nr1, m2= *nr2;
for ( ; pos < end ; pos++) for ( ; pos < end ; pos++)
{ {
nr1[0]^= (ulong) ((((uint) nr1[0] & 63) + nr2[0]) * MY_HASH_ADD(m1, m2, (uint)*pos);
((uint)*pos)) + (nr1[0] << 8);
nr2[0]+= 3;
} }
*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 static void
my_hash_sort_utf32(CHARSET_INFO *cs, const uchar *s, size_t slen, 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; my_wc_t wc;
int res; int res;
const uchar *e= s + slen; const uchar *e= s + slen;
MY_UNICASE_INFO *uni_plane= cs->caseinfo; MY_UNICASE_INFO *uni_plane= cs->caseinfo;
register ulong m1= *nr1, m2= *nr2;
/* Skip trailing spaces */ /* Skip trailing spaces */
while (e > s + 3 && e[-1] == ' ' && !e[-2] && !e[-3] && !e[-4]) 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) while ((res= my_utf32_uni(cs, &wc, (uchar*) s, (uchar*) e)) > 0)
{ {
my_tosort_utf32(uni_plane, &wc); my_tosort_utf32(uni_plane, &wc);
my_hash_add(n1, n2, (uint) (wc >> 24)); MY_HASH_ADD(m1, m2, (uint) (wc >> 24));
my_hash_add(n1, n2, (uint) (wc >> 16) & 0xFF); MY_HASH_ADD(m1, m2, (uint) (wc >> 16) & 0xFF);
my_hash_add(n1, n2, (uint) (wc >> 8) & 0xFF); MY_HASH_ADD(m1, m2, (uint) (wc >> 8) & 0xFF);
my_hash_add(n1, n2, (uint) (wc & 0xFF)); MY_HASH_ADD(m1, m2, (uint) (wc & 0xFF));
s+= res; 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, 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; my_wc_t wc;
int res; int res;
const uchar *e=s+slen; const uchar *e=s+slen;
MY_UNICASE_INFO *uni_plane= cs->caseinfo; MY_UNICASE_INFO *uni_plane= cs->caseinfo;
register ulong m1= *nr1, m2= *nr2;
while (e > s+1 && e[-1] == ' ' && e[-2] == '\0') while (e > s+1 && e[-1] == ' ' && e[-2] == '\0')
e-= 2; 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) while ((s < e) && (res=my_ucs2_uni(cs,&wc, (uchar *)s, (uchar*)e)) >0)
{ {
my_tosort_ucs2(uni_plane, &wc); my_tosort_ucs2(uni_plane, &wc);
n1[0]^= (((n1[0] & 63)+n2[0])*(wc & 0xFF))+ (n1[0] << 8); MY_HASH_ADD_16(m1, m2, wc);
n2[0]+=3;
n1[0]^= (((n1[0] & 63)+n2[0])*(wc >> 8))+ (n1[0] << 8);
n2[0]+=3;
s+=res; 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 *key, size_t len,ulong *nr1, ulong *nr2)
{ {
const uchar *end = key + len; const uchar *end = key + len;
register ulong m1= *nr1, m2= *nr2;
while (end > key+1 && end[-1] == ' ' && end[-2] == '\0') while (end > key+1 && end[-1] == ' ' && end[-2] == '\0')
end-= 2; end-= 2;
for (; key < (uchar*) end ; key++) for (; key < (uchar*) end ; key++)
{ {
nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * MY_HASH_ADD(m1, m2, (uint)*key);
((uint)*key)) + (nr1[0] << 8);
nr2[0]+=3;
} }
*nr1= m1;
*nr2= m2;
} }

View File

@ -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, 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; my_wc_t wc;
int res; int res;
const uchar *e=s+slen; const uchar *e=s+slen;
MY_UNICASE_INFO *uni_plane= cs->caseinfo; 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 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 ) while ((s < e) && (res=my_utf8_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 )
{ {
my_tosort_unicode(uni_plane, &wc, cs->state); my_tosort_unicode(uni_plane, &wc, cs->state);
n1[0]^= (((n1[0] & 63)+n2[0])*(wc & 0xFF))+ (n1[0] << 8); MY_HASH_ADD_16(m1, m2, wc);
n2[0]+=3;
n1[0]^= (((n1[0] & 63)+n2[0])*(wc >> 8))+ (n1[0] << 8);
n2[0]+=3;
s+=res; 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 static void
my_hash_sort_utf8mb4(CHARSET_INFO *cs, const uchar *s, size_t slen, 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; my_wc_t wc;
int res; int res;
const uchar *e= s + slen; const uchar *e= s + slen;
MY_UNICASE_INFO *uni_plane= cs->caseinfo; MY_UNICASE_INFO *uni_plane= cs->caseinfo;
register ulong m1= *nr1, m2= *nr2;
/* /*
Remove end space. We do this to be able to compare 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) while ((res= my_mb_wc_utf8mb4(cs, &wc, (uchar*) s, (uchar*) e)) > 0)
{ {
my_tosort_unicode(uni_plane, &wc, cs->state); my_tosort_unicode(uni_plane, &wc, cs->state);
my_hash_add(n1, n2, (uint) (wc & 0xFF)); MY_HASH_ADD_16(m1, m2, (uint) (wc & 0xFFFF));
my_hash_add(n1, n2, (uint) (wc >> 8) & 0xFF);
if (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 This is useful to keep order of records in
test results, e.g. for "SHOW GRANTS". 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; s+= res;
} }
*nr1= m1;
*nr2= m2;
} }

View File

@ -100,4 +100,20 @@ static inline const uchar *skip_trailing_space(const uchar *ptr,size_t len)
end--; end--;
return (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 #endif