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;
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);
}

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

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

View File

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

View File

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

View File

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

View File

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

View File

@ -58,6 +58,7 @@ drop table t2;
--sync_with_master 0,'master2'
--connection slave
--sorted_result
stop all slaves;
--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;
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
#

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
}
#
# 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

View File

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

View File

@ -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);
}
/**

View File

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

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);
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
{
/*

View File

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

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)
{
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);

View File

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

View File

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

View File

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

View File

@ -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
*/
end= skip_trailing_space(key, len);
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
*/
for ( ; key < end ; )
{
if (sort_order[*--end] != space_weight)
{
end++;
break;
}
}
n1= *nr1;
n2= *nr2;
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;
}

View File

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

View File

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

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,
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;
}

View File

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