diff --git a/configure.in b/configure.in index e366e5950e3..b06a60273cd 100644 --- a/configure.in +++ b/configure.in @@ -1688,6 +1688,30 @@ case "$with_atomic_ops" in *) AC_MSG_ERROR(["$with_atomic_ops" is not a valid value for --with-atomic-ops]) ;; esac +AC_CACHE_CHECK([whether the compiler provides atomic builtins], + [mysql_cv_gcc_atomic_builtins], [AC_TRY_RUN([ + int main() + { + int foo= -10; int bar= 10; + if (!__sync_fetch_and_add(&foo, bar) || foo) + return -1; + bar= __sync_lock_test_and_set(&foo, bar); + if (bar || foo != 10) + return -1; + bar= __sync_val_compare_and_swap(&bar, foo, 15); + if (bar) + return -1; + return 0; + } +], [mysql_cv_gcc_atomic_builtins=yes], + [mysql_cv_gcc_atomic_builtins=no], + [mysql_cv_gcc_atomic_builtins=no])]) + +if test "x$mysql_cv_gcc_atomic_builtins" = xyes; then + AC_DEFINE(HAVE_GCC_ATOMIC_BUILTINS, 1, + [Define to 1 if compiler provides atomic builtins.]) +fi + # Force static compilation to avoid linking problems/get more speed AC_ARG_WITH(mysqld-ldflags, [ --with-mysqld-ldflags Extra linking arguments for mysqld], diff --git a/include/Makefile.am b/include/Makefile.am index 8335da36e93..5975a3e8bf0 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -36,7 +36,7 @@ noinst_HEADERS = config-win.h config-netware.h \ mysql_version.h.in my_handler.h my_time.h \ my_vle.h my_user.h my_atomic.h atomic/nolock.h \ atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h \ - my_libwrap.h + atomic/gcc_builtins.h my_libwrap.h # Remove built files and the symlinked directories CLEANFILES = $(BUILT_SOURCES) readline openssl diff --git a/include/atomic/gcc_builtins.h b/include/atomic/gcc_builtins.h new file mode 100644 index 00000000000..509701b30a5 --- /dev/null +++ b/include/atomic/gcc_builtins.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2008 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#define make_atomic_add_body(S) \ + v= __sync_fetch_and_add(a, v); +#define make_atomic_swap_body(S) \ + v= __sync_lock_test_and_set(a, v); +#define make_atomic_cas_body(S) \ + int ## S sav; \ + sav= __sync_val_compare_and_swap(a, *cmp, set); \ + if (!(ret= (sav == *cmp))) *cmp= sav; + +#ifdef MY_ATOMIC_MODE_DUMMY +#define make_atomic_load_body(S) ret= *a +#define make_atomic_store_body(S) *a= v +#else +#define make_atomic_load_body(S) \ + ret= __sync_fetch_and_or(a, 0); +#define make_atomic_store_body(S) \ + (void) __sync_lock_test_and_set(a, v); +#endif diff --git a/include/atomic/nolock.h b/include/atomic/nolock.h index f15c8b13b7f..10ac17884b6 100644 --- a/include/atomic/nolock.h +++ b/include/atomic/nolock.h @@ -13,7 +13,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#if defined(__i386__) || defined(_M_IX86) +#if defined(__i386__) || defined(_M_IX86) || defined(HAVE_GCC_ATOMIC_BUILTINS) #ifdef MY_ATOMIC_MODE_DUMMY # define LOCK "" @@ -21,7 +21,9 @@ # define LOCK "lock" #endif -#ifdef __GNUC__ +#ifdef HAVE_GCC_ATOMIC_BUILTINS +#include "gcc_builtins.h" +#elif __GNUC__ #include "x86-gcc.h" #elif defined(_MSC_VER) #include "x86-msvc.h" diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index ef53f227ec0..e10bcba36c2 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -527,3 +527,23 @@ SELECT * FROM t1 WHERE a = INTERVAL(3,2,1) + 1; a b 3 1998-01-01 00:00:00 DROP TABLE t1; +DROP TABLE IF EXISTS t1,t2,t3; +CREATE TABLE t1 (a1 INT, a2 INT, a3 INT, a4 DATETIME); +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 LIKE t1; +SELECT t1.* FROM t1 AS t0, { OJ t2 INNER JOIN t1 ON (t1.a1=t2.a1) } WHERE t0.a3=2; +a1 a2 a3 a4 +SELECT t1.*,t2.* FROM { OJ ((t1 INNER JOIN t2 ON (t1.a1=t2.a2)) LEFT OUTER JOIN t3 ON t3.a3=t2.a1)}; +a1 a2 a3 a4 a1 a2 a3 a4 +SELECT t1.*,t2.* FROM { OJ ((t1 LEFT OUTER JOIN t2 ON t1.a3=t2.a2) INNER JOIN t3 ON (t3.a1=t2.a2))}; +a1 a2 a3 a4 a1 a2 a3 a4 +SELECT t1.*,t2.* FROM { OJ (t1 LEFT OUTER JOIN t2 ON t1.a1=t2.a2) CROSS JOIN t3 ON (t3.a2=t2.a3)}; +a1 a2 a3 a4 a1 a2 a3 a4 +SELECT * FROM {oj t1 LEFT OUTER JOIN t2 ON t1.a1=t2.a3} WHERE t1.a2 > 10; +a1 a2 a3 a4 a1 a2 a3 a4 +SELECT {fn CONCAT(a1,a2)} FROM t1; +{fn CONCAT(a1,a2)} +UPDATE t3 SET a4={d '1789-07-14'} WHERE a1=0; +SELECT a1, a4 FROM t2 WHERE a4 LIKE {fn UCASE('1789-07-14')}; +a1 a4 +DROP TABLE t1, t2, t3; diff --git a/mysql-test/r/query_cache_debug.result b/mysql-test/r/query_cache_debug.result new file mode 100644 index 00000000000..f177bfac836 --- /dev/null +++ b/mysql-test/r/query_cache_debug.result @@ -0,0 +1,24 @@ +flush status; +set query_cache_type=DEMAND; +set global query_cache_size= 1024*1024*512; +drop table if exists t1; +create table t1 (a varchar(100)); +insert into t1 values ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'); +Activate debug hook and attempt to retrieve the statement from the cache. +set session debug='+d,wait_in_query_cache_insert'; +select SQL_CACHE * from t1;; +On a second connection; clear the query cache. +show status like 'Qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 1 +set global query_cache_size= 0; +Signal the debug hook to release the lock. +select id from information_schema.processlist where state='wait_in_query_cache_insert' into @thread_id; +kill query @thread_id; +Show query cache status. +show status like 'Qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 0 +set global query_cache_size= 0; +use test; +drop table t1; diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result index 018173e723d..ca5c5b42102 100644 --- a/mysql-test/r/sp-code.result +++ b/mysql-test/r/sp-code.result @@ -733,6 +733,115 @@ optimizer: keep hreturn drop table t1; drop procedure proc_26977_broken; drop procedure proc_26977_works; +drop procedure if exists proc_33618_h; +drop procedure if exists proc_33618_c; +create procedure proc_33618_h(num int) +begin +declare count1 int default '0'; +declare vb varchar(30); +declare last_row int; +while(num>=1) do +set num=num-1; +begin +declare cur1 cursor for select `a` from t_33618; +declare continue handler for not found set last_row = 1; +set last_row:=0; +open cur1; +rep1: +repeat +begin +declare exit handler for 1062 begin end; +fetch cur1 into vb; +if (last_row = 1) then +## should generate a hpop instruction here +leave rep1; +end if; +end; +until last_row=1 +end repeat; +close cur1; +end; +end while; +end// +create procedure proc_33618_c(num int) +begin +declare count1 int default '0'; +declare vb varchar(30); +declare last_row int; +while(num>=1) do +set num=num-1; +begin +declare cur1 cursor for select `a` from t_33618; +declare continue handler for not found set last_row = 1; +set last_row:=0; +open cur1; +rep1: +repeat +begin +declare cur2 cursor for select `b` from t_33618; +fetch cur1 into vb; +if (last_row = 1) then +## should generate a cpop instruction here +leave rep1; +end if; +end; +until last_row=1 +end repeat; +close cur1; +end; +end while; +end// +show procedure code proc_33618_h; +Pos Instruction +0 set count1@1 _latin1'0' +1 set vb@2 NULL +2 set last_row@3 NULL +3 jump_if_not 24(24) (num@0 >= 1) +4 set num@0 (num@0 - 1) +5 cpush cur1@0 +6 hpush_jump 9 4 CONTINUE +7 set last_row@3 1 +8 hreturn 4 +9 set last_row@3 0 +10 copen cur1@0 +11 hpush_jump 13 4 EXIT +12 hreturn 0 17 +13 cfetch cur1@0 vb@2 +14 jump_if_not 17(17) (last_row@3 = 1) +15 hpop 1 +16 jump 19 +17 hpop 1 +18 jump_if_not 11(19) (last_row@3 = 1) +19 cclose cur1@0 +20 hpop 1 +21 cpop 1 +22 jump 3 +show procedure code proc_33618_c; +Pos Instruction +0 set count1@1 _latin1'0' +1 set vb@2 NULL +2 set last_row@3 NULL +3 jump_if_not 23(23) (num@0 >= 1) +4 set num@0 (num@0 - 1) +5 cpush cur1@0 +6 hpush_jump 9 4 CONTINUE +7 set last_row@3 1 +8 hreturn 4 +9 set last_row@3 0 +10 copen cur1@0 +11 cpush cur2@1 +12 cfetch cur1@0 vb@2 +13 jump_if_not 16(16) (last_row@3 = 1) +14 cpop 1 +15 jump 18 +16 cpop 1 +17 jump_if_not 11(18) (last_row@3 = 1) +18 cclose cur1@0 +19 hpop 1 +20 cpop 1 +21 jump 3 +drop procedure proc_33618_h; +drop procedure proc_33618_c; End of 5.0 tests. CREATE PROCEDURE p1() BEGIN diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index b81f8ea64c9..c33c378340e 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1579,3 +1579,51 @@ drop function f2; drop table t2; ERROR 42S02: Unknown table 't2' End of 5.1 tests +drop procedure if exists proc_33983_a; +drop procedure if exists proc_33983_b; +drop procedure if exists proc_33983_c; +drop procedure if exists proc_33983_d; +create procedure proc_33983_a() +begin +label1: +begin +label2: +begin +select 1; +end label1; +end; +end| +ERROR 42000: End-label label1 without match +create procedure proc_33983_b() +begin +label1: +repeat +label2: +repeat +select 1; +until FALSE end repeat label1; +until FALSE end repeat; +end| +ERROR 42000: End-label label1 without match +create procedure proc_33983_c() +begin +label1: +while TRUE do +label2: +while TRUE do +select 1; +end while label1; +end while; +end| +ERROR 42000: End-label label1 without match +create procedure proc_33983_d() +begin +label1: +loop +label2: +loop +select 1; +end loop label1; +end loop; +end| +ERROR 42000: End-label label1 without match diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 68aa278585f..50ece83b258 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6812,7 +6812,59 @@ DROP PROCEDURE db28318_b.t2; DROP DATABASE db28318_a; DROP DATABASE db28318_b; use test; -End of 5.0 tests +DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS bug29770; +CREATE TABLE t1(a int); +CREATE PROCEDURE bug29770() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '42S22' SET @state:= 'run'; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @exception:= 'run'; +SELECT x FROM t1; +END| +CALL bug29770(); +SELECT @state, @exception; +@state @exception +run NULL +DROP TABLE t1; +DROP PROCEDURE bug29770; +use test; +drop table if exists t_33618; +drop procedure if exists proc_33618; +create table t_33618 (`a` int, unique(`a`), `b` varchar(30)) engine=myisam; +insert into t_33618 (`a`,`b`) values (1,'1'),(2,'2'); +create procedure proc_33618(num int) +begin +declare count1 int default '0'; +declare vb varchar(30); +declare last_row int; +while(num>=1) do +set num=num-1; +begin +declare cur1 cursor for select `a` from t_33618; +declare continue handler for not found set last_row = 1; +set last_row:=0; +open cur1; +rep1: +repeat +begin +declare exit handler for 1062 begin end; +fetch cur1 into vb; +if (last_row = 1) then +leave rep1; +end if; +end; +until last_row=1 +end repeat; +close cur1; +end; +end while; +end// +call proc_33618(20); +drop table t_33618; +drop procedure proc_33618; +# ------------------------------------------------------------------ +# -- End of 5.0 tests +# ------------------------------------------------------------------ # # Bug#20550. @@ -6911,4 +6963,6 @@ END latin1 latin1_swedish_ci latin1_swedish_ci DROP FUNCTION f1; -End of 5.1 tests +# ------------------------------------------------------------------ +# -- End of 5.1 tests +# ------------------------------------------------------------------ diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index c95b09597fc..fc78f4ad40f 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -162,3 +162,24 @@ Variable_name Value Com_show_status 8 rnd_diff tmp_table_diff 20 8 +show global status like 'Com%function%'; +Variable_name Value +Com_alter_function 0 +Com_create_function 0 +Com_drop_function 0 +Com_show_function_code 0 +Com_show_function_status 0 +create function f1 (x INTEGER) returns integer +begin +declare ret integer; +set ret = x * 10; +return ret; +end // +drop function f1; +show global status like 'Com%function%'; +Variable_name Value +Com_alter_function 0 +Com_create_function 1 +Com_drop_function 1 +Com_show_function_code 0 +Com_show_function_status 0 diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index 9170308a4f2..800d717cf6b 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -657,3 +657,23 @@ CREATE TABLE t1 (a INT, b DATETIME); INSERT INTO t1 VALUES (INTERVAL(3,2,1) + 1, "1997-12-31 23:59:59" + INTERVAL 1 SECOND); SELECT * FROM t1 WHERE a = INTERVAL(3,2,1) + 1; DROP TABLE t1; + +# +# Bug#28317 Left Outer Join with {oj outer-join} +# + +--disable_warnings +DROP TABLE IF EXISTS t1,t2,t3; +--enable_warnings +CREATE TABLE t1 (a1 INT, a2 INT, a3 INT, a4 DATETIME); +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 LIKE t1; +SELECT t1.* FROM t1 AS t0, { OJ t2 INNER JOIN t1 ON (t1.a1=t2.a1) } WHERE t0.a3=2; +SELECT t1.*,t2.* FROM { OJ ((t1 INNER JOIN t2 ON (t1.a1=t2.a2)) LEFT OUTER JOIN t3 ON t3.a3=t2.a1)}; +SELECT t1.*,t2.* FROM { OJ ((t1 LEFT OUTER JOIN t2 ON t1.a3=t2.a2) INNER JOIN t3 ON (t3.a1=t2.a2))}; +SELECT t1.*,t2.* FROM { OJ (t1 LEFT OUTER JOIN t2 ON t1.a1=t2.a2) CROSS JOIN t3 ON (t3.a2=t2.a3)}; +SELECT * FROM {oj t1 LEFT OUTER JOIN t2 ON t1.a1=t2.a3} WHERE t1.a2 > 10; +SELECT {fn CONCAT(a1,a2)} FROM t1; +UPDATE t3 SET a4={d '1789-07-14'} WHERE a1=0; +SELECT a1, a4 FROM t2 WHERE a4 LIKE {fn UCASE('1789-07-14')}; +DROP TABLE t1, t2, t3; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 9e250372d51..771a32e8cd7 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -1316,6 +1316,5 @@ SELECT 1 FROM t1 GROUP BY (SELECT LAST_INSERT_ID() FROM t1 ORDER BY MIN(a) ASC LIMIT 1); DROP TABLE t1; - --echo End of 5.1 tests diff --git a/mysql-test/t/query_cache_debug.test b/mysql-test/t/query_cache_debug.test new file mode 100644 index 00000000000..b741eea0b29 --- /dev/null +++ b/mysql-test/t/query_cache_debug.test @@ -0,0 +1,46 @@ +--source include/not_embedded.inc +--source include/have_query_cache.inc +--source include/have_debug.inc + +# +# Bug #30887 Server crashes on SET GLOBAL query_cache_size=0 +# +flush status; +set query_cache_type=DEMAND; +set global query_cache_size= 1024*1024*512; +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a varchar(100)); +insert into t1 values ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'); +connect (bug30887con1, localhost, root, ,test); +connect (bug30887con2, localhost, root, ,test); + +connection bug30887con1; +--echo Activate debug hook and attempt to retrieve the statement from the cache. +set session debug='+d,wait_in_query_cache_insert'; +--send select SQL_CACHE * from t1; + +connection default; +let $wait_condition= select count(*)= 1 from information_schema.processlist where state= 'wait_in_query_cache_insert'; +--source include/wait_condition.inc + +connection bug30887con2; +--echo On a second connection; clear the query cache. +show status like 'Qcache_queries_in_cache'; +set global query_cache_size= 0; + +connection default; +--echo Signal the debug hook to release the lock. +select id from information_schema.processlist where state='wait_in_query_cache_insert' into @thread_id; +kill query @thread_id; + +--echo Show query cache status. +show status like 'Qcache_queries_in_cache'; + +disconnect bug30887con1; +disconnect bug30887con2; +set global query_cache_size= 0; +use test; +drop table t1; + diff --git a/mysql-test/t/sp-code.test b/mysql-test/t/sp-code.test index 66d5323d2e2..84f0201c808 100644 --- a/mysql-test/t/sp-code.test +++ b/mysql-test/t/sp-code.test @@ -520,6 +520,83 @@ drop table t1; drop procedure proc_26977_broken; drop procedure proc_26977_works; +# +# Bug#33618 Crash in sp_rcontext +# + +--disable_warnings +drop procedure if exists proc_33618_h; +drop procedure if exists proc_33618_c; +--enable_warnings + +delimiter //; + +create procedure proc_33618_h(num int) +begin + declare count1 int default '0'; + declare vb varchar(30); + declare last_row int; + + while(num>=1) do + set num=num-1; + begin + declare cur1 cursor for select `a` from t_33618; + declare continue handler for not found set last_row = 1; + set last_row:=0; + open cur1; + rep1: + repeat + begin + declare exit handler for 1062 begin end; + fetch cur1 into vb; + if (last_row = 1) then + ## should generate a hpop instruction here + leave rep1; + end if; + end; + until last_row=1 + end repeat; + close cur1; + end; + end while; +end// + +create procedure proc_33618_c(num int) +begin + declare count1 int default '0'; + declare vb varchar(30); + declare last_row int; + + while(num>=1) do + set num=num-1; + begin + declare cur1 cursor for select `a` from t_33618; + declare continue handler for not found set last_row = 1; + set last_row:=0; + open cur1; + rep1: + repeat + begin + declare cur2 cursor for select `b` from t_33618; + fetch cur1 into vb; + if (last_row = 1) then + ## should generate a cpop instruction here + leave rep1; + end if; + end; + until last_row=1 + end repeat; + close cur1; + end; + end while; +end// +delimiter ;// + +show procedure code proc_33618_h; +show procedure code proc_33618_c; + +drop procedure proc_33618_h; +drop procedure proc_33618_c; --echo End of 5.0 tests. diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 606c2a673bc..286722df65c 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -2305,6 +2305,69 @@ drop table t2; --echo End of 5.1 tests +# +# Bug#33983 (Stored Procedures: wrong end