diff --git a/configure.in b/configure.in index c0fa597dde5..a4daa5c2611 100644 --- a/configure.in +++ b/configure.in @@ -443,33 +443,33 @@ PS=$ac_cv_path_PS # Linux style if $PS p $$ 2> /dev/null | grep $0 > /dev/null then - FIND_PROC="$PS p \$\$PID | grep \$\$MYSQLD > /dev/null" + FIND_PROC="$PS p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null" # Solaris elif $PS -fp $$ 2> /dev/null | grep $0 > /dev/null then - FIND_PROC="$PS -p \$\$PID | grep \$\$MYSQLD > /dev/null" + FIND_PROC="$PS -p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null" # BSD style elif $PS -uaxww 2> /dev/null | grep $0 > /dev/null then - FIND_PROC="$PS -uaxww | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -uaxww | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null" # SysV style elif $PS -ef 2> /dev/null | grep $0 > /dev/null then - FIND_PROC="$PS -ef | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -ef | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null" # Do anybody use this? elif $PS $$ 2> /dev/null | grep $0 > /dev/null then - FIND_PROC="$PS \$\$PID | grep \$\$MYSQLD > /dev/null" + FIND_PROC="$PS \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null" else case $SYSTEM_TYPE in *freebsd*) - FIND_PROC="$PS p \$\$PID | grep \$\$MYSQLD > /dev/null" + FIND_PROC="$PS p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null" ;; *darwin*) - FIND_PROC="$PS -uaxww | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -uaxww | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null" ;; *cygwin*) - FIND_PROC="$PS -e | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -e | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null" ;; *netware*) FIND_PROC= diff --git a/extra/yassl/taocrypt/include/types.hpp b/extra/yassl/taocrypt/include/types.hpp index 85e2f85d3dd..9c5d3e4b194 100644 --- a/extra/yassl/taocrypt/include/types.hpp +++ b/extra/yassl/taocrypt/include/types.hpp @@ -68,8 +68,9 @@ typedef unsigned int word32; // TODO: FIXME, add asm multiply for x86_64 on Solaris and remove !__sun -#if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \ - defined(__mips64) || (defined(__x86_64__) && !defined(__sun)) +#if defined(__alpha__) || (defined(__ia64__) && !defined(__INTEL_COMPILER)) || \ + defined(_ARCH_PPC64) || defined(__mips64) || \ + (defined(__x86_64__) && !defined(__sun)) // These platforms have 64-bit CPU registers. Unfortunately most C++ compilers // don't allow any way to access the 64-bit by 64-bit multiply instruction // without using assembly, so in order to use word64 as word, the assembly diff --git a/include/my_global.h b/include/my_global.h index 195d208c93b..04d33be38b4 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -285,13 +285,7 @@ C_MODE_END # endif #endif /* TIME_WITH_SYS_TIME */ #ifdef HAVE_UNISTD_H -#if defined(HAVE_OPENSSL) && !defined(__FreeBSD__) && !defined(NeXT) && !defined(__OpenBSD__) && !defined(__APPLE__) -#define crypt unistd_crypt -#endif #include -#ifdef HAVE_OPENSSL -#undef crypt -#endif #endif #if defined(__cplusplus) && defined(NO_CPLUSPLUS_ALLOCA) #undef HAVE_ALLOCA diff --git a/mysql-test/r/analyze.result b/mysql-test/r/analyze.result new file mode 100644 index 00000000000..0b44a502b13 --- /dev/null +++ b/mysql-test/r/analyze.result @@ -0,0 +1,32 @@ +create table t1 (a bigint); +lock tables t1 write; +insert into t1 values(0); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +unlock tables; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; +create table t1 (a bigint); +insert into t1 values(0); +lock tables t1 write; +delete from t1; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +unlock tables; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; +create table t1 (a bigint); +insert into t1 values(0); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 9d96cef345f..d622127e8f0 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -596,3 +596,9 @@ ERROR 42000: Incorrect database name 'xyz' create table t1(t1.name int); create table t2(test.t2.name int); drop table t1,t2; +create database mysqltest; +use mysqltest; +drop database mysqltest; +create table test.t1 like x; +ERROR 42000: Incorrect database name 'NULL' +drop table if exists test.t1; diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index e4889289c18..c7674c57c8d 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -143,3 +143,6 @@ select format(col2,6) from t1 where col1=7; format(col2,6) 1,234,567,890,123,456.123450 drop table t1; +select round(150, 2); +round(150, 2) +150.00 diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result index d2750fd5a43..22304c4a93d 100644 --- a/mysql-test/r/heap.result +++ b/mysql-test/r/heap.result @@ -696,3 +696,8 @@ drop table t1; create table t1 (a int not null, b int not null auto_increment, primary key(a, b)) engine=heap; ERROR 42000: Incorrect table definition; there can be only one auto column and it must be defined as a key +create table t1 (c char(255), primary key(c(90))); +insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); +insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); +ERROR 23000: Duplicate entry 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl' for key 1 +drop table t1; diff --git a/mysql-test/r/innodb_handler.result b/mysql-test/r/innodb_handler.result index 7f4960ffa35..7e853a55e37 100644 --- a/mysql-test/r/innodb_handler.result +++ b/mysql-test/r/innodb_handler.result @@ -132,6 +132,22 @@ a b handler t2 read last; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 handler t2 close; +handler t1 open; +handler t1 read a next; +a b +14 aaa +handler t1 read a next; +a b +15 bbb +handler t1 close; +handler t1 open; +handler t1 read a prev; +a b +22 iii +handler t1 read a prev; +a b +21 hhh +handler t1 close; handler t1 open as t2; handler t2 read first; a b diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index 98e8851bb7e..3ad8571aadd 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -329,3 +329,28 @@ ERROR 42S21: Duplicate column name 'c1' alter table t1 add key (c1,c1,c2); ERROR 42S21: Duplicate column name 'c1' drop table t1; +create table t1 (a varchar(10), b varchar(10), key(a(10),b(10))); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(10) default NULL, + `b` varchar(10) default NULL, + KEY `a` (`a`,`b`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t1 modify b varchar(20); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(10) default NULL, + `b` varchar(20) default NULL, + KEY `a` (`a`,`b`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t1 modify a varchar(20); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(20) default NULL, + `b` varchar(20) default NULL, + KEY `a` (`a`,`b`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index eaed7719673..1c0321ac658 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2682,3 +2682,20 @@ AND FK_firma_id = 2; COUNT(*) 0 drop table t1; +CREATE TABLE t1 (a int); +CREATE TABLE t2 (a int); +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +INSERT INTO t2 VALUES (2), (4), (6); +SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a; +a +2 +4 +EXPLAIN SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where +EXPLAIN SELECT t1.a FROM t1 INNER JOIN t2 ON t1.a=t2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where +DROP TABLE t1,t2; diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index 09adc48259c..c5ba4d15a50 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -138,6 +138,8 @@ t1 CREATE TABLE `t1` ( `min_num` decimal(7,6) default '0.000001' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1 ; +set @@SQL_MODE=NULL; +ERROR 42000: Variable 'sql_mode' can't be set to the value of 'NULL' SET @OLD_SQL_MODE=@@SQL_MODE, @@SQL_MODE=''; show local variables like 'SQL_MODE'; Variable_name Value diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index c0693d1585c..b406dbab82f 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -896,6 +896,14 @@ create table t1( d1 decimal(18) unsigned, d2 decimal(20) unsigned, d3 decimal (2 insert into t1 values(1,-1,-1); ERROR 22003: Out of range value adjusted for column 'd2' at row 1 drop table t1; +create table t1 (col1 decimal(5,2), col2 numeric(5,2)); +insert into t1 values (999.999,999.999); +ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +insert into t1 values (-999.999,-999.999); +ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +select * from t1; +col1 col2 +drop table t1; set sql_mode=''; set @sav_dpi= @@div_precision_increment; set @@div_precision_increment=15; diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result index 3bd7fe6b175..e3b12cc36e3 100644 --- a/mysql-test/r/type_varchar.result +++ b/mysql-test/r/type_varchar.result @@ -126,13 +126,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 258 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 258 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 258 NULL 2 Using where; Using index alter table t1 change v v varchar(256); select * from t1 where v like 'This is a test' order by v; v @@ -150,13 +150,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 259 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 259 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 259 NULL 2 Using where; Using index alter table t1 change v v varchar(257); select * from t1 where v like 'This is a test' order by v; v @@ -174,13 +174,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 260 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 260 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 260 NULL 2 Using where; Using index alter table t1 change v v varchar(258); select * from t1 where v like 'This is a test' order by v; v @@ -198,13 +198,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 261 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 261 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 261 NULL 2 Using where; Using index alter table t1 change v v varchar(259); select * from t1 where v like 'This is a test' order by v; v @@ -222,13 +222,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 262 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 262 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 262 NULL 2 Using where; Using index alter table t1 change v v varchar(258); select * from t1 where v like 'This is a test' order by v; v @@ -246,13 +246,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 261 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 261 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 261 NULL 2 Using where; Using index alter table t1 change v v varchar(257); select * from t1 where v like 'This is a test' order by v; v @@ -270,13 +270,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 260 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 260 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 260 NULL 2 Using where; Using index alter table t1 change v v varchar(256); select * from t1 where v like 'This is a test' order by v; v @@ -294,13 +294,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 259 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 259 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 259 NULL 2 Using where; Using index alter table t1 change v v varchar(255); select * from t1 where v like 'This is a test' order by v; v @@ -318,13 +318,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 258 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 258 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 258 NULL 2 Using where; Using index alter table t1 change v v varchar(254); select * from t1 where v like 'This is a test' order by v; v @@ -392,3 +392,26 @@ group by t1.b, t1.a; a b min(t1.b) 22 NULL NULL drop table t1, t2; +create table t1 (f1 varchar(65500)); +create index index1 on t1(f1(10)); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` varchar(65500) default NULL, + KEY `index1` (`f1`(10)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t1 modify f1 varchar(255); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` varchar(255) default NULL, + KEY `index1` (`f1`(10)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t1 modify f1 tinytext; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` tinytext, + KEY `index1` (`f1`(10)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/t/analyze.test b/mysql-test/t/analyze.test new file mode 100644 index 00000000000..faf30279c68 --- /dev/null +++ b/mysql-test/t/analyze.test @@ -0,0 +1,39 @@ +# +# Bug #10901 Analyze Table on new table destroys table +# This is minimal test case to get error +# The problem was that analyze table wrote the shared state to the file and this +# didn't include the inserts while locked. A check was needed to ensure that +# state information was not updated when executing analyze table for a locked table. +# The analyze table had to be within locks and check table had to be after unlocking +# since then it brings the wrong state from disk rather than from the currently +# correct internal state. The insert is needed since it changes the file state, +# number of records. +# The fix is to synchronise the state of the shared state and the current state before +# calling mi_state_info_write +# +create table t1 (a bigint); +lock tables t1 write; +insert into t1 values(0); +analyze table t1; +unlock tables; +check table t1; + +drop table t1; + +create table t1 (a bigint); +insert into t1 values(0); +lock tables t1 write; +delete from t1; +analyze table t1; +unlock tables; +check table t1; + +drop table t1; + +create table t1 (a bigint); +insert into t1 values(0); +analyze table t1; +check table t1; + +drop table t1; + diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 487fa2ea76b..d870ff368d3 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -503,3 +503,14 @@ create table t1(t1.name int); create table t2(test.t2.name int); drop table t1,t2; +# +# Bug#11028: Crash on create table like +# +create database mysqltest; +use mysqltest; +drop database mysqltest; +--error 1102 +create table test.t1 like x; +--disable_warnings +drop table if exists test.t1; +--enable_warnings diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index b21f38052b6..03057af6911 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -79,3 +79,8 @@ insert into t1 values(7,1234567890123456.12345); select format(col2,6) from t1 where col1=7; drop table t1; + +# +# Bug #10083 (round doesn't increase decimals) +# +select round(150, 2); diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test index 68a84e1c193..75ef5a73cb0 100644 --- a/mysql-test/t/heap.test +++ b/mysql-test/t/heap.test @@ -426,3 +426,12 @@ drop table t1; --error 1075 create table t1 (a int not null, b int not null auto_increment, primary key(a, b)) engine=heap; + +# +# Bug #10566: Verify that we can create a prefixed key with length > 255 +# +create table t1 (c char(255), primary key(c(90))); +insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); +--error 1062 +insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); +drop table t1; diff --git a/mysql-test/t/innodb_handler.test b/mysql-test/t/innodb_handler.test index e8c486caf66..65728519e7b 100644 --- a/mysql-test/t/innodb_handler.test +++ b/mysql-test/t/innodb_handler.test @@ -69,6 +69,16 @@ handler t2 read next; handler t2 read last; handler t2 close; +handler t1 open; +handler t1 read a next; # this used to crash as a bug#5373 +handler t1 read a next; +handler t1 close; + +handler t1 open; +handler t1 read a prev; # this used to crash as a bug#5373 +handler t1 read a prev; +handler t1 close; + handler t1 open as t2; handler t2 read first; alter table t1 engine=innodb; diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index af3509c8454..9db1523be51 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -324,3 +324,16 @@ alter table t1 add key (c1,c2,c1); --error 1060 alter table t1 add key (c1,c1,c2); drop table t1; + +# +# If we use a partial field for a key that is actually the length of the +# field, and we extend the field, we end up with a key that includes the +# whole new length of the field. +# +create table t1 (a varchar(10), b varchar(10), key(a(10),b(10))); +show create table t1; +alter table t1 modify b varchar(20); +show create table t1; +alter table t1 modify a varchar(20); +show create table t1; +drop table t1; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index b6132d23d02..372325c4cbd 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2255,3 +2255,19 @@ AND FK_firma_id = 2; drop table t1; +# +# Test for bug #10084: STRAIGHT_JOIN with ON expression +# + +CREATE TABLE t1 (a int); +CREATE TABLE t2 (a int); +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +INSERT INTO t2 VALUES (2), (4), (6); + +SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a; + +EXPLAIN SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a; +EXPLAIN SELECT t1.a FROM t1 INNER JOIN t2 ON t1.a=t2.a; + +DROP TABLE t1,t2; + diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test index e80752eb71b..6a0c4aecada 100644 --- a/mysql-test/t/sql_mode.test +++ b/mysql-test/t/sql_mode.test @@ -80,6 +80,11 @@ create table t1 ( min_num dec(6,6) default .000001); show create table t1; drop table t1 ; +# +# Bug #10732: Set SQL_MODE to NULL gives garbled error message +# +--error 1231 +set @@SQL_MODE=NULL; # # test for diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index d1d595285a2..6199bd34fa9 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -934,6 +934,13 @@ create table t1( d1 decimal(18) unsigned, d2 decimal(20) unsigned, d3 decimal (2 --error 1264 insert into t1 values(1,-1,-1); drop table t1; +create table t1 (col1 decimal(5,2), col2 numeric(5,2)); +--error 1264 +insert into t1 values (999.999,999.999); +--error 1264 +insert into t1 values (-999.999,-999.999); +select * from t1; +drop table t1; set sql_mode=''; # diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test index 2bffca6b889..1a3a93018a4 100644 --- a/mysql-test/t/type_varchar.test +++ b/mysql-test/t/type_varchar.test @@ -118,3 +118,15 @@ insert into t2 values (22), (22); select t1.a, t1.b, min(t1.b) from t1 inner join t2 ON t2.a = t1.a group by t1.b, t1.a; drop table t1, t2; + +# +# Bug #10543: convert varchar with index to text +# +create table t1 (f1 varchar(65500)); +create index index1 on t1(f1(10)); +show create table t1; +alter table t1 modify f1 varchar(255); +show create table t1; +alter table t1 modify f1 tinytext; +show create table t1; +drop table t1; diff --git a/mysys/default_modify.c b/mysys/default_modify.c index add4317bb56..721ca596428 100644 --- a/mysys/default_modify.c +++ b/mysys/default_modify.c @@ -37,22 +37,20 @@ #define NEWLINE_LEN 1 #endif +static char *add_option(char *dst, const char *option_value, + const char *option, int remove_option); + int modify_defaults_file(const char *file_location, const char *option, const char *option_value, const char *section_name, int remove_option) { FILE *cnf_file; MY_STAT file_stat; - char linebuff[BUFF_SIZE], tmp[BUFF_SIZE], *tmp_ptr, *src_ptr, *dst_ptr, - *file_buffer; - uint optlen, optval_len, sect_len; - my_bool in_section= FALSE; + char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer; + uint optlen, optval_len, sect_len, nr_newlines= 0; + my_bool in_section= FALSE, opt_applied= 0; DBUG_ENTER("modify_defaults_file"); - optlen= strlen(option); - optval_len= strlen(option_value); - sect_len= strlen(section_name); - if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0)))) DBUG_RETURN(2); @@ -60,12 +58,15 @@ int modify_defaults_file(const char *file_location, const char *option, if (my_fstat(fileno(cnf_file), &file_stat, MYF(0))) goto err; + optlen= strlen(option); + optval_len= strlen(option_value); + /* Reserve space to read the contents of the file and some more for the option we want to add. */ - if (!(file_buffer= (char*) my_malloc(sizeof(char)* - (file_stat.st_size + + if (!(file_buffer= (char*) my_malloc(sizeof(char) * + (file_stat.st_size + /* option name len */ optlen + /* reserve space for newline */ @@ -73,35 +74,44 @@ int modify_defaults_file(const char *file_location, const char *option, /* reserve for '=' char */ 1 + /* option value len */ - optval_len), MYF(MY_WME)))) + optval_len + + /* The ending zero plus some safety */ + FN_REFLEN), MYF(MY_WME)))) goto malloc_err; - for (dst_ptr= file_buffer, tmp_ptr= 0; - fgets(linebuff, BUFF_SIZE, cnf_file); ) + sect_len= strlen(section_name); + + for (dst_ptr= file_buffer; fgets(linebuff, BUFF_SIZE, cnf_file); ) { /* Skip over whitespaces */ for (src_ptr= linebuff; my_isspace(&my_charset_latin1, *src_ptr); src_ptr++) {} - if (in_section && !strncmp(src_ptr, option, optlen) && + if (!*src_ptr) /* Empty line */ + { + nr_newlines++; + continue; + } + + if (!opt_applied && in_section && !strncmp(src_ptr, option, optlen) && (*(src_ptr + optlen) == '=' || my_isspace(&my_charset_latin1, *(src_ptr + optlen)) || *(src_ptr + optlen) == '\0')) { - /* The option under modifying was found in this section. Apply new. */ - if (!remove_option) - dst_ptr= strmov(dst_ptr, tmp); - tmp_ptr= 0; /* To mark that we have already applied this */ + dst_ptr= add_option(dst_ptr, option_value, option, remove_option); + opt_applied= 1; } else { /* If going to new group and we have option to apply, do it now */ - if (tmp_ptr && *src_ptr == '[') + if (in_section && !opt_applied && *src_ptr == '[') { - dst_ptr= strmov(dst_ptr, tmp); - tmp_ptr= 0; + dst_ptr= add_option(dst_ptr, option_value, option, remove_option); + } + for (; nr_newlines; nr_newlines--) + dst_ptr= strmov(dst_ptr, NEWLINE); dst_ptr= strmov(dst_ptr, linebuff); } /* Look for a section */ @@ -117,43 +127,38 @@ int modify_defaults_file(const char *file_location, const char *option, if (*src_ptr != ']') continue; /* Missing closing parenthesis. Assume this was no group */ - in_section= TRUE; - /* add option */ - if (!remove_option) - { - tmp_ptr= strmov(tmp, option); - if (*option_value) - { - *tmp_ptr++= '='; - tmp_ptr= strmov(tmp_ptr, option_value); - } - /* add a newline */ - strmov(tmp_ptr, NEWLINE); - } } else in_section= FALSE; /* mark that this section is of no interest to us */ } } - /* File ended. New option still remains to apply at the end */ - if (tmp_ptr) + /* File ended. */ + if (!opt_applied && !remove_option && in_section) { + /* New option still remains to apply at the end */ if (*(dst_ptr - 1) != '\n') - *dst_ptr++= '\n'; - dst_ptr= strmov(dst_ptr, tmp); + dst_ptr= strmov(dst_ptr, NEWLINE); + dst_ptr= add_option(dst_ptr, option_value, option, remove_option); + opt_applied= 1; } + for (; nr_newlines; nr_newlines--) + dst_ptr= strmov(dst_ptr, NEWLINE); - if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0, - MYF(MY_WME)) || - my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) || - my_fwrite(cnf_file, file_buffer, (uint) (dst_ptr - file_buffer), - MYF(MY_NABP)) || - my_fclose(cnf_file, MYF(MY_WME))) - goto err; + if (opt_applied) + { + /* Don't write the file if there are no changes to be made */ + if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0, + MYF(MY_WME)) || + my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) || + my_fwrite(cnf_file, file_buffer, (uint) (dst_ptr - file_buffer), + MYF(MY_NABP))) + goto err; + } + if (my_fclose(cnf_file, MYF(MY_WME))) + goto err; my_free(file_buffer, MYF(0)); - DBUG_RETURN(0); err: @@ -162,3 +167,21 @@ malloc_err: my_fclose(cnf_file, MYF(0)); DBUG_RETURN(1); /* out of resources */ } + + +static char *add_option(char *dst, const char *option_value, + const char *option, int remove_option) +{ + if (!remove_option) + { + dst= strmov(dst, option); + if (*option_value) + { + *dst++= '='; + dst= strmov(dst, option_value); + } + /* add a newline */ + dst= strmov(dst, NEWLINE); + } + return dst; +} diff --git a/mysys/hash.c b/mysys/hash.c index fe27b5fcb6d..28f8797288c 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -262,7 +262,25 @@ static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink) return; } - /* Compare a key in a record to a whole key. Return 0 if identical */ +/* + Compare a key in a record to a whole key. Return 0 if identical + + SYNOPSIS + hashcmp() + hash hash table + pos position of hash record to use in comparison + key key for comparison + length length of key + + NOTES: + If length is 0, comparison is done using the length of the + record being compared against. + + RETURN + < 0 key of record < key + = 0 key of record == key + > 0 key of record > key + */ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length) { @@ -270,7 +288,7 @@ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length) byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1); return ((length && length != rec_keylength) || my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength, - (uchar*) key, length)); + (uchar*) key, rec_keylength)); } diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index 3c6f1b15384..002e5ca0f06 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -158,32 +158,52 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) DBUG_RETURN(fd); } /* my_fdopen */ +/* + make_ftype + Make a filehandler-open-typestring from ordinary inputflags - /* Make a filehandler-open-typestring from ordinary inputflags */ - + Note: This routine attempts to find the best possible match + between a numeric option and a string option that could be + fed to fopen. There is not a 1 to 1 mapping between the two. + + r == O_RDONLY + w == O_WRONLY|O_TRUNC|O_CREAT + a == O_WRONLY|O_APPEND|O_CREAT + r+ == O_RDWR + w+ == O_RDWR|O_TRUNC|O_CREAT + a+ == O_RDWR|O_APPEND|O_CREAT +*/ static void make_ftype(register my_string to, register int flag) { -#if FILE_BINARY /* If we have binary-files */ +#if FILE_BINARY + /* If we have binary-files */ reg3 int org_flag=flag; -#endif - flag&= ~FILE_BINARY; /* remove binary bit */ - if (flag == O_RDONLY) - *to++= 'r'; - else if (flag == O_WRONLY) - *to++= 'w'; - else - { /* Add '+' after theese */ - if (flag == O_RDWR) +#endif + flag&= ~FILE_BINARY; /* remove binary bit */ + + /* check some possible invalid combinations */ + DBUG_ASSERT(flag & (O_TRUNC|O_APPEND) != O_TRUNC|O_APPEND); + + if (flag & (O_RDONLY|O_WRONLY) == O_WRONLY) + *to++= (flag & O_APPEND) ? 'a' : 'w'; + else if (flag & O_RDWR) + { + /* Add '+' after theese */ + if (flag & (O_TRUNC | O_CREAT)) + *to++= 'w'; + else if (flag & O_APPEND) + *to++= 'a'; + else *to++= 'r'; - else if (flag & O_APPEND) - *to++= 'a'; - else - *to++= 'w'; /* Create file */ - *to++= '+'; - } -#if FILE_BINARY /* If we have binary-files */ - if (org_flag & FILE_BINARY) + *to++= '+'; + } + else + *to++= 'r'; + +#if FILE_BINARY /* If we have binary-files */ + if (org_flag & FILE_BINARY) *to++='b'; -#endif +#endif *to='\0'; } /* make_ftype */ + diff --git a/sql/field.cc b/sql/field.cc index daa28887ee9..54d64136052 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -982,6 +982,39 @@ Item_result Field::result_merge_type(enum_field_types field_type) Static help functions *****************************************************************************/ + +/* + Check whether a field type can be partially indexed by a key + + This is a static method, rather than a virtual function, because we need + to check the type of a non-Field in mysql_alter_table(). + + SYNOPSIS + type_can_have_key_part() + type field type + + RETURN + TRUE Type can have a prefixed key + FALSE Type can not have a prefixed key +*/ + +bool Field::type_can_have_key_part(enum enum_field_types type) +{ + switch (type) { + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_STRING: + return TRUE; + default: + return FALSE; + } +} + + /* Numeric fields base class constructor */ diff --git a/sql/field.h b/sql/field.h index b99acd43123..b336b15b550 100644 --- a/sql/field.h +++ b/sql/field.h @@ -123,6 +123,7 @@ public: virtual Item_result result_type () const=0; virtual Item_result cmp_type () const { return result_type(); } virtual Item_result cast_to_int_type () const { return result_type(); } + static bool type_can_have_key_part(enum_field_types); static enum_field_types field_type_merge(enum_field_types, enum_field_types); static Item_result result_merge_type(enum_field_types); bool eq(Field *field) diff --git a/sql/ha_heap.h b/sql/ha_heap.h index 5d50270ec5b..2aa065e0d96 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -57,6 +57,7 @@ public: } const key_map *keys_to_use_for_scanning() { return &btree_keys; } uint max_supported_keys() const { return MAX_KEY; } + uint max_supported_key_part_length() const { return MAX_KEY_LENGTH; } double scan_time() { return (double) (records+deleted) / 20.0+10; } double read_time(uint index, uint ranges, ha_rows rows) { return (double) rows / 20.0+1; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 68292859504..c3fc537f04e 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1876,7 +1876,8 @@ void Item_func_round::fix_length_and_dec() max_length= float_length(decimals); break; case INT_RESULT: - if (truncate || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS)) + if ((decimals_to_set==0) && + (truncate || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))) { /* Here we can keep INT_RESULT */ hybrid_type= INT_RESULT; @@ -1890,18 +1891,12 @@ void Item_func_round::fix_length_and_dec() hybrid_type= DECIMAL_RESULT; int decimals_delta= args[0]->decimals - decimals_to_set; int precision= args[0]->decimal_precision(); - if (decimals_delta > 0) - { - int length_increase= truncate ? 0:1; - precision-= decimals_delta - length_increase; - decimals= decimals_to_set; - } - else - /* Decimals to set is bigger that the original scale */ - /* we keep original decimals value */ - decimals= args[0]->decimals; + int length_increase= ((decimals_delta <= 0) || truncate) ? 0:1; + + precision-= decimals_delta - length_increase; + decimals= decimals_to_set; max_length= my_decimal_precision_to_length(precision, decimals, - unsigned_flag); + unsigned_flag); break; } default: diff --git a/sql/log_event.cc b/sql/log_event.cc index 3b6b3cda0b4..08aedfb3f63 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -708,7 +708,7 @@ failed my_b_read")); Log_event *res= 0; #ifndef max_allowed_packet THD *thd=current_thd; - uint max_allowed_packet= thd ? thd->variables.max_allowed_packet : ~0; + uint max_allowed_packet= thd ? thd->variables.max_allowed_packet : ~(ulong)0; #endif if (data_len > max_allowed_packet) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 8359207905b..afa9129900c 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -838,7 +838,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length); void mysql_stmt_free(THD *thd, char *packet); void mysql_stmt_reset(THD *thd, char *packet); void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); -void reset_stmt_for_execute(THD *thd, LEX *lex); +void reinit_stmt_before_use(THD *thd, LEX *lex); void init_stmt_after_parse(THD*, LEX*); /* sql_handler.cc */ diff --git a/sql/set_var.cc b/sql/set_var.cc index 3f8c8ea2508..b22c0924de1 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1616,7 +1616,10 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names) if (var->value->result_type() == STRING_RESULT) { if (!(res= var->value->val_str(&str))) + { + strmake(buff, "NULL", 4); goto err; + } var->save_result.ulong_value= ((ulong) find_set(enum_names, res->c_ptr(), res->length(), diff --git a/sql/sp_head.cc b/sql/sp_head.cc index f3459e5b104..8ac9ed1a338 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1355,7 +1355,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, implemented at the same time as ability not to store LEX for instruction if it is not really used. */ - reset_stmt_for_execute(thd, m_lex); + reinit_stmt_before_use(thd, m_lex); /* If requested check whenever we have access to tables in LEX's table list diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 28b841435c8..32c769537a1 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -187,7 +187,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) ACL_HOST host; update_hostname(&host.host,get_field(&mem, table->field[0])); host.db= get_field(&mem, table->field[1]); - if (lower_case_table_names) + if (lower_case_table_names && host.db) { /* convert db to lower case and give a warning if the db wasn't @@ -209,7 +209,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) { sql_print_warning("'host' entry '%s|%s' " "ignored in --skip-name-resolve mode.", - host.host.hostname, host.db, host.host.hostname); + host.host.hostname, host.db?host.db:""); continue; } #ifndef TO_BE_REMOVED @@ -277,7 +277,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) { sql_print_warning("'user' entry '%s@%s' " "ignored in --skip-name-resolve mode.", - user.user, user.host.hostname, user.host.hostname); + user.user, user.host.hostname); continue; } @@ -413,7 +413,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) { sql_print_warning("'db' entry '%s %s@%s' " "ignored in --skip-name-resolve mode.", - db.db, db.user, db.host.hostname, db.host.hostname); + db.db, db.user, db.host.hostname); continue; } db.access=get_access(table,3); @@ -3232,7 +3232,7 @@ my_bool grant_init(THD *org_thd) sql_print_warning("'procs_priv' entry '%s %s@%s' " "ignored in --skip-name-resolve mode.", mem_check->tname, mem_check->user, - mem_check->host, mem_check->host); + mem_check->host); continue; } } @@ -5172,7 +5172,7 @@ bool mysql_revoke_all(THD *thd, List &list) grant_proc->db, grant_proc->tname, is_proc, - ~0, 1)) + ~(ulong)0, 1)) { revoked= 1; continue; @@ -5240,7 +5240,7 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, lex_user.host.length= strlen(grant_proc->host.hostname); if (!replace_routine_table(thd,grant_proc,tables[4].table,lex_user, grant_proc->db, grant_proc->tname, - is_proc, ~0, 1)) + is_proc, ~(ulong)0, 1)) { revoked= 1; continue; diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index aca53db0ec8..9356ee04c45 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -413,8 +413,6 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, cond->fix_fields(thd, tables, &cond)) || cond->check_cols(1))) goto err0; - table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it - if (keyname) { if ((keyno=find_type(keyname, &table->s->keynames, 1+2)-1)<0) @@ -422,8 +420,6 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), keyname, tables->alias); goto err0; } - table->file->ha_index_or_rnd_end(); - table->file->ha_index_init(keyno); } if (insert_fields(thd, tables, tables->db, tables->alias, &it, 0, 0)) @@ -449,9 +445,22 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, for (num_rows=0; num_rows < select_limit_cnt; ) { switch (mode) { + case RNEXT: + if (table->file->inited != handler::NONE) + { + error=keyname ? + table->file->index_next(table->record[0]) : + table->file->rnd_next(table->record[0]); + break; + } + /* else fall through */ case RFIRST: if (keyname) + { + table->file->ha_index_or_rnd_end(); + table->file->ha_index_init(keyno); error= table->file->index_first(table->record[0]); + } else { table->file->ha_index_or_rnd_end(); @@ -460,19 +469,20 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, } mode=RNEXT; break; - case RLAST: - DBUG_ASSERT(keyname != 0); - error= table->file->index_last(table->record[0]); - mode=RPREV; - break; - case RNEXT: - error= (keyname ? - table->file->index_next(table->record[0]) : - table->file->rnd_next(table->record[0])); - break; case RPREV: DBUG_ASSERT(keyname != 0); - error= table->file->index_prev(table->record[0]); + if (table->file->inited != handler::NONE) + { + error=table->file->index_prev(table->record[0]); + break; + } + /* else fall through */ + case RLAST: + DBUG_ASSERT(keyname != 0); + table->file->ha_index_or_rnd_end(); + table->file->ha_index_init(keyno); + error= table->file->index_last(table->record[0]); + mode=RPREV; break; case RNEXT_SAME: /* Continue scan on "(keypart1,keypart2,...)=(c1, c2, ...) */ @@ -508,6 +518,8 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, } if (!(key= (byte*) thd->calloc(ALIGN_SIZE(key_len)))) goto err; + table->file->ha_index_or_rnd_end(); + table->file->ha_index_init(keyno); key_copy(key, table->record[0], table->key_info + keyno, key_len); error= table->file->index_read(table->record[0], key,key_len,ha_rkey_mode); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index f1b3c69264c..37efd1d62b9 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1656,6 +1656,17 @@ static bool init_param_array(Prepared_statement *stmt) return FALSE; } + +/* Cleanup PS after execute/prepare and restore THD state */ + +static void cleanup_stmt_and_thd_after_use(Statement *stmt, THD *thd) +{ + stmt->lex->unit.cleanup(); + cleanup_items(stmt->free_list); + thd->rollback_item_tree_changes(); + thd->cleanup_after_query(); +} + /* Given a query string with parameter markers, create a Prepared Statement from it and send PS info back to the client. @@ -1760,12 +1771,9 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, thd->lex->sphead= NULL; } lex_end(lex); - lex->unit.cleanup(); close_thread_tables(thd); + cleanup_stmt_and_thd_after_use(stmt, thd); thd->restore_backup_statement(stmt, &thd->stmt_backup); - cleanup_items(stmt->free_list); - thd->rollback_item_tree_changes(); - thd->cleanup_after_query(); thd->current_arena= thd; if (error) @@ -1808,10 +1816,10 @@ void init_stmt_after_parse(THD *thd, LEX *lex) /* Reinit prepared statement/stored procedure before execution */ -void reset_stmt_for_execute(THD *thd, LEX *lex) +void reinit_stmt_before_use(THD *thd, LEX *lex) { SELECT_LEX *sl= lex->all_selects_list; - DBUG_ENTER("reset_stmt_for_execute"); + DBUG_ENTER("reinit_stmt_before_use"); if (lex->empty_field_list_on_rset) { @@ -2007,7 +2015,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) thd->stmt_backup.set_statement(thd); thd->set_statement(stmt); thd->current_arena= stmt; - reset_stmt_for_execute(thd, stmt->lex); + reinit_stmt_before_use(thd, stmt->lex); /* From now cursors assume that thd->mem_root is clean */ if (expanded_query.length() && alloc_query(thd, (char *)expanded_query.ptr(), @@ -2031,17 +2039,18 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) if (cursor && cursor->is_open()) { + /* + It's safer if we grab THD state after mysql_execute_command is + finished and not in Cursor::open(), because currently the call to + Cursor::open is buried deep in JOIN::exec of the top level join. + */ cursor->init_from_thd(thd); - cursor->state= stmt->state; } else { - thd->lex->unit.cleanup(); - cleanup_items(stmt->free_list); + close_thread_tables(thd); + cleanup_stmt_and_thd_after_use(stmt, thd); reset_stmt_params(stmt); - close_thread_tables(thd); /* to close derived tables */ - thd->rollback_item_tree_changes(); - thd->cleanup_after_query(); } thd->set_statement(&thd->stmt_backup); @@ -2119,7 +2128,7 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt, { DBUG_ENTER("execute_stmt"); - reset_stmt_for_execute(thd, stmt->lex); + reinit_stmt_before_use(thd, stmt->lex); if (expanded_query->length() && alloc_query(thd, (char *)expanded_query->ptr(), @@ -2141,14 +2150,11 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt, if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); - thd->lex->unit.cleanup(); - thd->current_arena= thd; - cleanup_items(stmt->free_list); - thd->rollback_item_tree_changes(); - reset_stmt_params(stmt); close_thread_tables(thd); // to close derived tables + cleanup_stmt_and_thd_after_use(stmt, thd); + reset_stmt_params(stmt); thd->set_statement(&thd->stmt_backup); - thd->cleanup_after_query(); + thd->current_arena= thd; if (stmt->state == Item_arena::PREPARED) stmt->state= Item_arena::EXECUTED; @@ -2171,7 +2177,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) /* assume there is always place for 8-16 bytes */ ulong stmt_id= uint4korr(packet); ulong num_rows= uint4korr(packet+4); - Statement *stmt; + Prepared_statement *stmt; DBUG_ENTER("mysql_stmt_fetch"); if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch"))) @@ -2185,7 +2191,6 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) thd->current_arena= stmt; thd->set_n_backup_statement(stmt, &thd->stmt_backup); - stmt->cursor->init_thd(thd); if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), QUERY_PRIOR); @@ -2197,11 +2202,16 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); - /* Restore THD state */ - stmt->cursor->reset_thd(thd); thd->restore_backup_statement(stmt, &thd->stmt_backup); thd->current_arena= thd; + if (!stmt->cursor->is_open()) + { + /* We're done with the fetch: reset PS for next execution */ + cleanup_stmt_and_thd_after_use(stmt, thd); + reset_stmt_params(stmt); + } + DBUG_VOID_RETURN; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 76fb05dac36..0aed2703ed3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1705,10 +1705,11 @@ Cursor::init_from_thd(THD *thd) We need to save and reset thd->mem_root, otherwise it'll be freed later in mysql_parse. - We can't just change the thd->mem_root here as we want to keep the things - that is already allocated in thd->mem_root for Cursor::fetch() + We can't just change the thd->mem_root here as we want to keep the + things that are already allocated in thd->mem_root for Cursor::fetch() */ main_mem_root= *thd->mem_root; + state= thd->current_arena->state; /* Allocate new memory root for thd */ init_sql_alloc(thd->mem_root, thd->variables.query_alloc_block_size, @@ -1731,24 +1732,6 @@ Cursor::init_from_thd(THD *thd) What problems can we have with it if cursor is open? TODO: must be fixed because of the prelocked mode. */ - /* - TODO: grab thd->free_list here? - */ -} - - -void -Cursor::init_thd(THD *thd) -{ - DBUG_ASSERT(thd->derived_tables == 0); - thd->derived_tables= derived_tables; - - DBUG_ASSERT(thd->open_tables == 0); - thd->open_tables= open_tables; - - DBUG_ASSERT(thd->lock== 0); - thd->lock= lock; - thd->query_id= query_id; } @@ -1824,6 +1807,13 @@ Cursor::fetch(ulong num_rows) DBUG_ENTER("Cursor::fetch"); DBUG_PRINT("enter",("rows: %lu", num_rows)); + DBUG_ASSERT(thd->derived_tables == 0 && thd->open_tables == 0 && + thd->lock == 0); + + thd->derived_tables= derived_tables; + thd->open_tables= open_tables; + thd->lock= lock; + thd->query_id= query_id; /* save references to memory, allocated during fetch */ thd->set_n_backup_item_arena(this, &thd->stmt_backup); @@ -1842,6 +1832,9 @@ Cursor::fetch(ulong num_rows) #endif thd->restore_backup_item_arena(this, &thd->stmt_backup); + DBUG_ASSERT(thd->free_list == 0); + reset_thd(thd); + if (error == NESTED_LOOP_CURSOR_LIMIT) { /* Fetch limit worked, possibly more rows are there */ @@ -1882,8 +1875,8 @@ Cursor::close() join->cleanup(); delete join; } - /* XXX: Another hack: closing tables used in the cursor */ { + /* XXX: Another hack: closing tables used in the cursor */ DBUG_ASSERT(lock || open_tables || derived_tables); TABLE *tmp_derived_tables= thd->derived_tables; diff --git a/sql/sql_select.h b/sql/sql_select.h index 49ac58e913b..5351bbb13d3 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -386,8 +386,6 @@ public: /* Temporary implementation as now we replace THD state by value */ /* Save THD state into cursor */ void init_from_thd(THD *thd); - /* Restore THD from cursor to continue cursor execution */ - void init_thd(THD *thd); /* bzero cursor state in THD */ void reset_thd(THD *thd); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 5e1e76e2a40..ff3e20a4cb3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2590,28 +2590,33 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char *db= table->db; char *table_name= table->table_name; - char *src_db= thd->db; + char *src_db; char *src_table= table_ident->table.str; int err; bool res= TRUE; TABLE_LIST src_tables_list; DBUG_ENTER("mysql_create_like_table"); + src_db= table_ident->db.str ? table_ident->db.str : thd->db; /* Validate the source table */ if (table_ident->table.length > NAME_LEN || (table_ident->table.length && - check_table_name(src_table,table_ident->table.length)) || - table_ident->db.str && check_db_name((src_db= table_ident->db.str))) + check_table_name(src_table,table_ident->table.length))) { my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table); DBUG_RETURN(TRUE); } + if (!src_db || check_db_name(src_db)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), src_db ? src_db : "NULL"); + DBUG_RETURN(-1); + } bzero((gptr)&src_tables_list, sizeof(src_tables_list)); - src_tables_list.db= table_ident->db.str ? table_ident->db.str : thd->db; - src_tables_list.table_name= table_ident->table.str; + src_tables_list.db= src_db; + src_tables_list.table_name= src_table; if (lock_and_wait_for_table_name(thd, &src_tables_list)) goto err; @@ -3394,12 +3399,25 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, continue; // Field is removed uint key_part_length=key_part->length; if (cfield->field) // Not new field - { // Check if sub key - if (cfield->field->type() != FIELD_TYPE_BLOB && - (cfield->field->pack_length() == key_part_length || - cfield->length <= key_part_length / - key_part->field->charset()->mbmaxlen)) - key_part_length=0; // Use whole field + { + /* + If the field can't have only a part used in a key according to its + new type, or should not be used partially according to its + previous type, or the field length is less than the key part + length, unset the key part length. + + We also unset the key part length if it is the same as the + old field's length, so the whole new field will be used. + + BLOBs may have cfield->length == 0, which is why we test it before + checking whether cfield->length < key_part_length (in chars). + */ + if (!Field::type_can_have_key_part(cfield->field->type()) || + !Field::type_can_have_key_part(cfield->sql_type) || + cfield->field->field_length == key_part_length || + (cfield->length && (cfield->length < key_part_length / + key_part->field->charset()->mbmaxlen))) + key_part_length= 0; // Use whole field } key_part_length /= key_part->field->charset()->mbmaxlen; key_parts.push_back(new key_part_spec(cfield->field_name, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4f8e31bd49e..ae215452c42 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5108,10 +5108,12 @@ derived_table_list: join_table: table_ref normal_join table_ref { TEST_ASSERT($1 && ($$=$3)); } - | table_ref STRAIGHT_JOIN table_factor - { TEST_ASSERT($1 && ($$=$3)); $3->straight=1; } + | table_ref STRAIGHT_JOIN table_ref + { TEST_ASSERT($1 && ($$=$3)); $3->straight=1; } | table_ref normal_join table_ref ON expr { TEST_ASSERT($1 && ($$=$3)); add_join_on($3,$5); } + | table_ref STRAIGHT_JOIN table_ref ON expr + { TEST_ASSERT($1 && ($$=$3)); $3->straight=1; add_join_on($3,$5); } | table_ref normal_join table_ref USING { diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 38f3ebaa20a..9e003a18dac 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -3871,6 +3871,14 @@ int update_state_info(MI_CHECK *param, MI_INFO *info,uint update) if (!share->state.create_time) share->state.create_time=share->state.check_time; } + /* + When tables are locked we haven't synched the share state and the + real state for a while so we better do it here before synching + the share state to disk. Only when table is write locked is it + necessary to perform this synch. + */ + if (info->lock_type == F_WRLCK) + share->state.state= *info->state; if (mi_state_info_write(share->kfile,&share->state,1+2)) goto err; share->changed=0; diff --git a/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp b/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp index 9750e1c5179..6f848d7fe16 100644 --- a/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp +++ b/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp @@ -247,10 +247,10 @@ Ndbfs::readWriteRequest(int action, Signal * signal) AsyncFile* openFile = theOpenFiles.find(filePointer); const NewVARIABLE *myBaseAddrRef = &getBat(blockNumber)[fsRWReq->varIndex]; - unsigned int tPageSize; - unsigned int tClusterSize; - unsigned int tNRR; - unsigned int tPageOffset; + UintPtr tPageSize; + UintPtr tClusterSize; + UintPtr tNRR; + UintPtr tPageOffset; char* tWA; FsRef::NdbfsErrorCodeType errorCode; @@ -294,8 +294,8 @@ Ndbfs::readWriteRequest(int action, Signal * signal) jam(); for (unsigned int i = 0; i < fsRWReq->numberOfPages; i++) { jam(); - const Uint32 varIndex = fsRWReq->data.listOfPair[i].varIndex; - const Uint32 fileOffset = fsRWReq->data.listOfPair[i].fileOffset; + const UintPtr varIndex = fsRWReq->data.listOfPair[i].varIndex; + const UintPtr fileOffset = fsRWReq->data.listOfPair[i].fileOffset; if (varIndex >= tNRR) { jam(); errorCode = FsRef::fsErrInvalidParameters; @@ -316,8 +316,8 @@ Ndbfs::readWriteRequest(int action, Signal * signal) errorCode = FsRef::fsErrInvalidParameters; goto error; }//if - const Uint32 varIndex = fsRWReq->data.arrayOfPages.varIndex; - const Uint32 fileOffset = fsRWReq->data.arrayOfPages.fileOffset; + const UintPtr varIndex = fsRWReq->data.arrayOfPages.varIndex; + const UintPtr fileOffset = fsRWReq->data.arrayOfPages.fileOffset; request->par.readWrite.pages[0].offset = fileOffset * tPageSize; request->par.readWrite.pages[0].size = tPageSize * fsRWReq->numberOfPages; @@ -334,7 +334,7 @@ Ndbfs::readWriteRequest(int action, Signal * signal) for (unsigned int i = 0; i < fsRWReq->numberOfPages; i++) { jam(); - Uint32 varIndex = fsRWReq->data.listOfMemPages.varIndex[i]; + UintPtr varIndex = fsRWReq->data.listOfMemPages.varIndex[i]; if (varIndex >= tNRR) { jam(); diff --git a/storage/ndb/test/run-test/ndb-autotest.sh b/storage/ndb/test/run-test/ndb-autotest.sh index 3ba4d1928d5..09087a8a8c7 100755 --- a/storage/ndb/test/run-test/ndb-autotest.sh +++ b/storage/ndb/test/run-test/ndb-autotest.sh @@ -13,7 +13,7 @@ save_args=$* VERSION="ndb-autotest.sh version 1.04" DATE=`date '+%Y-%m-%d'` -HOST=`hostname -s` +HOST=`hostname` export DATE HOST set -e @@ -330,7 +330,10 @@ start(){ tar cfz /tmp/res.$2.$$.tgz `basename $p2`/$DATE scp /tmp/res.$2.$$.tgz \ $result_host:$result_path/res.$DATE.$HOST.$2.$$.tgz - rm -f /tmp/res.$2.$$.tgz + if [ $? -eq 0 ] + then + rm -f /tmp/res.$2.$$.tgz + fi fi } diff --git a/strings/decimal.c b/strings/decimal.c index 787d00dcb46..4a487f3c9b0 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1546,6 +1546,14 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, *buf1=1; to->intg++; } + /* Here we check 999.9 -> 1000 case when we need to increase intg */ + else + { + int first_dig= to->intg % DIG_PER_DEC1; + /* first_dig==0 should be handled above in the 'if' */ + if (first_dig && (*buf1 >= powers10[first_dig])) + to->intg++; + } } else { diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 002076afd90..b6ca4996c70 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13145,6 +13145,67 @@ static void test_bug9643() myquery(rc); } +/* + Check that proper cleanups are done for prepared statement when + fetching thorugh a cursor. +*/ + +static void test_bug10729() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + char a[21]; + int rc; + const char *stmt_text; + int i= 0; + char *name_array[3]= { "aaa", "bbb", "ccc" }; + ulong type; + + myheader("test_bug10729"); + + mysql_query(mysql, "drop table if exists t1"); + mysql_query(mysql, "create table t1 (id integer not null primary key," + "name VARCHAR(20) NOT NULL)"); + rc= mysql_query(mysql, "insert into t1 (id, name) values " + "(1, 'aaa'), (2, 'bbb'), (3, 'ccc')"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + + type= (ulong) CURSOR_TYPE_READ_ONLY; + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type); + check_execute(stmt, rc); + stmt_text= "select name from t1"; + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + check_execute(stmt, rc); + + bzero(bind, sizeof(bind)); + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= (void*) a; + bind[0].buffer_length= sizeof(a); + mysql_stmt_bind_result(stmt, bind); + + for (i= 0; i < 3; i++) + { + int row_no= 0; + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + while ((rc= mysql_stmt_fetch(stmt)) == 0) + { + DIE_UNLESS(strcmp(a, name_array[row_no]) == 0); + if (!opt_silent) + printf("%d: %s\n", row_no, a); + ++row_no; + } + DIE_UNLESS(rc == MYSQL_NO_DATA); + } + rc= mysql_stmt_close(stmt); + DIE_UNLESS(rc == 0); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -13377,6 +13438,7 @@ static struct my_tests_st my_tests[]= { { "test_bug9520", test_bug9520 }, { "test_bug9478", test_bug9478 }, { "test_bug9643", test_bug9643 }, + { "test_bug10729", test_bug10729 }, { 0, 0 } };