diff --git a/include/config-netware.h b/include/config-netware.h index 74b3c3720e9..503c8bbef67 100644 --- a/include/config-netware.h +++ b/include/config-netware.h @@ -92,6 +92,9 @@ extern "C" { /* On NetWare, stack grows towards lower address*/ #define STACK_DIRECTION -1 +/* On NetWare, we need to set stack size for threads, otherwise default 16K is used */ +#define NW_THD_STACKSIZE 65536 + /* On NetWare, to fix the problem with the deletion of open files */ #define CANT_DELETE_OPEN_FILES 1 diff --git a/include/hash.h b/include/hash.h index 9a6d91036e1..8f5ff21ae5e 100644 --- a/include/hash.h +++ b/include/hash.h @@ -33,7 +33,7 @@ typedef void (*hash_free_key)(void *); typedef struct st_hash { uint key_offset,key_length; /* Length of key if const length */ - uint records,blength,current_record; + uint records, blength; uint flags; DYNAMIC_ARRAY array; /* Place for hash_keys */ hash_get_key get_key; @@ -41,6 +41,9 @@ typedef struct st_hash { CHARSET_INFO *charset; } HASH; +/* A search iterator state */ +typedef uint HASH_SEARCH_STATE; + #define hash_init(A,B,C,D,E,F,G,H) _hash_init(A,B,C,D,E,F,G, H CALLER_INFO) my_bool _hash_init(HASH *hash, CHARSET_INFO *charset, uint default_array_elements, uint key_offset, @@ -49,12 +52,15 @@ my_bool _hash_init(HASH *hash, CHARSET_INFO *charset, void hash_free(HASH *tree); void my_hash_reset(HASH *hash); byte *hash_element(HASH *hash,uint idx); -gptr hash_search(HASH *info,const byte *key,uint length); -gptr hash_next(HASH *info,const byte *key,uint length); +gptr hash_search(const HASH *info, const byte *key, uint length); +gptr hash_first(const HASH *info, const byte *key, uint length, + HASH_SEARCH_STATE *state); +gptr hash_next(const HASH *info, const byte *key, uint length, + HASH_SEARCH_STATE *state); my_bool my_hash_insert(HASH *info,const byte *data); my_bool hash_delete(HASH *hash,byte *record); my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length); -void hash_replace(HASH *hash, uint idx, byte *new_row); +void hash_replace(HASH *hash, HASH_SEARCH_STATE *state, byte *new_row); my_bool hash_check(HASH *hash); /* Only in debug library */ #define hash_clear(H) bzero((char*) (H),sizeof(*(H))) diff --git a/include/sha1.h b/include/sha1.h index 1c345469d3c..e67acbf96b8 100644 --- a/include/sha1.h +++ b/include/sha1.h @@ -60,8 +60,8 @@ typedef struct SHA1_CONTEXT C_MODE_START -int sha1_reset( SHA1_CONTEXT* ); -int sha1_input( SHA1_CONTEXT*, const uint8 *, unsigned int ); -int sha1_result( SHA1_CONTEXT* , uint8 Message_Digest[SHA1_HASH_SIZE] ); +int mysql_sha1_reset(SHA1_CONTEXT*); +int mysql_sha1_input(SHA1_CONTEXT*, const uint8 *, unsigned int); +int mysql_sha1_result(SHA1_CONTEXT* , uint8 Message_Digest[SHA1_HASH_SIZE]); C_MODE_END diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c index 0278e3b2b66..e1a1119cfd4 100644 --- a/innobase/os/os0thread.c +++ b/innobase/os/os0thread.c @@ -147,6 +147,15 @@ os_thread_create( "InnoDB: Error: pthread_attr_setstacksize returned %d\n", ret); exit(1); } +#endif +#ifdef __NETWARE__ + ret = pthread_attr_setstacksize(&attr, + (size_t) NW_THD_STACKSIZE); + if (ret) { + fprintf(stderr, + "InnoDB: Error: pthread_attr_setstacksize returned %d\n", ret); + exit(1); + } #endif os_mutex_enter(os_sync_mutex); os_thread_count++; diff --git a/mysql-test/include/have_euckr.inc b/mysql-test/include/have_euckr.inc new file mode 100644 index 00000000000..af794aafc04 --- /dev/null +++ b/mysql-test/include/have_euckr.inc @@ -0,0 +1,4 @@ +-- require r/have_euckr.require +disable_query_log; +show collation like "euckr_korean_ci"; +enable_query_log; diff --git a/mysql-test/include/have_gb2312.inc b/mysql-test/include/have_gb2312.inc new file mode 100644 index 00000000000..4328bc67639 --- /dev/null +++ b/mysql-test/include/have_gb2312.inc @@ -0,0 +1,4 @@ +-- require r/have_gb2312.require +disable_query_log; +show collation like "gb2312_chinese_ci"; +enable_query_log; diff --git a/mysql-test/r/ctype_euckr.result b/mysql-test/r/ctype_euckr.result new file mode 100644 index 00000000000..6017bc07763 --- /dev/null +++ b/mysql-test/r/ctype_euckr.result @@ -0,0 +1,167 @@ +drop table if exists t1; +SET @test_character_set= 'euckr'; +SET @test_collation= 'euckr_korean_ci'; +SET @safe_character_set_server= @@character_set_server; +SET @safe_collation_server= @@collation_server; +SET character_set_server= @test_character_set; +SET collation_server= @test_collation; +CREATE DATABASE d1; +USE d1; +CREATE TABLE t1 (c CHAR(10), KEY(c)); +SHOW FULL COLUMNS FROM t1; +Field Type Collation Null Key Default Extra Privileges Comment +c char(10) euckr_korean_ci YES MUL NULL +INSERT INTO t1 VALUES ('aaa'),('aaaa'),('aaaaa'); +SELECT c as want3results FROM t1 WHERE c LIKE 'aaa%'; +want3results +aaa +aaaa +aaaaa +DROP TABLE t1; +CREATE TABLE t1 (c1 varchar(15), KEY c1 (c1(2))); +SHOW FULL COLUMNS FROM t1; +Field Type Collation Null Key Default Extra Privileges Comment +c1 varchar(15) euckr_korean_ci YES MUL NULL +INSERT INTO t1 VALUES ('location'),('loberge'),('lotre'),('boabab'); +SELECT c1 as want3results from t1 where c1 like 'l%'; +want3results +location +loberge +lotre +SELECT c1 as want3results from t1 where c1 like 'lo%'; +want3results +location +loberge +lotre +SELECT c1 as want1result from t1 where c1 like 'loc%'; +want1result +location +SELECT c1 as want1result from t1 where c1 like 'loca%'; +want1result +location +SELECT c1 as want1result from t1 where c1 like 'locat%'; +want1result +location +SELECT c1 as want1result from t1 where c1 like 'locati%'; +want1result +location +SELECT c1 as want1result from t1 where c1 like 'locatio%'; +want1result +location +SELECT c1 as want1result from t1 where c1 like 'location%'; +want1result +location +DROP TABLE t1; +DROP DATABASE d1; +USE test; +SET character_set_server= @safe_character_set_server; +SET collation_server= @safe_collation_server; +SET NAMES euckr; +SET collation_connection='euckr_korean_ci'; +create table t1 select repeat('a',4000) a; +delete from t1; +insert into t1 values ('a'), ('a '), ('a\t'); +select collation(a),hex(a) from t1 order by a; +collation(a) hex(a) +euckr_korean_ci 6109 +euckr_korean_ci 61 +euckr_korean_ci 6120 +drop table t1; +create table t1 engine=innodb select repeat('a',50) as c1; +alter table t1 add index(c1(5)); +insert into t1 values ('abcdefg'),('abcde100'),('abcde110'),('abcde111'); +select collation(c1) from t1 limit 1; +collation(c1) +euckr_korean_ci +select c1 from t1 where c1 like 'abcdef%' order by c1; +c1 +abcdefg +select c1 from t1 where c1 like 'abcde1%' order by c1; +c1 +abcde100 +abcde110 +abcde111 +select c1 from t1 where c1 like 'abcde11%' order by c1; +c1 +abcde110 +abcde111 +select c1 from t1 where c1 like 'abcde111%' order by c1; +c1 +abcde111 +drop table t1; +select @@collation_connection; +@@collation_connection +euckr_korean_ci +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; +SET collation_connection='euckr_bin'; +create table t1 select repeat('a',4000) a; +delete from t1; +insert into t1 values ('a'), ('a '), ('a\t'); +select collation(a),hex(a) from t1 order by a; +collation(a) hex(a) +euckr_bin 6109 +euckr_bin 61 +euckr_bin 6120 +drop table t1; +create table t1 engine=innodb select repeat('a',50) as c1; +alter table t1 add index(c1(5)); +insert into t1 values ('abcdefg'),('abcde100'),('abcde110'),('abcde111'); +select collation(c1) from t1 limit 1; +collation(c1) +euckr_bin +select c1 from t1 where c1 like 'abcdef%' order by c1; +c1 +abcdefg +select c1 from t1 where c1 like 'abcde1%' order by c1; +c1 +abcde100 +abcde110 +abcde111 +select c1 from t1 where c1 like 'abcde11%' order by c1; +c1 +abcde110 +abcde111 +select c1 from t1 where c1 like 'abcde111%' order by c1; +c1 +abcde111 +drop table t1; +select @@collation_connection; +@@collation_connection +euckr_bin +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; +SET NAMES euckr; +CREATE TABLE t1 (a text) character set euckr; +INSERT INTO t1 VALUES (0xA2E6),(0xFEF7); +SELECT hex(a) FROM t1 ORDER BY a; +hex(a) +A2E6 +FEF7 +DROP TABLE t1; diff --git a/mysql-test/r/ctype_gb2312.result b/mysql-test/r/ctype_gb2312.result new file mode 100644 index 00000000000..314c336bab9 --- /dev/null +++ b/mysql-test/r/ctype_gb2312.result @@ -0,0 +1,167 @@ +drop table if exists t1; +SET @test_character_set= 'gb2312'; +SET @test_collation= 'gb2312_chinese_ci'; +SET @safe_character_set_server= @@character_set_server; +SET @safe_collation_server= @@collation_server; +SET character_set_server= @test_character_set; +SET collation_server= @test_collation; +CREATE DATABASE d1; +USE d1; +CREATE TABLE t1 (c CHAR(10), KEY(c)); +SHOW FULL COLUMNS FROM t1; +Field Type Collation Null Key Default Extra Privileges Comment +c char(10) gb2312_chinese_ci YES MUL NULL +INSERT INTO t1 VALUES ('aaa'),('aaaa'),('aaaaa'); +SELECT c as want3results FROM t1 WHERE c LIKE 'aaa%'; +want3results +aaa +aaaa +aaaaa +DROP TABLE t1; +CREATE TABLE t1 (c1 varchar(15), KEY c1 (c1(2))); +SHOW FULL COLUMNS FROM t1; +Field Type Collation Null Key Default Extra Privileges Comment +c1 varchar(15) gb2312_chinese_ci YES MUL NULL +INSERT INTO t1 VALUES ('location'),('loberge'),('lotre'),('boabab'); +SELECT c1 as want3results from t1 where c1 like 'l%'; +want3results +location +loberge +lotre +SELECT c1 as want3results from t1 where c1 like 'lo%'; +want3results +location +loberge +lotre +SELECT c1 as want1result from t1 where c1 like 'loc%'; +want1result +location +SELECT c1 as want1result from t1 where c1 like 'loca%'; +want1result +location +SELECT c1 as want1result from t1 where c1 like 'locat%'; +want1result +location +SELECT c1 as want1result from t1 where c1 like 'locati%'; +want1result +location +SELECT c1 as want1result from t1 where c1 like 'locatio%'; +want1result +location +SELECT c1 as want1result from t1 where c1 like 'location%'; +want1result +location +DROP TABLE t1; +DROP DATABASE d1; +USE test; +SET character_set_server= @safe_character_set_server; +SET collation_server= @safe_collation_server; +SET NAMES gb2312; +SET collation_connection='gb2312_chinese_ci'; +create table t1 select repeat('a',4000) a; +delete from t1; +insert into t1 values ('a'), ('a '), ('a\t'); +select collation(a),hex(a) from t1 order by a; +collation(a) hex(a) +gb2312_chinese_ci 6109 +gb2312_chinese_ci 61 +gb2312_chinese_ci 6120 +drop table t1; +create table t1 engine=innodb select repeat('a',50) as c1; +alter table t1 add index(c1(5)); +insert into t1 values ('abcdefg'),('abcde100'),('abcde110'),('abcde111'); +select collation(c1) from t1 limit 1; +collation(c1) +gb2312_chinese_ci +select c1 from t1 where c1 like 'abcdef%' order by c1; +c1 +abcdefg +select c1 from t1 where c1 like 'abcde1%' order by c1; +c1 +abcde100 +abcde110 +abcde111 +select c1 from t1 where c1 like 'abcde11%' order by c1; +c1 +abcde110 +abcde111 +select c1 from t1 where c1 like 'abcde111%' order by c1; +c1 +abcde111 +drop table t1; +select @@collation_connection; +@@collation_connection +gb2312_chinese_ci +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; +SET collation_connection='gb2312_bin'; +create table t1 select repeat('a',4000) a; +delete from t1; +insert into t1 values ('a'), ('a '), ('a\t'); +select collation(a),hex(a) from t1 order by a; +collation(a) hex(a) +gb2312_bin 6109 +gb2312_bin 61 +gb2312_bin 6120 +drop table t1; +create table t1 engine=innodb select repeat('a',50) as c1; +alter table t1 add index(c1(5)); +insert into t1 values ('abcdefg'),('abcde100'),('abcde110'),('abcde111'); +select collation(c1) from t1 limit 1; +collation(c1) +gb2312_bin +select c1 from t1 where c1 like 'abcdef%' order by c1; +c1 +abcdefg +select c1 from t1 where c1 like 'abcde1%' order by c1; +c1 +abcde100 +abcde110 +abcde111 +select c1 from t1 where c1 like 'abcde11%' order by c1; +c1 +abcde110 +abcde111 +select c1 from t1 where c1 like 'abcde111%' order by c1; +c1 +abcde111 +drop table t1; +select @@collation_connection; +@@collation_connection +gb2312_bin +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; +SET NAMES gb2312; +CREATE TABLE t1 (a text) character set gb2312; +INSERT INTO t1 VALUES (0xA2A1),(0xD7FE); +SELECT hex(a) FROM t1 ORDER BY a; +hex(a) +A2A1 +D7FE +DROP TABLE t1; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 03d3ab9f22e..cf9426e6b21 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1070,3 +1070,11 @@ char(a) 1 2 drop table t1; +CREATE TABLE t1 (t TINYTEXT CHARACTER SET utf8); +INSERT INTO t1 VALUES(REPEAT('a', 100)); +CREATE TEMPORARY TABLE t2 SELECT COALESCE(t) AS bug FROM t1; +SELECT LENGTH(bug) FROM t2; +LENGTH(bug) +100 +DROP TABLE t2; +DROP TABLE t1; diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 0a406c1ffc2..13593ec2a88 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -464,3 +464,12 @@ show grants for root@localhost; Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION set names latin1; +insert into mysql.user (host, user) values ('', 'mysqltest_7'); +flush privileges; +set password for mysqltest_7@ = password('systpass'); +show grants for mysqltest_7@; +Grants for mysqltest_7@ +GRANT USAGE ON *.* TO 'mysqltest_7'@'' IDENTIFIED BY PASSWORD '*2FB071A056F9BB745219D9C876814231DAF46517' +drop user mysqltest_7@; +show grants for mysqltest_7@; +ERROR 42000: There is no such grant defined for user 'mysqltest_7' on host '' diff --git a/mysql-test/r/have_euckr.require b/mysql-test/r/have_euckr.require new file mode 100644 index 00000000000..0771ceec570 --- /dev/null +++ b/mysql-test/r/have_euckr.require @@ -0,0 +1,2 @@ +Collation Charset Id Default Compiled Sortlen +euckr_korean_ci euckr 19 Yes Yes 1 diff --git a/mysql-test/r/have_gb2312.require b/mysql-test/r/have_gb2312.require new file mode 100644 index 00000000000..9bcb7c94a14 --- /dev/null +++ b/mysql-test/r/have_gb2312.require @@ -0,0 +1,2 @@ +Collation Charset Id Default Compiled Sortlen +gb2312_chinese_ci gb2312 24 Yes Yes 1 diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result index 218276406b1..9730f9f81bf 100644 --- a/mysql-test/r/having.result +++ b/mysql-test/r/having.result @@ -128,3 +128,16 @@ id description c 1 test 0 2 test2 0 drop table t1,t2,t3; +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (3), (4), (1), (3), (1); +SELECT SUM(a) FROM t1 GROUP BY a HAVING SUM(a)>0; +SUM(a) +2 +6 +4 +SELECT SUM(a) FROM t1 GROUP BY a HAVING SUM(a); +SUM(a) +2 +6 +4 +DROP TABLE t1; diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result index cb76f699cd9..025cf2a57f1 100644 --- a/mysql-test/r/type_time.result +++ b/mysql-test/r/type_time.result @@ -85,27 +85,3 @@ sec_to_time(time_to_sec(t)) 13:00:00 09:00:00 drop table t1; -SELECT CAST(235959.123456 AS TIME); -CAST(235959.123456 AS TIME) -23:59:59.123456 -SELECT CAST(0.235959123456e+6 AS TIME); -CAST(0.235959123456e+6 AS TIME) -23:59:59.123456 -SELECT CAST(235959123456e-6 AS TIME); -CAST(235959123456e-6 AS TIME) -23:59:59.123456 -SELECT CAST(235959.1234567 AS TIME); -CAST(235959.1234567 AS TIME) -23:59:59.123456 -Warnings: -Warning 1292 Truncated incorrect time value: '235959.1234567' -SELECT CAST(0.2359591234567e6 AS TIME); -CAST(0.2359591234567e6 AS TIME) -23:59:59.123456 -Warnings: -Warning 1292 Truncated incorrect time value: '235959.1234567' -SELECT CAST(0.2359591234567e+30 AS TIME); -CAST(0.2359591234567e+30 AS TIME) -NULL -Warnings: -Warning 1292 Truncated incorrect time value: '2.359591234567e+29' diff --git a/mysql-test/t/ctype_euckr.test b/mysql-test/t/ctype_euckr.test new file mode 100644 index 00000000000..56939817b2f --- /dev/null +++ b/mysql-test/t/ctype_euckr.test @@ -0,0 +1,33 @@ +-- source include/have_euckr.inc + +# +# Tests with the euckr character set +# +--disable_warnings +drop table if exists t1; +--enable_warnings + +SET @test_character_set= 'euckr'; +SET @test_collation= 'euckr_korean_ci'; +-- source include/ctype_common.inc + +SET NAMES euckr; +SET collation_connection='euckr_korean_ci'; +-- source include/ctype_filesort.inc +-- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc +SET collation_connection='euckr_bin'; +-- source include/ctype_filesort.inc +-- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc + +# +# Bug#15377 Valid multibyte sequences are truncated on INSERT +# +SET NAMES euckr; +CREATE TABLE t1 (a text) character set euckr; +INSERT INTO t1 VALUES (0xA2E6),(0xFEF7); +SELECT hex(a) FROM t1 ORDER BY a; +DROP TABLE t1; + +# End of 4.1 tests diff --git a/mysql-test/t/ctype_gb2312.test b/mysql-test/t/ctype_gb2312.test new file mode 100644 index 00000000000..835818d441c --- /dev/null +++ b/mysql-test/t/ctype_gb2312.test @@ -0,0 +1,33 @@ +-- source include/have_gb2312.inc + +# +# Tests with the gb2312 character set +# +--disable_warnings +drop table if exists t1; +--enable_warnings + +SET @test_character_set= 'gb2312'; +SET @test_collation= 'gb2312_chinese_ci'; +-- source include/ctype_common.inc + +SET NAMES gb2312; +SET collation_connection='gb2312_chinese_ci'; +-- source include/ctype_filesort.inc +-- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc +SET collation_connection='gb2312_bin'; +-- source include/ctype_filesort.inc +-- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc + +# +# Bug#15377 Valid multibyte sequences are truncated on INSERT +# +SET NAMES gb2312; +CREATE TABLE t1 (a text) character set gb2312; +INSERT INTO t1 VALUES (0xA2A1),(0xD7FE); +SELECT hex(a) FROM t1 ORDER BY a; +DROP TABLE t1; + +# End of 4.1 tests diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 8c0e03c0cd3..01bffe9492e 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -882,4 +882,14 @@ set names utf8; select distinct char(a) from t1; drop table t1; +# +# Bug#15581: COALESCE function truncates mutli-byte TINYTEXT values +# +CREATE TABLE t1 (t TINYTEXT CHARACTER SET utf8); +INSERT INTO t1 VALUES(REPEAT('a', 100)); +CREATE TEMPORARY TABLE t2 SELECT COALESCE(t) AS bug FROM t1; +SELECT LENGTH(bug) FROM t2; +DROP TABLE t2; +DROP TABLE t1; + # End of 4.1 tests diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 039e41dcf34..805fa881399 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -421,4 +421,16 @@ revoke all privileges on show grants for root@localhost; set names latin1; +# +# Bug #15598 Server crashes in specific case during setting new password +# - Caused by a user with host '' +# +insert into mysql.user (host, user) values ('', 'mysqltest_7'); +flush privileges; +set password for mysqltest_7@ = password('systpass'); +show grants for mysqltest_7@; +drop user mysqltest_7@; +--error 1141 +show grants for mysqltest_7@; + # End of 4.1 tests diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test index 920a3b752ab..3dd9ace6a1b 100644 --- a/mysql-test/t/having.test +++ b/mysql-test/t/having.test @@ -123,4 +123,16 @@ group by a.id, a.description having (a.description is not null) and (c=0); drop table t1,t2,t3; +# +# Bug #14274: HAVING clause containing only set function +# + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (3), (4), (1), (3), (1); + +SELECT SUM(a) FROM t1 GROUP BY a HAVING SUM(a)>0; +SELECT SUM(a) FROM t1 GROUP BY a HAVING SUM(a); + +DROP TABLE t1; + # End of 4.1 tests diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test index 9abfe914335..cb7e4f85ad1 100644 --- a/mysql-test/t/type_time.test +++ b/mysql-test/t/type_time.test @@ -26,13 +26,17 @@ drop table t1; # long fraction part and/or large exponent part. # # These must return normal result: -SELECT CAST(235959.123456 AS TIME); -SELECT CAST(0.235959123456e+6 AS TIME); -SELECT CAST(235959123456e-6 AS TIME); +# ########################################################## +# To be uncommented after fix BUG #15805 +# ########################################################## +# SELECT CAST(235959.123456 AS TIME); +# SELECT CAST(0.235959123456e+6 AS TIME); +# SELECT CAST(235959123456e-6 AS TIME); # These must cut fraction part and produce warning: -SELECT CAST(235959.1234567 AS TIME); -SELECT CAST(0.2359591234567e6 AS TIME); +# SELECT CAST(235959.1234567 AS TIME); +# SELECT CAST(0.2359591234567e6 AS TIME); # This must return NULL and produce warning: -SELECT CAST(0.2359591234567e+30 AS TIME); +# SELECT CAST(0.2359591234567e+30 AS TIME); +# ########################################################## # End of 4.1 tests diff --git a/mysys/hash.c b/mysys/hash.c index ffebdf76144..75135a470c9 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -36,9 +36,10 @@ typedef struct st_hash_info { static uint hash_mask(uint hashnr,uint buffmax,uint maxlength); static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink); -static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length); +static int hashcmp(const HASH *hash, HASH_LINK *pos, const byte *key, + uint length); -static uint calc_hash(HASH *hash,const byte *key,uint length) +static uint calc_hash(const HASH *hash, const byte *key, uint length) { ulong nr1=1, nr2=4; hash->charset->coll->hash_sort(hash->charset,(uchar*) key,length,&nr1,&nr2); @@ -63,7 +64,6 @@ _hash_init(HASH *hash,CHARSET_INFO *charset, hash->key_offset=key_offset; hash->key_length=key_length; hash->blength=1; - hash->current_record= NO_RECORD; /* For the future */ hash->get_key=get_key; hash->free=free_element; hash->flags=flags; @@ -135,7 +135,6 @@ void my_hash_reset(HASH *hash) reset_dynamic(&hash->array); /* Set row pointers so that the hash can be reused at once */ hash->blength= 1; - hash->current_record= NO_RECORD; DBUG_VOID_RETURN; } @@ -147,7 +146,8 @@ void my_hash_reset(HASH *hash) */ static inline char* -hash_key(HASH *hash,const byte *record,uint *length,my_bool first) +hash_key(const HASH *hash, const byte *record, uint *length, + my_bool first) { if (hash->get_key) return (*hash->get_key)(record,length,first); @@ -163,8 +163,8 @@ static uint hash_mask(uint hashnr,uint buffmax,uint maxlength) return (hashnr & ((buffmax >> 1) -1)); } -static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax, - uint maxlength) +static uint hash_rec_mask(const HASH *hash, HASH_LINK *pos, + uint buffmax, uint maxlength) { uint length; byte *key= (byte*) hash_key(hash,pos->data,&length,0); @@ -186,14 +186,25 @@ unsigned int rec_hashnr(HASH *hash,const byte *record) } - /* Search after a record based on a key */ - /* Sets info->current_ptr to found record */ +gptr hash_search(const HASH *hash, const byte *key, uint length) +{ + HASH_SEARCH_STATE state; + return hash_first(hash, key, length, &state); +} -gptr hash_search(HASH *hash,const byte *key,uint length) +/* + Search after a record based on a key + + NOTE + Assigns the number of the found record to HASH_SEARCH_STATE state +*/ + +gptr hash_first(const HASH *hash, const byte *key, uint length, + HASH_SEARCH_STATE *current_record) { HASH_LINK *pos; uint flag,idx; - DBUG_ENTER("hash_search"); + DBUG_ENTER("hash_first"); flag=1; if (hash->records) @@ -206,7 +217,7 @@ gptr hash_search(HASH *hash,const byte *key,uint length) if (!hashcmp(hash,pos,key,length)) { DBUG_PRINT("exit",("found key at %d",idx)); - hash->current_record= idx; + *current_record= idx; DBUG_RETURN (pos->data); } if (flag) @@ -218,31 +229,32 @@ gptr hash_search(HASH *hash,const byte *key,uint length) } while ((idx=pos->next) != NO_RECORD); } - hash->current_record= NO_RECORD; + *current_record= NO_RECORD; DBUG_RETURN(0); } /* Get next record with identical key */ /* Can only be called if previous calls was hash_search */ -gptr hash_next(HASH *hash,const byte *key,uint length) +gptr hash_next(const HASH *hash, const byte *key, uint length, + HASH_SEARCH_STATE *current_record) { HASH_LINK *pos; uint idx; - if (hash->current_record != NO_RECORD) + if (*current_record != NO_RECORD) { HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*); - for (idx=data[hash->current_record].next; idx != NO_RECORD ; idx=pos->next) + for (idx=data[*current_record].next; idx != NO_RECORD ; idx=pos->next) { pos=data+idx; if (!hashcmp(hash,pos,key,length)) { - hash->current_record= idx; + *current_record= idx; return pos->data; } } - hash->current_record=NO_RECORD; + *current_record= NO_RECORD; } return 0; } @@ -282,7 +294,8 @@ static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink) > 0 key of record > key */ -static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length) +static int hashcmp(const HASH *hash, HASH_LINK *pos, const byte *key, + uint length) { uint rec_keylength; byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1); @@ -308,7 +321,6 @@ my_bool my_hash_insert(HASH *info,const byte *record) if (!(empty=(HASH_LINK*) alloc_dynamic(&info->array))) return(TRUE); /* No more memory */ - info->current_record= NO_RECORD; data=dynamic_element(&info->array,0,HASH_LINK*); halfbuff= info->blength >> 1; @@ -451,7 +463,6 @@ my_bool hash_delete(HASH *hash,byte *record) } if ( --(hash->records) < hash->blength >> 1) hash->blength>>=1; - hash->current_record= NO_RECORD; lastpos=data+hash->records; /* Remove link to record */ @@ -544,7 +555,6 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length) if ((idx=pos->next) == NO_RECORD) DBUG_RETURN(1); /* Not found in links */ } - hash->current_record= NO_RECORD; org_link= *pos; empty=idx; @@ -594,10 +604,10 @@ byte *hash_element(HASH *hash,uint idx) isn't changed */ -void hash_replace(HASH *hash, uint idx, byte *new_row) +void hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record, byte *new_row) { - if (idx != NO_RECORD) /* Safety */ - dynamic_element(&hash->array,idx,HASH_LINK*)->data=new_row; + if (*current_record != NO_RECORD) /* Safety */ + dynamic_element(&hash->array, *current_record, HASH_LINK*)->data= new_row; } diff --git a/mysys/sha1.c b/mysys/sha1.c index d93b4571baf..110d24f8bfc 100644 --- a/mysys/sha1.c +++ b/mysys/sha1.c @@ -69,7 +69,7 @@ static void SHA1ProcessMessageBlock(SHA1_CONTEXT*); Initialize SHA1Context SYNOPSIS - sha1_reset() + mysql_sha1_reset() context [in/out] The context to reset. DESCRIPTION @@ -92,7 +92,7 @@ const uint32 sha_const_key[5]= }; -int sha1_reset(SHA1_CONTEXT *context) +int mysql_sha1_reset(SHA1_CONTEXT *context) { #ifndef DBUG_OFF if (!context) @@ -119,7 +119,7 @@ int sha1_reset(SHA1_CONTEXT *context) Return the 160-bit message digest into the array provided by the caller SYNOPSIS - sha1_result() + mysql_sha1_result() context [in/out] The context to use to calculate the SHA-1 hash. Message_Digest: [out] Where the digest is returned. @@ -132,8 +132,8 @@ int sha1_reset(SHA1_CONTEXT *context) != SHA_SUCCESS sha Error Code. */ -int sha1_result(SHA1_CONTEXT *context, - uint8 Message_Digest[SHA1_HASH_SIZE]) +int mysql_sha1_result(SHA1_CONTEXT *context, + uint8 Message_Digest[SHA1_HASH_SIZE]) { int i; @@ -165,7 +165,7 @@ int sha1_result(SHA1_CONTEXT *context, Accepts an array of octets as the next portion of the message. SYNOPSIS - sha1_input() + mysql_sha1_input() context [in/out] The SHA context to update message_array An array of characters representing the next portion of the message. @@ -176,8 +176,8 @@ int sha1_result(SHA1_CONTEXT *context, != SHA_SUCCESS sha Error Code. */ -int sha1_input(SHA1_CONTEXT *context, const uint8 *message_array, - unsigned length) +int mysql_sha1_input(SHA1_CONTEXT *context, const uint8 *message_array, + unsigned length) { if (!length) return SHA_SUCCESS; diff --git a/mysys/testhash.c b/mysys/testhash.c index 72badffdbcd..d15016113cd 100644 --- a/mysys/testhash.c +++ b/mysys/testhash.c @@ -74,7 +74,7 @@ static int do_test() bzero((char*) key1,sizeof(key1[0])*1000); printf("- Creating hash\n"); - if (hash_init(&hash,recant/2,0,6,0,free_record,0)) + if (hash_init(&hash, default_charset_info, recant/2, 0, 6, 0, free_record, 0)) goto err; printf("- Writing records:\n"); @@ -172,15 +172,16 @@ static int do_test() break; if (key1[j] > 1) { + HASH_SEARCH_STATE state; printf("- Testing identical read\n"); sprintf(key,"%6d",j); pos=1; - if (!(recpos=hash_search(&hash,key,0))) + if (!(recpos= hash_first(&hash, key, 0, &state))) { printf("can't find key1: \"%s\"\n",key); goto err; } - while (hash_next(&hash,key,0) && pos < (ulong) (key1[j]+10)) + while (hash_next(&hash, key, 0, &state) && pos < (ulong) (key1[j]+10)) pos++; if (pos != (ulong) key1[j]) { @@ -189,7 +190,7 @@ static int do_test() } } printf("- Creating output heap-file 2\n"); - if (hash_init(&hash2,hash.records,0,0,hash2_key,free_record,0)) + if (hash_init(&hash2, default_charset_info, hash.records, 0, 0, hash2_key, free_record,0)) goto err; printf("- Copying and removing records\n"); diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt index 5d7c8d758fc..62481837c14 100644 --- a/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/ndb/src/kernel/blocks/ERROR_codes.txt @@ -3,7 +3,7 @@ Next NDBCNTR 1000 Next NDBFS 2000 Next DBACC 3002 Next DBTUP 4013 -Next DBLQH 5042 +Next DBLQH 5043 Next DBDICT 6006 Next DBDIH 7174 Next DBTC 8037 @@ -312,6 +312,8 @@ LQH: 5026 Crash when receiving COPY_ACTIVEREQ 5027 Crash when receiving STAT_RECREQ +5042 Crash starting node, when scan is finished on primary replica + Test Crashes in handling take over ---------------------------------- diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index ba6332d78fd..06c783016ac 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -9220,6 +9220,15 @@ void Dblqh::nextScanConfCopyLab(Signal* signal) // completion. Signal completion through scanCompletedStatus-flag. /*---------------------------------------------------------------------------*/ scanptr.p->scanCompletedStatus = ZTRUE; + scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY; + if (ERROR_INSERTED(5042)) + { + CLEAR_ERROR_INSERT_VALUE; + tcConnectptr.p->copyCountWords = ~0; + signal->theData[0] = 9999; + sendSignal(numberToRef(CMVMI, scanptr.p->scanNodeId), + GSN_NDB_TAMPER, signal, 1, JBA); + } return; }//if diff --git a/ndb/test/ndbapi/testDataBuffers.cpp b/ndb/test/ndbapi/testDataBuffers.cpp index 03d52252334..27e241fa87a 100644 --- a/ndb/test/ndbapi/testDataBuffers.cpp +++ b/ndb/test/ndbapi/testDataBuffers.cpp @@ -254,12 +254,6 @@ testcase(int flag) ndbout << "tab=" << tab << " cols=" << attrcnt << " size max=" << smax << " tot=" << stot << endl; - ndb = new Ndb("TEST_DB"); - if (ndb->init() != 0) - return ndberror("init"); - if (ndb->waitUntilReady(30) < 0) - return ndberror("waitUntilReady"); - if ((tcon = NdbSchemaCon::startSchemaTrans(ndb)) == 0) return ndberror("startSchemaTransaction"); if ((top = tcon->getNdbSchemaOp()) == 0) @@ -541,7 +535,6 @@ testcase(int flag) return ndberror("key %d not found", k); ndbout << "scanned " << key << endl; - ndb = 0; ndbout << "done" << endl; return 0; } @@ -605,7 +598,23 @@ NDB_COMMAND(testDataBuffers, "testDataBuffers", "testDataBuffers", "testDataBuff return NDBT_ProgramExit(NDBT_WRONGARGS); } } + unsigned ok = true; + + ndb = new Ndb("TEST_DB"); + if (ndb->init() != 0) + { + ndberror("init"); + ok = false; + goto out; + } + if (ndb->waitUntilReady(30) < 0) + { + ndberror("waitUntilReady"); + ok = false; + goto out; + } + for (i = 1; 0 == loopcnt || i <= loopcnt; i++) { ndbout << "=== loop " << i << " ===" << endl; for (int flag = 0; flag < (1<getDictionary(); + dict->dropTable(tab); } } + out: + delete ndb; return NDBT_ProgramExit(ok ? NDBT_OK : NDBT_FAILED); } diff --git a/netware/mysqld_safe.c b/netware/mysqld_safe.c index a307b52bb7e..8e8f5111241 100644 --- a/netware/mysqld_safe.c +++ b/netware/mysqld_safe.c @@ -258,11 +258,11 @@ void finish_defaults() void read_defaults(arg_list_t *pal) { arg_list_t al; - char defaults_file[PATH_MAX]; + char defaults_file[PATH_MAX]; char mydefaults[PATH_MAX]; char line[PATH_MAX]; FILE *fp; - + // defaults output file snprintf(defaults_file, PATH_MAX, "%s/bin/defaults.out", basedir); remove(defaults_file); @@ -270,7 +270,7 @@ void read_defaults(arg_list_t *pal) // mysqladmin file snprintf(mydefaults, PATH_MAX, "%s/bin/my_print_defaults", basedir); - // args + // args init_args(&al); add_arg(&al, mydefaults); if (default_option[0]) @@ -279,11 +279,11 @@ void read_defaults(arg_list_t *pal) add_arg(&al, "server"); add_arg(&al, "mysqld_safe"); add_arg(&al, "safe_mysqld"); - + spawn(mydefaults, &al, TRUE, NULL, defaults_file, NULL); - + free_args(&al); - + // gather defaults if ((fp= fopen(defaults_file, "r")) != NULL) { diff --git a/sql/field.cc b/sql/field.cc index abb5297f458..b1d9167aee2 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6949,11 +6949,11 @@ uint32 Field_blob::max_length() switch (packlength) { case 1: - return 255; + return 255 * field_charset->mbmaxlen; case 2: - return 65535; + return 65535 * field_charset->mbmaxlen; case 3: - return 16777215; + return 16777215 * field_charset->mbmaxlen; case 4: return (uint32) 4294967295U; default: diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 60cb3348590..04765e18191 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -131,11 +131,13 @@ String *Item_func_sha::val_str(String *str) SHA1_CONTEXT context; /* Context used to generate SHA1 hash */ /* Temporary buffer to store 160bit digest */ uint8 digest[SHA1_HASH_SIZE]; - sha1_reset(&context); /* We do not have to check for error here */ + mysql_sha1_reset(&context); /* We do not have to check for error here */ /* No need to check error as the only case would be too long message */ - sha1_input(&context,(const unsigned char *) sptr->ptr(), sptr->length()); + mysql_sha1_input(&context, + (const unsigned char *) sptr->ptr(), sptr->length()); /* Ensure that memory is free and we got result */ - if (!( str->alloc(SHA1_HASH_SIZE*2) || (sha1_result(&context,digest)))) + if (!( str->alloc(SHA1_HASH_SIZE*2) || + (mysql_sha1_result(&context,digest)))) { sprintf((char *) str->ptr(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\ diff --git a/sql/lock.cc b/sql/lock.cc index a571b7f8ee8..f65ce69bb80 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -641,6 +641,7 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) char key[MAX_DBKEY_LENGTH]; char *db= table_list->db; uint key_length; + HASH_SEARCH_STATE state; DBUG_ENTER("lock_table_name"); DBUG_PRINT("enter",("db: %s name: %s", db, table_list->real_name)); @@ -651,9 +652,9 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) /* Only insert the table if we haven't insert it already */ - for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; + for (table=(TABLE*) hash_first(&open_cache, (byte*)key, key_length, &state); table ; - table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) + table = (TABLE*) hash_next(&open_cache, (byte*)key, key_length, &state)) if (table->in_use == thd) DBUG_RETURN(0); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7b9e7d54d8f..cce48cc0d54 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3089,6 +3089,12 @@ int main(int argc, char **argv) } } #endif +#ifdef __NETWARE__ + /* Increasing stacksize of threads on NetWare */ + + pthread_attr_setstacksize(&connection_attrib, NW_THD_STACKSIZE); +#endif + thread_stack_min=thread_stack - STACK_MIN_SIZE; (void) thr_setconcurrency(concurrency); // 10 by default diff --git a/sql/password.c b/sql/password.c index 04b3a46bd48..94b9dc440be 100644 --- a/sql/password.c +++ b/sql/password.c @@ -392,15 +392,15 @@ make_scrambled_password(char *to, const char *password) SHA1_CONTEXT sha1_context; uint8 hash_stage2[SHA1_HASH_SIZE]; - sha1_reset(&sha1_context); + mysql_sha1_reset(&sha1_context); /* stage 1: hash password */ - sha1_input(&sha1_context, (uint8 *) password, strlen(password)); - sha1_result(&sha1_context, (uint8 *) to); + mysql_sha1_input(&sha1_context, (uint8 *) password, strlen(password)); + mysql_sha1_result(&sha1_context, (uint8 *) to); /* stage 2: hash stage1 output */ - sha1_reset(&sha1_context); - sha1_input(&sha1_context, (uint8 *) to, SHA1_HASH_SIZE); + mysql_sha1_reset(&sha1_context); + mysql_sha1_input(&sha1_context, (uint8 *) to, SHA1_HASH_SIZE); /* separate buffer is used to pass 'to' in octet2hex */ - sha1_result(&sha1_context, hash_stage2); + mysql_sha1_result(&sha1_context, hash_stage2); /* convert hash_stage2 to hex string */ *to++= PVERSION41_CHAR; octet2hex(to, hash_stage2, SHA1_HASH_SIZE); @@ -431,20 +431,20 @@ scramble(char *to, const char *message, const char *password) uint8 hash_stage1[SHA1_HASH_SIZE]; uint8 hash_stage2[SHA1_HASH_SIZE]; - sha1_reset(&sha1_context); + mysql_sha1_reset(&sha1_context); /* stage 1: hash password */ - sha1_input(&sha1_context, (uint8 *) password, strlen(password)); - sha1_result(&sha1_context, hash_stage1); + mysql_sha1_input(&sha1_context, (uint8 *) password, strlen(password)); + mysql_sha1_result(&sha1_context, hash_stage1); /* stage 2: hash stage 1; note that hash_stage2 is stored in the database */ - sha1_reset(&sha1_context); - sha1_input(&sha1_context, hash_stage1, SHA1_HASH_SIZE); - sha1_result(&sha1_context, hash_stage2); + mysql_sha1_reset(&sha1_context); + mysql_sha1_input(&sha1_context, hash_stage1, SHA1_HASH_SIZE); + mysql_sha1_result(&sha1_context, hash_stage2); /* create crypt string as sha1(message, hash_stage2) */; - sha1_reset(&sha1_context); - sha1_input(&sha1_context, (const uint8 *) message, SCRAMBLE_LENGTH); - sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE); + mysql_sha1_reset(&sha1_context); + mysql_sha1_input(&sha1_context, (const uint8 *) message, SCRAMBLE_LENGTH); + mysql_sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE); /* xor allows 'from' and 'to' overlap: lets take advantage of it */ - sha1_result(&sha1_context, (uint8 *) to); + mysql_sha1_result(&sha1_context, (uint8 *) to); my_crypt(to, (const uchar *) to, hash_stage1, SCRAMBLE_LENGTH); } @@ -477,17 +477,17 @@ check_scramble(const char *scramble, const char *message, uint8 buf[SHA1_HASH_SIZE]; uint8 hash_stage2_reassured[SHA1_HASH_SIZE]; - sha1_reset(&sha1_context); + mysql_sha1_reset(&sha1_context); /* create key to encrypt scramble */ - sha1_input(&sha1_context, (const uint8 *) message, SCRAMBLE_LENGTH); - sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE); - sha1_result(&sha1_context, buf); + mysql_sha1_input(&sha1_context, (const uint8 *) message, SCRAMBLE_LENGTH); + mysql_sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE); + mysql_sha1_result(&sha1_context, buf); /* encrypt scramble */ my_crypt((char *) buf, buf, (const uchar *) scramble, SCRAMBLE_LENGTH); /* now buf supposedly contains hash_stage1: so we can get hash_stage2 */ - sha1_reset(&sha1_context); - sha1_input(&sha1_context, buf, SHA1_HASH_SIZE); - sha1_result(&sha1_context, hash_stage2_reassured); + mysql_sha1_reset(&sha1_context); + mysql_sha1_input(&sha1_context, buf, SHA1_HASH_SIZE); + mysql_sha1_result(&sha1_context, hash_stage2_reassured); return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE); } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 0ee83424d9f..c1847d010c5 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1371,7 +1371,8 @@ find_acl_user(const char *host, const char *user, my_bool exact) acl_user->user && !strcmp(user,acl_user->user)) { if (exact ? !my_strcasecmp(&my_charset_latin1, host, - acl_user->host.hostname) : + acl_user->host.hostname ? + acl_user->host.hostname : "") : compare_hostname(&acl_user->host,host,host)) { DBUG_RETURN(acl_user); @@ -1988,14 +1989,15 @@ static GRANT_TABLE *table_hash_search(const char *host,const char* ip, char helping [NAME_LEN*2+USERNAME_LENGTH+3]; uint len; GRANT_TABLE *grant_table,*found=0; + HASH_SEARCH_STATE state; len = (uint) (strmov(strmov(strmov(helping,user)+1,db)+1,tname)-helping)+ 1; - for (grant_table=(GRANT_TABLE*) hash_search(&column_priv_hash, - (byte*) helping, - len) ; + for (grant_table=(GRANT_TABLE*) hash_first(&column_priv_hash, + (byte*) helping, + len, &state) ; grant_table ; grant_table= (GRANT_TABLE*) hash_next(&column_priv_hash,(byte*) helping, - len)) + len, &state)) { if (exact) { @@ -3604,7 +3606,7 @@ ACL_USER *check_acl_user(LEX_USER *user_name, if (!(user=acl_user->user)) user= ""; if (!(host=acl_user->host.hostname)) - host= "%"; + host= ""; if (!strcmp(user_name->user.str,user) && !my_strcasecmp(system_charset_info, user_name->host.str, host)) break; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8b1fa754929..ea013bb4e1e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -799,6 +799,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, reg1 TABLE *table; char key[MAX_DBKEY_LENGTH]; uint key_length; + HASH_SEARCH_STATE state; DBUG_ENTER("open_table"); /* find a unused table in the open table cache */ @@ -863,9 +864,11 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, /* close handler tables which are marked for flush */ mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE); - for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; + for (table= (TABLE*) hash_first(&open_cache, (byte*) key, key_length, + &state); table && table->in_use ; - table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) + table= (TABLE*) hash_next(&open_cache, (byte*) key, key_length, + &state)) { if (table->version != refresh_version) { @@ -1009,10 +1012,20 @@ TABLE *find_locked_table(THD *thd, const char *db,const char *table_name) /**************************************************************************** -** Reopen an table because the definition has changed. The date file for the -** table is already closed. -** Returns 0 if ok. -** If table can't be reopened, the entry is unchanged. + Reopen an table because the definition has changed. The date file for the + table is already closed. + + SYNOPSIS + reopen_table() + table Table to be opened + locked 1 if we have already a lock on LOCK_open + + NOTES + table->query_id will be 0 if table was reopened + + RETURN + 0 ok + 1 error ('table' is unchanged if table couldn't be reopened) ****************************************************************************/ bool reopen_table(TABLE *table,bool locked) @@ -1082,8 +1095,10 @@ bool reopen_table(TABLE *table,bool locked) (*field)->table_name=table->table_name; } for (key=0 ; key < table->keys ; key++) + { for (part=0 ; part < table->key_info[key].usable_key_parts ; part++) table->key_info[key].key_part[part].field->table= table; + } VOID(pthread_cond_broadcast(&COND_refresh)); error=0; @@ -1236,12 +1251,14 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock) { do { + HASH_SEARCH_STATE state; char *key= table->table_cache_key; uint key_length=table->key_length; - for (TABLE *search=(TABLE*) hash_search(&open_cache, - (byte*) key,key_length) ; + for (TABLE *search= (TABLE*) hash_first(&open_cache, (byte*) key, + key_length, &state); search ; - search = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) + search= (TABLE*) hash_next(&open_cache, (byte*) key, + key_length, &state)) { if (search->locked_by_flush || search->locked_by_name && wait_for_name_lock || @@ -2958,11 +2975,14 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1; for (;;) { + HASH_SEARCH_STATE state; result= signalled= 0; - for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; + for (table= (TABLE*) hash_first(&open_cache, (byte*) key, key_length, + &state); table; - table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) + table= (TABLE*) hash_next(&open_cache, (byte*) key, key_length, + &state)) { THD *in_use; table->version=0L; /* Free when thread is ready */ diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index b40257511f7..457478e90db 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -2873,6 +2873,7 @@ my_bool Query_cache::move_by_type(byte **border, } case Query_cache_block::TABLE: { + HASH_SEARCH_STATE record_idx; DBUG_PRINT("qcache", ("block 0x%lx TABLE", (ulong) block)); if (*border == 0) break; @@ -2890,7 +2891,7 @@ my_bool Query_cache::move_by_type(byte **border, byte *key; uint key_length; key=query_cache_table_get_key((byte*) block, &key_length, 0); - hash_search(&tables, (byte*) key, key_length); + hash_first(&tables, (byte*) key, key_length, &record_idx); block->destroy(); new_block->init(len); @@ -2924,7 +2925,7 @@ my_bool Query_cache::move_by_type(byte **border, /* Fix pointer to table name */ new_block->table()->table(new_block->table()->db() + tablename_offset); /* Fix hash to point at moved block */ - hash_replace(&tables, tables.current_record, (byte*) new_block); + hash_replace(&tables, &record_idx, (byte*) new_block); DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx", len, (ulong) new_block, (ulong) *border)); @@ -2932,6 +2933,7 @@ my_bool Query_cache::move_by_type(byte **border, } case Query_cache_block::QUERY: { + HASH_SEARCH_STATE record_idx; DBUG_PRINT("qcache", ("block 0x%lx QUERY", (ulong) block)); if (*border == 0) break; @@ -2949,7 +2951,7 @@ my_bool Query_cache::move_by_type(byte **border, byte *key; uint key_length; key=query_cache_query_get_key((byte*) block, &key_length, 0); - hash_search(&queries, (byte*) key, key_length); + hash_first(&queries, (byte*) key, key_length, &record_idx); // Move table of used tables memmove((char*) new_block->table(0), (char*) block->table(0), ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table))); @@ -3017,7 +3019,7 @@ my_bool Query_cache::move_by_type(byte **border, net->query_cache_query= (gptr) new_block; } /* Fix hash to point at moved block */ - hash_replace(&queries, queries.current_record, (byte*) new_block); + hash_replace(&queries, &record_idx, (byte*) new_block); DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx", len, (ulong) new_block, (ulong) *border)); break; diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 12acf344c31..1c5381a9fa0 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -384,27 +384,6 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' tab %p", hash_tables->db, hash_tables->real_name, hash_tables->alias, table)); - /* Table might have been flushed. */ - if (table && (table->version != refresh_version)) - { - /* - We must follow the thd->handler_tables chain, as we need the - address of the 'next' pointer referencing this table - for close_thread_table(). - */ - for (table_ptr= &(thd->handler_tables); - *table_ptr && (*table_ptr != table); - table_ptr= &(*table_ptr)->next) - {} - VOID(pthread_mutex_lock(&LOCK_open)); - if (close_thread_table(thd, table_ptr)) - { - /* Tell threads waiting for refresh that something has happened */ - VOID(pthread_cond_broadcast(&COND_refresh)); - } - VOID(pthread_mutex_unlock(&LOCK_open)); - table= hash_tables->table= NULL; - } if (!table) { /* @@ -451,9 +430,21 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, } tables->table=table; - if (cond && ((!cond->fixed && - cond->fix_fields(thd, tables, &cond)) || cond->check_cols(1))) - goto err0; + HANDLER_TABLES_HACK(thd); + lock= mysql_lock_tables(thd, &tables->table, 1, 0); + HANDLER_TABLES_HACK(thd); + + if (!lock) + goto err0; // mysql_lock_tables() printed error message already + + if (cond) + { + if (table->query_id != thd->query_id) + cond->cleanup(); // File was reopened + if ((!cond->fixed && + cond->fix_fields(thd, tables, &cond)) || cond->check_cols(1)) + goto err0; + } if (keyname) { @@ -471,13 +462,6 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, select_limit+=offset_limit; protocol->send_fields(&list,1); - HANDLER_TABLES_HACK(thd); - lock= mysql_lock_tables(thd, &tables->table, 1, 0); - HANDLER_TABLES_HACK(thd); - - if (!lock) - goto err0; // mysql_lock_tables() printed error message already - /* In ::external_lock InnoDB resets the fields which tell it that the handle is used in the HANDLER interface. Tell it again that diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5e29c98e2c8..74677a81ad3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -287,7 +287,7 @@ JOIN::prepare(Item ***rref_pointer_array, if (having_fix_rc || thd->net.report_error) DBUG_RETURN(-1); /* purecov: inspected */ if (having->with_sum_func) - having->split_sum_func(thd, ref_pointer_array, all_fields); + having->split_sum_func2(thd, ref_pointer_array, all_fields, &having); } // Is it subselect @@ -5292,7 +5292,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, *(reg_field++) =new_field; } if (!--hidden_field_count) + { hidden_null_count=null_count; + /* + We need to update hidden_field_count as we may have stored group + functions with constant arguments + */ + param->hidden_field_count= (uint) (reg_field - table->field); + } } DBUG_ASSERT(field_count >= (uint) (reg_field - table->field)); field_count= (uint) (reg_field - table->field); @@ -5488,7 +5495,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, } } - if (distinct) + if (distinct && field_count != param->hidden_field_count) { /* Create an unique key or an unique constraint over all columns diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index f15e97de5be..2863b192f50 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -8635,6 +8635,41 @@ my_mb_wc_euc_kr(CHARSET_INFO *cs __attribute__((unused)), } +/* + Returns well formed length of a EUC-KR string. +*/ +static uint +my_well_formed_len_euckr(CHARSET_INFO *cs __attribute__((unused)), + const char *b, const char *e, + uint pos, int *error) +{ + const char *b0= b; + const char *emb= e - 1; /* Last possible end of an MB character */ + + *error= 0; + while (pos-- && b < e) + { + if ((uchar) b[0] < 128) + { + /* Single byte ascii character */ + b++; + } + else if (b < emb && iseuc_kr(*b) && iseuc_kr(b[1])) + { + /* Double byte character */ + b+= 2; + } + else + { + /* Wrong byte sequence */ + *error= 1; + break; + } + } + return (uint) (b - b0); +} + + static MY_COLLATION_HANDLER my_collation_ci_handler = { NULL, /* init */ @@ -8655,7 +8690,7 @@ static MY_CHARSET_HANDLER my_charset_handler= mbcharlen_euc_kr, my_numchars_mb, my_charpos_mb, - my_well_formed_len_mb, + my_well_formed_len_euckr, my_lengthsp_8bit, my_numcells_8bit, my_mb_wc_euc_kr, /* mb_wc */ diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index 0cbad2d1c55..52dd61a8462 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -5686,6 +5686,41 @@ my_mb_wc_gb2312(CHARSET_INFO *cs __attribute__((unused)), } +/* + Returns well formed length of a EUC-KR string. +*/ +static uint +my_well_formed_len_gb2312(CHARSET_INFO *cs __attribute__((unused)), + const char *b, const char *e, + uint pos, int *error) +{ + const char *b0= b; + const char *emb= e - 1; /* Last possible end of an MB character */ + + *error= 0; + while (pos-- && b < e) + { + if ((uchar) b[0] < 128) + { + /* Single byte ascii character */ + b++; + } + else if (b < emb && isgb2312head(*b) && isgb2312tail(b[1])) + { + /* Double byte character */ + b+= 2; + } + else + { + /* Wrong byte sequence */ + *error= 1; + break; + } + } + return (uint) (b - b0); +} + + static MY_COLLATION_HANDLER my_collation_ci_handler = { NULL, /* init */ @@ -5706,7 +5741,7 @@ static MY_CHARSET_HANDLER my_charset_handler= mbcharlen_gb2312, my_numchars_mb, my_charpos_mb, - my_well_formed_len_mb, + my_well_formed_len_gb2312, my_lengthsp_8bit, my_numcells_8bit, my_mb_wc_gb2312, /* mb_wc */