diff options
author | malff/marcsql@weblab.(none) <> | 2007-08-30 13:23:59 -0600 |
---|---|---|
committer | malff/marcsql@weblab.(none) <> | 2007-08-30 13:23:59 -0600 |
commit | 2482c59740ba73b62851f175fbe2b7adf70f76ae (patch) | |
tree | 8a9eb637bc86a49e83f7ac315d1483f381fea0a2 | |
parent | 52ae4496c560829fe48a4a1c6145b17199492b4d (diff) | |
parent | 7ed3555c673db711db27cf645fd4aaa367402922 (diff) | |
download | mariadb-git-2482c59740ba73b62851f175fbe2b7adf70f76ae.tar.gz |
Merge weblab.(none):/home/marcsql/TREE/mysql-5.1-base
into weblab.(none):/home/marcsql/TREE/mysql-5.1-rt50-merge
38 files changed, 2041 insertions, 241 deletions
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 6b3708f475f..e940f7a3371 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -105,7 +105,7 @@ if [ "x$warning_mode" != "xpedantic" ]; then # Added unless --with-debug=full debug_extra_cflags="-O1 -Wuninitialized" else - warnings="-W -Wall -ansi -pedantic -Wno-long-long -D_POSIX_SOURCE" + warnings="-W -Wall -ansi -pedantic -Wno-long-long -Wno-unused -D_POSIX_SOURCE" c_warnings="$warnings" cxx_warnings="$warnings -std=c++98" # NOTE: warning mode should not influence optimize/debug mode. @@ -207,3 +207,28 @@ then echo "$CC" | grep "ccache" > /dev/null || CC="ccache $CC" echo "$CXX" | grep "ccache" > /dev/null || CXX="ccache $CXX" fi + +# gcov + +# The -fprofile-arcs and -ftest-coverage options cause GCC to instrument the +# code with profiling information used by gcov. +# The -DDISABLE_TAO_ASM is needed to avoid build failures in Yassl. +# The -DHAVE_gcov enables code to write out coverage info even when crashing. + +gcov_compile_flags="-fprofile-arcs -ftest-coverage" +gcov_compile_flags="$gcov_compile_flags -DDISABLE_TAO_ASM" +gcov_compile_flags="$gcov_compile_flags -DMYSQL_SERVER_SUFFIX=-gcov -DHAVE_gcov" + +# GCC4 needs -fprofile-arcs -ftest-coverage on the linker command line (as well +# as on the compiler command line), and this requires setting LDFLAGS for BDB. + +gcov_link_flags="-fprofile-arcs -ftest-coverage" + +gcov_configs="--disable-shared" + +# gprof + +gprof_compile_flags="-O2 -pg -g" + +gprof_link_flags="--disable-shared $static_link" + diff --git a/BUILD/compile-amd64-gcov b/BUILD/compile-amd64-gcov new file mode 100755 index 00000000000..239a4aed0fb --- /dev/null +++ b/BUILD/compile-amd64-gcov @@ -0,0 +1,17 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +# Need to disable ccache, or we loose the gcov-needed compiler output files. +CCACHE_DISABLE=1 +export CCACHE_DISABLE + +export LDFLAGS="$gcov_link_flags" + +extra_flags="$amd64_cflags $debug_cflags $max_cflags $gcov_compile_flags" +c_warnings="$c_warnings $debug_extra_warnings" +cxx_warnings="$cxx_warnings $debug_extra_warnings" +extra_configs="$amd64_configs $debug_configs $gcov_configs $max_configs" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-amd64-gprof b/BUILD/compile-amd64-gprof new file mode 100755 index 00000000000..6cfb8a4302c --- /dev/null +++ b/BUILD/compile-amd64-gprof @@ -0,0 +1,9 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$amd64_cflags $gprof_compile_flags" +extra_configs="$amd64_configs $debug_configs $gprof_link_flags" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium-gcov b/BUILD/compile-pentium-gcov index 77de5867d48..42666b2632c 100755 --- a/BUILD/compile-pentium-gcov +++ b/BUILD/compile-pentium-gcov @@ -20,18 +20,11 @@ export CCACHE_GCOV_VERSION_ENABLED path=`dirname $0` . "$path/SETUP.sh" -# GCC4 needs -fprofile-arcs -ftest-coverage on the linker command line (as well -# as on the compiler command line), and this requires setting LDFLAGS for BDB. -export LDFLAGS="-fprofile-arcs -ftest-coverage" +export LDFLAGS="$gcov_link_flags" -# The -fprofile-arcs and -ftest-coverage options cause GCC to instrument the -# code with profiling information used by gcov. -# The -DDISABLE_TAO_ASM is needed to avoid build failures in Yassl. -# The -DHAVE_gcov enables code to write out coverage info even when crashing. -extra_flags="$pentium_cflags -fprofile-arcs -ftest-coverage -DDISABLE_TAO_ASM -DHAVE_MUTEX_THREAD_ONLY $debug_extra_flags $debug_cflags $max_cflags -DMYSQL_SERVER_SUFFIX=-gcov -DHAVE_gcov" -extra_configs="$pentium_configs $debug_configs --disable-shared $static_link" -extra_configs="$extra_configs $max_configs" +extra_flags="$pentium_cflags $debug_cflags $max_cflags $gcov_compile_flags" c_warnings="$c_warnings $debug_extra_warnings" cxx_warnings="$cxx_warnings $debug_extra_warnings" +extra_configs="$pentium_configs $debug_configs $gcov_configs $max_configs" . "$path/FINISH.sh" diff --git a/BUILD/compile-pentium-gprof b/BUILD/compile-pentium-gprof index aa74de0b1b2..4aebc1d2e02 100755 --- a/BUILD/compile-pentium-gprof +++ b/BUILD/compile-pentium-gprof @@ -3,7 +3,7 @@ path=`dirname $0` . "$path/SETUP.sh" -extra_flags="$pentium_cflags -O2 -pg -g" -extra_configs="$pentium_configs $debug_configs --disable-shared $static_link" +extra_flags="$pentium_cflags $gprof_compile_flags" +extra_configs="$pentium_configs $debug_configs $gprof_link_flags" . "$path/FINISH.sh" diff --git a/BUILD/compile-pentium64-gcov b/BUILD/compile-pentium64-gcov new file mode 100755 index 00000000000..5a99b7f8796 --- /dev/null +++ b/BUILD/compile-pentium64-gcov @@ -0,0 +1,17 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +# Need to disable ccache, or we loose the gcov-needed compiler output files. +CCACHE_DISABLE=1 +export CCACHE_DISABLE + +export LDFLAGS="$gcov_link_flags" + +extra_flags="$pentium64_cflags $debug_cflags $max_cflags $gcov_compile_flags" +c_warnings="$c_warnings $debug_extra_warnings" +cxx_warnings="$cxx_warnings $debug_extra_warnings" +extra_configs="$pentium64_configs $debug_configs $gcov_configs $max_configs" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium64-gprof b/BUILD/compile-pentium64-gprof new file mode 100755 index 00000000000..f64dee6d196 --- /dev/null +++ b/BUILD/compile-pentium64-gprof @@ -0,0 +1,9 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$pentium64_cflags $gprof_compile_flags" +extra_configs="$pentium64_configs $debug_configs $gprof_link_flags" + +. "$path/FINISH.sh" diff --git a/client/mysql.cc b/client/mysql.cc index 8e6a4dd99ae..794f252853a 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1263,6 +1263,7 @@ static bool add_line(String &buffer,char *line,char *in_string, char buff[80], *pos, *out; COMMANDS *com; bool need_space= 0; + bool ss_comment= 0; DBUG_ENTER("add_line"); if (!line[0] && buffer.is_empty()) @@ -1311,22 +1312,36 @@ static bool add_line(String &buffer,char *line,char *in_string, } if ((com=find_command(NullS,(char) inchar))) { - const String tmp(line,(uint) (out-line), charset_info); - buffer.append(tmp); - if ((*com->func)(&buffer,pos-1) > 0) - DBUG_RETURN(1); // Quit - if (com->takes_params) - { - for (pos++ ; - *pos && (*pos != *delimiter || - !is_prefix(pos + 1, delimiter + 1)) ; pos++) - ; // Remove parameters - if (!*pos) - pos--; - else - pos+= delimiter_length - 1; // Point at last delim char - } - out=line; + const String tmp(line,(uint) (out-line), charset_info); + buffer.append(tmp); + if ((*com->func)(&buffer,pos-1) > 0) + DBUG_RETURN(1); // Quit + if (com->takes_params) + { + if (ss_comment) + { + /* + If a client-side macro appears inside a server-side comment, + discard all characters in the comment after the macro (that is, + until the end of the comment rather than the next delimiter) + */ + for (pos++; *pos && (*pos != '*' || *(pos + 1) != '/'); pos++) + ; + pos--; + } + else + { + for (pos++ ; + *pos && (*pos != *delimiter || + !is_prefix(pos + 1, delimiter + 1)) ; pos++) + ; // Remove parameters + if (!*pos) + pos--; + else + pos+= delimiter_length - 1; // Point at last delim char + } + } + out=line; } else { @@ -1386,7 +1401,7 @@ static bool add_line(String &buffer,char *line,char *in_string, out=line; } } - else if (*ml_comment && inchar == '*' && *(pos + 1) == '/') + else if (*ml_comment && !ss_comment && inchar == '*' && *(pos + 1) == '/') { pos++; *ml_comment= 0; @@ -1394,6 +1409,11 @@ static bool add_line(String &buffer,char *line,char *in_string, } else { // Add found char to buffer + if (!*in_string && inchar == '/' && *(pos + 1) == '*' && + *(pos + 2) == '!') + ss_comment= 1; + else if (!*in_string && ss_comment && inchar == '*' && *(pos + 1) == '/') + ss_comment= 0; if (inchar == *in_string) *in_string= 0; else if (!*ml_comment && !*in_string && diff --git a/mysql-test/include/deadlock.inc b/mysql-test/include/deadlock.inc index 41c68f39320..89c34abc871 100644 --- a/mysql-test/include/deadlock.inc +++ b/mysql-test/include/deadlock.inc @@ -144,4 +144,29 @@ disconnect con1; disconnect con2; drop table t1, t2; -# End of 4.1 tests +--echo End of 4.1 tests + +# +# Bug#25164 create table `a` as select * from `A` hangs +# + +set storage_engine=innodb; + +--disable_warnings +drop table if exists a; +drop table if exists A; +--enable_warnings + +create table A (c int); +insert into A (c) values (0); +--error 0,ER_LOCK_DEADLOCK,ER_UPDATE_TABLE_USED +create table a as select * from A; +drop table A; + +--disable_warnings +drop table if exists a; +--enable_warnings + +set storage_engine=default; + +--echo End of 5.0 tests. diff --git a/mysql-test/include/handler.inc b/mysql-test/include/handler.inc index a5b8c6cc7c9..437dd6ced4d 100644 --- a/mysql-test/include/handler.inc +++ b/mysql-test/include/handler.inc @@ -479,3 +479,22 @@ handler t1 open; --echo --> client 1 connection default; drop table t1; + +# +# Bug#30632 HANDLER read failure causes hang +# +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a int); +handler t1 open as t1_alias; +--error 1176 +handler t1_alias read a next; +--error 1054 +handler t1_alias READ a next where inexistent > 0; +--error 1176 +handler t1_alias read a next; +--error 1054 +handler t1_alias READ a next where inexistent > 0; +handler t1_alias close; +drop table t1; diff --git a/mysql-test/r/comments.result b/mysql-test/r/comments.result index 98921c561d1..d8ac68e2468 100644 --- a/mysql-test/r/comments.result +++ b/mysql-test/r/comments.result @@ -36,3 +36,18 @@ select 1/*!999992*/; select 1 + /*!00000 2 */ + 3 /*!99999 noise*/ + 4; 1 + 2 + 3 + 4 10 +drop table if exists table_28779; +create table table_28779 (a int); +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*' AND b = 'bar';"; +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 '/*' AND b = 'bar'' at line 1 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*' AND b = 'bar';*"; +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 '/*' AND b = 'bar';*' at line 1 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*! AND 2=2;"; +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 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*! AND 2=2;*"; +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 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*!98765' AND b = 'bar';"; +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 '/*!98765' AND b = 'bar'' at line 1 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*!98765' AND b = 'bar';*"; +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 '/*!98765' AND b = 'bar';*' at line 1 +drop table table_28779; diff --git a/mysql-test/r/deadlock_innodb.result b/mysql-test/r/deadlock_innodb.result index a0686d1c844..7a4874d6aab 100644 --- a/mysql-test/r/deadlock_innodb.result +++ b/mysql-test/r/deadlock_innodb.result @@ -112,3 +112,14 @@ id x commit; # Switch to connection default + disconnect con1 and con2 drop table t1, t2; +End of 4.1 tests +set storage_engine=innodb; +drop table if exists a; +drop table if exists A; +create table A (c int); +insert into A (c) values (0); +create table a as select * from A; +drop table A; +drop table if exists a; +set storage_engine=default; +End of 5.0 tests. diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result index 579f5907882..be67e2acc7b 100644 --- a/mysql-test/r/events.result +++ b/mysql-test/r/events.result @@ -499,6 +499,9 @@ set global event_scheduler=off; select /*4*/ user, host, db, command, state, info from information_schema.processlist where (command!='Daemon' || user='event_scheduler') and (info is null or info not like '%processlist%') order by info; user host db command state info root localhost events_test Connect User lock select get_lock("test_lock2_1", 20) +select release_lock("test_lock2_1"); +release_lock("test_lock2_1") +1 drop event закачка21; create table t_16 (s1 int); create trigger t_16_bi before insert on t_16 for each row create event e_16 on schedule every 1 second do set @a=5; diff --git a/mysql-test/r/handler_innodb.result b/mysql-test/r/handler_innodb.result index 81d1e26f8d0..98b8922bc5f 100644 --- a/mysql-test/r/handler_innodb.result +++ b/mysql-test/r/handler_innodb.result @@ -522,3 +522,16 @@ handler t1 open; ERROR HY000: Table storage engine for 't1' doesn't have this option --> client 1 drop table t1; +drop table if exists t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias read a next; +ERROR 42000: Key 'a' doesn't exist in table 't1_alias' +handler t1_alias READ a next where inexistent > 0; +ERROR 42S22: Unknown column 'inexistent' in 'field list' +handler t1_alias read a next; +ERROR 42000: Key 'a' doesn't exist in table 't1_alias' +handler t1_alias READ a next where inexistent > 0; +ERROR 42S22: Unknown column 'inexistent' in 'field list' +handler t1_alias close; +drop table t1; diff --git a/mysql-test/r/handler_myisam.result b/mysql-test/r/handler_myisam.result index 5d04604959b..464b775b795 100644 --- a/mysql-test/r/handler_myisam.result +++ b/mysql-test/r/handler_myisam.result @@ -522,3 +522,16 @@ handler t1 open; ERROR HY000: Table storage engine for 't1' doesn't have this option --> client 1 drop table t1; +drop table if exists t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias read a next; +ERROR 42000: Key 'a' doesn't exist in table 't1_alias' +handler t1_alias READ a next where inexistent > 0; +ERROR 42S22: Unknown column 'inexistent' in 'field list' +handler t1_alias read a next; +ERROR 42000: Key 'a' doesn't exist in table 't1_alias' +handler t1_alias READ a next where inexistent > 0; +ERROR 42S22: Unknown column 'inexistent' in 'field list' +handler t1_alias close; +drop table t1; diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index f5b369f246a..df77bc99c22 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -176,5 +176,7 @@ ERROR at line 1: DELIMITER cannot contain a backslash character ERROR at line 1: DELIMITER cannot contain a backslash character 1 1 +1 +1 End of 5.0 tests WARNING: --server-arg option not supported in this configuration. diff --git a/mysql-test/r/parser_precedence.result b/mysql-test/r/parser_precedence.result new file mode 100644 index 00000000000..cf301ec677b --- /dev/null +++ b/mysql-test/r/parser_precedence.result @@ -0,0 +1,747 @@ +drop table if exists t1_30237_bool; +create table t1_30237_bool(A boolean, B boolean, C boolean); +insert into t1_30237_bool values +(FALSE, FALSE, FALSE), +(FALSE, FALSE, NULL), +(FALSE, FALSE, TRUE), +(FALSE, NULL, FALSE), +(FALSE, NULL, NULL), +(FALSE, NULL, TRUE), +(FALSE, TRUE, FALSE), +(FALSE, TRUE, NULL), +(FALSE, TRUE, TRUE), +(NULL, FALSE, FALSE), +(NULL, FALSE, NULL), +(NULL, FALSE, TRUE), +(NULL, NULL, FALSE), +(NULL, NULL, NULL), +(NULL, NULL, TRUE), +(NULL, TRUE, FALSE), +(NULL, TRUE, NULL), +(NULL, TRUE, TRUE), +(TRUE, FALSE, FALSE), +(TRUE, FALSE, NULL), +(TRUE, FALSE, TRUE), +(TRUE, NULL, FALSE), +(TRUE, NULL, NULL), +(TRUE, NULL, TRUE), +(TRUE, TRUE, FALSE), +(TRUE, TRUE, NULL), +(TRUE, TRUE, TRUE) ; +Testing OR, XOR, AND +select A, B, A OR B, A XOR B, A AND B +from t1_30237_bool where C is null order by A, B; +A B A OR B A XOR B A AND B +NULL NULL NULL NULL NULL +NULL 0 NULL NULL 0 +NULL 1 1 NULL NULL +0 NULL NULL NULL 0 +0 0 0 0 0 +0 1 1 1 0 +1 NULL 1 NULL NULL +1 0 1 1 0 +1 1 1 0 1 +Testing that OR is associative +select A, B, C, (A OR B) OR C, A OR (B OR C), A OR B OR C +from t1_30237_bool order by A, B, C; +A B C (A OR B) OR C A OR (B OR C) A OR B OR C +NULL NULL NULL NULL NULL NULL +NULL NULL 0 NULL NULL NULL +NULL NULL 1 1 1 1 +NULL 0 NULL NULL NULL NULL +NULL 0 0 NULL NULL NULL +NULL 0 1 1 1 1 +NULL 1 NULL 1 1 1 +NULL 1 0 1 1 1 +NULL 1 1 1 1 1 +0 NULL NULL NULL NULL NULL +0 NULL 0 NULL NULL NULL +0 NULL 1 1 1 1 +0 0 NULL NULL NULL NULL +0 0 0 0 0 0 +0 0 1 1 1 1 +0 1 NULL 1 1 1 +0 1 0 1 1 1 +0 1 1 1 1 1 +1 NULL NULL 1 1 1 +1 NULL 0 1 1 1 +1 NULL 1 1 1 1 +1 0 NULL 1 1 1 +1 0 0 1 1 1 +1 0 1 1 1 1 +1 1 NULL 1 1 1 +1 1 0 1 1 1 +1 1 1 1 1 1 +select count(*) from t1_30237_bool +where ((A OR B) OR C) != (A OR (B OR C)); +count(*) +0 +Testing that XOR is associative +select A, B, C, (A XOR B) XOR C, A XOR (B XOR C), A XOR B XOR C +from t1_30237_bool order by A, B, C; +A B C (A XOR B) XOR C A XOR (B XOR C) A XOR B XOR C +NULL NULL NULL NULL NULL NULL +NULL NULL 0 NULL NULL NULL +NULL NULL 1 NULL NULL NULL +NULL 0 NULL NULL NULL NULL +NULL 0 0 NULL NULL NULL +NULL 0 1 NULL NULL NULL +NULL 1 NULL NULL NULL NULL +NULL 1 0 NULL NULL NULL +NULL 1 1 NULL NULL NULL +0 NULL NULL NULL NULL NULL +0 NULL 0 NULL NULL NULL +0 NULL 1 NULL NULL NULL +0 0 NULL NULL NULL NULL +0 0 0 0 0 0 +0 0 1 1 1 1 +0 1 NULL NULL NULL NULL +0 1 0 1 1 1 +0 1 1 0 0 0 +1 NULL NULL NULL NULL NULL +1 NULL 0 NULL NULL NULL +1 NULL 1 NULL NULL NULL +1 0 NULL NULL NULL NULL +1 0 0 1 1 1 +1 0 1 0 0 0 +1 1 NULL NULL NULL NULL +1 1 0 0 0 0 +1 1 1 1 1 1 +select count(*) from t1_30237_bool +where ((A XOR B) XOR C) != (A XOR (B XOR C)); +count(*) +0 +Testing that AND is associative +select A, B, C, (A AND B) AND C, A AND (B AND C), A AND B AND C +from t1_30237_bool order by A, B, C; +A B C (A AND B) AND C A AND (B AND C) A AND B AND C +NULL NULL NULL NULL NULL NULL +NULL NULL 0 0 0 0 +NULL NULL 1 NULL NULL NULL +NULL 0 NULL 0 0 0 +NULL 0 0 0 0 0 +NULL 0 1 0 0 0 +NULL 1 NULL NULL NULL NULL +NULL 1 0 0 0 0 +NULL 1 1 NULL NULL NULL +0 NULL NULL 0 0 0 +0 NULL 0 0 0 0 +0 NULL 1 0 0 0 +0 0 NULL 0 0 0 +0 0 0 0 0 0 +0 0 1 0 0 0 +0 1 NULL 0 0 0 +0 1 0 0 0 0 +0 1 1 0 0 0 +1 NULL NULL NULL NULL NULL +1 NULL 0 0 0 0 +1 NULL 1 NULL NULL NULL +1 0 NULL 0 0 0 +1 0 0 0 0 0 +1 0 1 0 0 0 +1 1 NULL NULL NULL NULL +1 1 0 0 0 0 +1 1 1 1 1 1 +select count(*) from t1_30237_bool +where ((A AND B) AND C) != (A AND (B AND C)); +count(*) +0 +Testing that AND has precedence over OR +select A, B, C, (A OR B) AND C, A OR (B AND C), A OR B AND C +from t1_30237_bool order by A, B, C; +A B C (A OR B) AND C A OR (B AND C) A OR B AND C +NULL NULL NULL NULL NULL NULL +NULL NULL 0 0 NULL NULL +NULL NULL 1 NULL NULL NULL +NULL 0 NULL NULL NULL NULL +NULL 0 0 0 NULL NULL +NULL 0 1 NULL NULL NULL +NULL 1 NULL NULL NULL NULL +NULL 1 0 0 NULL NULL +NULL 1 1 1 1 1 +0 NULL NULL NULL NULL NULL +0 NULL 0 0 0 0 +0 NULL 1 NULL NULL NULL +0 0 NULL 0 0 0 +0 0 0 0 0 0 +0 0 1 0 0 0 +0 1 NULL NULL NULL NULL +0 1 0 0 0 0 +0 1 1 1 1 1 +1 NULL NULL NULL 1 1 +1 NULL 0 0 1 1 +1 NULL 1 1 1 1 +1 0 NULL NULL 1 1 +1 0 0 0 1 1 +1 0 1 1 1 1 +1 1 NULL NULL 1 1 +1 1 0 0 1 1 +1 1 1 1 1 1 +select count(*) from t1_30237_bool +where (A OR (B AND C)) != (A OR B AND C); +count(*) +0 +select A, B, C, (A AND B) OR C, A AND (B OR C), A AND B OR C +from t1_30237_bool order by A, B, C; +A B C (A AND B) OR C A AND (B OR C) A AND B OR C +NULL NULL NULL NULL NULL NULL +NULL NULL 0 NULL NULL NULL +NULL NULL 1 1 NULL 1 +NULL 0 NULL NULL NULL NULL +NULL 0 0 0 0 0 +NULL 0 1 1 NULL 1 +NULL 1 NULL NULL NULL NULL +NULL 1 0 NULL NULL NULL +NULL 1 1 1 NULL 1 +0 NULL NULL NULL 0 NULL +0 NULL 0 0 0 0 +0 NULL 1 1 0 1 +0 0 NULL NULL 0 NULL +0 0 0 0 0 0 +0 0 1 1 0 1 +0 1 NULL NULL 0 NULL +0 1 0 0 0 0 +0 1 1 1 0 1 +1 NULL NULL NULL NULL NULL +1 NULL 0 NULL NULL NULL +1 NULL 1 1 1 1 +1 0 NULL NULL NULL NULL +1 0 0 0 0 0 +1 0 1 1 1 1 +1 1 NULL 1 1 1 +1 1 0 1 1 1 +1 1 1 1 1 1 +select count(*) from t1_30237_bool +where ((A AND B) OR C) != (A AND B OR C); +count(*) +0 +Testing that AND has precedence over XOR +select A, B, C, (A XOR B) AND C, A XOR (B AND C), A XOR B AND C +from t1_30237_bool order by A, B, C; +A B C (A XOR B) AND C A XOR (B AND C) A XOR B AND C +NULL NULL NULL NULL NULL NULL +NULL NULL 0 0 NULL NULL +NULL NULL 1 NULL NULL NULL +NULL 0 NULL NULL NULL NULL +NULL 0 0 0 NULL NULL +NULL 0 1 NULL NULL NULL +NULL 1 NULL NULL NULL NULL +NULL 1 0 0 NULL NULL +NULL 1 1 NULL NULL NULL +0 NULL NULL NULL NULL NULL +0 NULL 0 0 0 0 +0 NULL 1 NULL NULL NULL +0 0 NULL 0 0 0 +0 0 0 0 0 0 +0 0 1 0 0 0 +0 1 NULL NULL NULL NULL +0 1 0 0 0 0 +0 1 1 1 1 1 +1 NULL NULL NULL NULL NULL +1 NULL 0 0 1 1 +1 NULL 1 NULL NULL NULL +1 0 NULL NULL 1 1 +1 0 0 0 1 1 +1 0 1 1 1 1 +1 1 NULL 0 NULL NULL +1 1 0 0 1 1 +1 1 1 0 0 0 +select count(*) from t1_30237_bool +where (A XOR (B AND C)) != (A XOR B AND C); +count(*) +0 +select A, B, C, (A AND B) XOR C, A AND (B XOR C), A AND B XOR C +from t1_30237_bool order by A, B, C; +A B C (A AND B) XOR C A AND (B XOR C) A AND B XOR C +NULL NULL NULL NULL NULL NULL +NULL NULL 0 NULL NULL NULL +NULL NULL 1 NULL NULL NULL +NULL 0 NULL NULL NULL NULL +NULL 0 0 0 0 0 +NULL 0 1 1 NULL 1 +NULL 1 NULL NULL NULL NULL +NULL 1 0 NULL NULL NULL +NULL 1 1 NULL 0 NULL +0 NULL NULL NULL 0 NULL +0 NULL 0 0 0 0 +0 NULL 1 1 0 1 +0 0 NULL NULL 0 NULL +0 0 0 0 0 0 +0 0 1 1 0 1 +0 1 NULL NULL 0 NULL +0 1 0 0 0 0 +0 1 1 1 0 1 +1 NULL NULL NULL NULL NULL +1 NULL 0 NULL NULL NULL +1 NULL 1 NULL NULL NULL +1 0 NULL NULL NULL NULL +1 0 0 0 0 0 +1 0 1 1 1 1 +1 1 NULL NULL NULL NULL +1 1 0 1 1 1 +1 1 1 0 0 0 +select count(*) from t1_30237_bool +where ((A AND B) XOR C) != (A AND B XOR C); +count(*) +0 +Testing that XOR has precedence over OR +select A, B, C, (A XOR B) OR C, A XOR (B OR C), A XOR B OR C +from t1_30237_bool order by A, B, C; +A B C (A XOR B) OR C A XOR (B OR C) A XOR B OR C +NULL NULL NULL NULL NULL NULL +NULL NULL 0 NULL NULL NULL +NULL NULL 1 1 NULL 1 +NULL 0 NULL NULL NULL NULL +NULL 0 0 NULL NULL NULL +NULL 0 1 1 NULL 1 +NULL 1 NULL NULL NULL NULL +NULL 1 0 NULL NULL NULL +NULL 1 1 1 NULL 1 +0 NULL NULL NULL NULL NULL +0 NULL 0 NULL NULL NULL +0 NULL 1 1 1 1 +0 0 NULL NULL NULL NULL +0 0 0 0 0 0 +0 0 1 1 1 1 +0 1 NULL 1 1 1 +0 1 0 1 1 1 +0 1 1 1 1 1 +1 NULL NULL NULL NULL NULL +1 NULL 0 NULL NULL NULL +1 NULL 1 1 0 1 +1 0 NULL 1 NULL 1 +1 0 0 1 1 1 +1 0 1 1 0 1 +1 1 NULL NULL 0 NULL +1 1 0 0 0 0 +1 1 1 1 0 1 +select count(*) from t1_30237_bool +where ((A XOR B) OR C) != (A XOR B OR C); +count(*) +0 +select A, B, C, (A OR B) XOR C, A OR (B XOR C), A OR B XOR C +from t1_30237_bool order by A, B, C; +A B C (A OR B) XOR C A OR (B XOR C) A OR B XOR C +NULL NULL NULL NULL NULL NULL +NULL NULL 0 NULL NULL NULL +NULL NULL 1 NULL NULL NULL +NULL 0 NULL NULL NULL NULL +NULL 0 0 NULL NULL NULL +NULL 0 1 NULL 1 1 +NULL 1 NULL NULL NULL NULL +NULL 1 0 1 1 1 +NULL 1 1 0 NULL NULL +0 NULL NULL NULL NULL NULL +0 NULL 0 NULL NULL NULL +0 NULL 1 NULL NULL NULL +0 0 NULL NULL NULL NULL +0 0 0 0 0 0 +0 0 1 1 1 1 +0 1 NULL NULL NULL NULL +0 1 0 1 1 1 +0 1 1 0 0 0 +1 NULL NULL NULL 1 1 +1 NULL 0 1 1 1 +1 NULL 1 0 1 1 +1 0 NULL NULL 1 1 +1 0 0 1 1 1 +1 0 1 0 1 1 +1 1 NULL NULL 1 1 +1 1 0 1 1 1 +1 1 1 0 1 1 +select count(*) from t1_30237_bool +where (A OR (B XOR C)) != (A OR B XOR C); +count(*) +0 +drop table t1_30237_bool; +Testing that NOT has precedence over OR +select (NOT FALSE) OR TRUE, NOT (FALSE OR TRUE), NOT FALSE OR TRUE; +(NOT FALSE) OR TRUE NOT (FALSE OR TRUE) NOT FALSE OR TRUE +1 0 1 +Testing that NOT has precedence over XOR +select (NOT FALSE) XOR FALSE, NOT (FALSE XOR FALSE), NOT FALSE XOR FALSE; +(NOT FALSE) XOR FALSE NOT (FALSE XOR FALSE) NOT FALSE XOR FALSE +1 1 1 +Testing that NOT has precedence over AND +select (NOT FALSE) AND FALSE, NOT (FALSE AND FALSE), NOT FALSE AND FALSE; +(NOT FALSE) AND FALSE NOT (FALSE AND FALSE) NOT FALSE AND FALSE +0 1 0 +Testing that NOT is associative +select NOT NOT TRUE, NOT NOT NOT FALSE; +NOT NOT TRUE NOT NOT NOT FALSE +1 1 +Testing that IS has precedence over NOT +select (NOT NULL) IS TRUE, NOT (NULL IS TRUE), NOT NULL IS TRUE; +(NOT NULL) IS TRUE NOT (NULL IS TRUE) NOT NULL IS TRUE +0 1 1 +select (NOT NULL) IS NOT TRUE, NOT (NULL IS NOT TRUE), NOT NULL IS NOT TRUE; +(NOT NULL) IS NOT TRUE NOT (NULL IS NOT TRUE) NOT NULL IS NOT TRUE +1 0 0 +select (NOT NULL) IS FALSE, NOT (NULL IS FALSE), NOT NULL IS FALSE; +(NOT NULL) IS FALSE NOT (NULL IS FALSE) NOT NULL IS FALSE +0 1 1 +select (NOT NULL) IS NOT FALSE, NOT (NULL IS NOT FALSE), NOT NULL IS NOT FALSE; +(NOT NULL) IS NOT FALSE NOT (NULL IS NOT FALSE) NOT NULL IS NOT FALSE +1 0 0 +select (NOT TRUE) IS UNKNOWN, NOT (TRUE IS UNKNOWN), NOT TRUE IS UNKNOWN; +(NOT TRUE) IS UNKNOWN NOT (TRUE IS UNKNOWN) NOT TRUE IS UNKNOWN +0 1 1 +select (NOT TRUE) IS NOT UNKNOWN, NOT (TRUE IS NOT UNKNOWN), NOT TRUE IS NOT UNKNOWN; +(NOT TRUE) IS NOT UNKNOWN NOT (TRUE IS NOT UNKNOWN) NOT TRUE IS NOT UNKNOWN +1 0 0 +select (NOT TRUE) IS NULL, NOT (TRUE IS NULL), NOT TRUE IS NULL; +(NOT TRUE) IS NULL NOT (TRUE IS NULL) NOT TRUE IS NULL +0 1 1 +select (NOT TRUE) IS NOT NULL, NOT (TRUE IS NOT NULL), NOT TRUE IS NOT NULL; +(NOT TRUE) IS NOT NULL NOT (TRUE IS NOT NULL) NOT TRUE IS NOT NULL +1 0 0 +Testing that IS [NOT] TRUE/FALSE/UNKNOWN predicates are not associative +select TRUE IS TRUE IS TRUE IS TRUE; +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 'IS TRUE IS TRUE' at line 1 +select FALSE IS NOT TRUE IS NOT TRUE IS NOT TRUE; +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 'IS NOT TRUE IS NOT TRUE' at line 1 +select NULL IS FALSE IS FALSE IS FALSE; +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 'IS FALSE IS FALSE' at line 1 +select TRUE IS NOT FALSE IS NOT FALSE IS NOT FALSE; +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 'IS NOT FALSE IS NOT FALSE' at line 1 +select FALSE IS UNKNOWN IS UNKNOWN IS UNKNOWN; +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 'IS UNKNOWN IS UNKNOWN' at line 1 +select TRUE IS NOT UNKNOWN IS NOT UNKNOWN IS NOT UNKNOWN; +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 'IS NOT UNKNOWN IS NOT UNKNOWN' at line 1 +Testing that IS [NOT] NULL predicates are associative +select FALSE IS NULL IS NULL IS NULL; +FALSE IS NULL IS NULL IS NULL +0 +select TRUE IS NOT NULL IS NOT NULL IS NOT NULL; +TRUE IS NOT NULL IS NOT NULL IS NOT NULL +1 +Testing that comparison operators are left associative +select 1 <=> 2 <=> 2, (1 <=> 2) <=> 2, 1 <=> (2 <=> 2); +1 <=> 2 <=> 2 (1 <=> 2) <=> 2 1 <=> (2 <=> 2) +0 0 1 +select 1 = 2 = 2, (1 = 2) = 2, 1 = (2 = 2); +1 = 2 = 2 (1 = 2) = 2 1 = (2 = 2) +0 0 1 +select 1 != 2 != 3, (1 != 2) != 3, 1 != (2 != 3); +1 != 2 != 3 (1 != 2) != 3 1 != (2 != 3) +1 1 0 +select 1 <> 2 <> 3, (1 <> 2) <> 3, 1 <> (2 <> 3); +1 <> 2 <> 3 (1 <> 2) <> 3 1 <> (2 <> 3) +1 1 0 +select 1 < 2 < 3, (1 < 2) < 3, 1 < (2 < 3); +1 < 2 < 3 (1 < 2) < 3 1 < (2 < 3) +1 1 0 +select 3 <= 2 <= 1, (3 <= 2) <= 1, 3 <= (2 <= 1); +3 <= 2 <= 1 (3 <= 2) <= 1 3 <= (2 <= 1) +1 1 0 +select 1 > 2 > 3, (1 > 2) > 3, 1 > (2 > 3); +1 > 2 > 3 (1 > 2) > 3 1 > (2 > 3) +0 0 1 +select 1 >= 2 >= 3, (1 >= 2) >= 3, 1 >= (2 >= 3); +1 >= 2 >= 3 (1 >= 2) >= 3 1 >= (2 >= 3) +0 0 1 +Testing that | is associative +select 0xF0 | 0x0F | 0x55, (0xF0 | 0x0F) | 0x55, 0xF0 | (0x0F | 0x55); +0xF0 | 0x0F | 0x55 (0xF0 | 0x0F) | 0x55 0xF0 | (0x0F | 0x55) +255 255 255 +Testing that & is associative +select 0xF5 & 0x5F & 0x55, (0xF5 & 0x5F) & 0x55, 0xF5 & (0x5F & 0x55); +0xF5 & 0x5F & 0x55 (0xF5 & 0x5F) & 0x55 0xF5 & (0x5F & 0x55) +85 85 85 +Testing that << is left associative +select 4 << 3 << 2, (4 << 3) << 2, 4 << (3 << 2); +4 << 3 << 2 (4 << 3) << 2 4 << (3 << 2) +128 128 16384 +Testing that >> is left associative +select 256 >> 3 >> 2, (256 >> 3) >> 2, 256 >> (3 >> 2); +256 >> 3 >> 2 (256 >> 3) >> 2 256 >> (3 >> 2) +8 8 256 +Testing that & has precedence over | +select 0xF0 & 0x0F | 0x55, (0xF0 & 0x0F) | 0x55, 0xF0 & (0x0F | 0x55); +0xF0 & 0x0F | 0x55 (0xF0 & 0x0F) | 0x55 0xF0 & (0x0F | 0x55) +85 85 80 +select 0x55 | 0xF0 & 0x0F, (0x55 | 0xF0) & 0x0F, 0x55 | (0xF0 & 0x0F); +0x55 | 0xF0 & 0x0F (0x55 | 0xF0) & 0x0F 0x55 | (0xF0 & 0x0F) +85 5 85 +Testing that << has precedence over | +select 0x0F << 4 | 0x0F, (0x0F << 4) | 0x0F, 0x0F << (4 | 0x0F); +0x0F << 4 | 0x0F (0x0F << 4) | 0x0F 0x0F << (4 | 0x0F) +255 255 491520 +select 0x0F | 0x0F << 4, (0x0F | 0x0F) << 4, 0x0F | (0x0F << 4); +0x0F | 0x0F << 4 (0x0F | 0x0F) << 4 0x0F | (0x0F << 4) +255 240 255 +Testing that >> has precedence over | +select 0xF0 >> 4 | 0xFF, (0xF0 >> 4) | 0xFF, 0xF0 >> (4 | 0xFF); +0xF0 >> 4 | 0xFF (0xF0 >> 4) | 0xFF 0xF0 >> (4 | 0xFF) +255 255 0 +select 0xFF | 0xF0 >> 4, (0xFF | 0xF0) >> 4, 0xFF | (0xF0 >> 4); +0xFF | 0xF0 >> 4 (0xFF | 0xF0) >> 4 0xFF | (0xF0 >> 4) +255 15 255 +Testing that << has precedence over & +select 0x0F << 4 & 0xF0, (0x0F << 4) & 0xF0, 0x0F << (4 & 0xF0); +0x0F << 4 & 0xF0 (0x0F << 4) & 0xF0 0x0F << (4 & 0xF0) +240 240 15 +select 0xF0 & 0x0F << 4, (0xF0 & 0x0F) << 4, 0xF0 & (0x0F << 4); +0xF0 & 0x0F << 4 (0xF0 & 0x0F) << 4 0xF0 & (0x0F << 4) +240 0 240 +Testing that >> has precedence over & +select 0xF0 >> 4 & 0x55, (0xF0 >> 4) & 0x55, 0xF0 >> (4 & 0x55); +0xF0 >> 4 & 0x55 (0xF0 >> 4) & 0x55 0xF0 >> (4 & 0x55) +5 5 15 +select 0x0F & 0xF0 >> 4, (0x0F & 0xF0) >> 4, 0x0F & (0xF0 >> 4); +0x0F & 0xF0 >> 4 (0x0F & 0xF0) >> 4 0x0F & (0xF0 >> 4) +15 0 15 +Testing that >> and << have the same precedence +select 0xFF >> 4 << 2, (0xFF >> 4) << 2, 0xFF >> (4 << 2); +0xFF >> 4 << 2 (0xFF >> 4) << 2 0xFF >> (4 << 2) +60 60 0 +select 0x0F << 4 >> 2, (0x0F << 4) >> 2, 0x0F << (4 >> 2); +0x0F << 4 >> 2 (0x0F << 4) >> 2 0x0F << (4 >> 2) +60 60 30 +Testing that binary + is associative +select 1 + 2 + 3, (1 + 2) + 3, 1 + (2 + 3); +1 + 2 + 3 (1 + 2) + 3 1 + (2 + 3) +6 6 6 +Testing that binary - is left associative +select 1 - 2 - 3, (1 - 2) - 3, 1 - (2 - 3); +1 - 2 - 3 (1 - 2) - 3 1 - (2 - 3) +-4 -4 2 +Testing that binary + and binary - have the same precedence +select 1 + 2 - 3, (1 + 2) - 3, 1 + (2 - 3); +1 + 2 - 3 (1 + 2) - 3 1 + (2 - 3) +0 0 0 +select 1 - 2 + 3, (1 - 2) + 3, 1 - (2 + 3); +1 - 2 + 3 (1 - 2) + 3 1 - (2 + 3) +2 2 -4 +Testing that binary + has precedence over | +select 0xF0 + 0x0F | 0x55, (0xF0 + 0x0F) | 0x55, 0xF0 + (0x0F | 0x55); +0xF0 + 0x0F | 0x55 (0xF0 + 0x0F) | 0x55 0xF0 + (0x0F | 0x55) +255 255 335 +select 0x55 | 0xF0 + 0x0F, (0x55 | 0xF0) + 0x0F, 0x55 | (0xF0 + 0x0F); +0x55 | 0xF0 + 0x0F (0x55 | 0xF0) + 0x0F 0x55 | (0xF0 + 0x0F) +255 260 255 +Testing that binary + has precedence over & +select 0xF0 + 0x0F & 0x55, (0xF0 + 0x0F) & 0x55, 0xF0 + (0x0F & 0x55); +0xF0 + 0x0F & 0x55 (0xF0 + 0x0F) & 0x55 0xF0 + (0x0F & 0x55) +85 85 245 +select 0x55 & 0xF0 + 0x0F, (0x55 & 0xF0) + 0x0F, 0x55 & (0xF0 + 0x0F); +0x55 & 0xF0 + 0x0F (0x55 & 0xF0) + 0x0F 0x55 & (0xF0 + 0x0F) +85 95 85 +Testing that binary + has precedence over << +select 2 + 3 << 4, (2 + 3) << 4, 2 + (3 << 4); +2 + 3 << 4 (2 + 3) << 4 2 + (3 << 4) +80 80 50 +select 3 << 4 + 2, (3 << 4) + 2, 3 << (4 + 2); +3 << 4 + 2 (3 << 4) + 2 3 << (4 + 2) +192 50 192 +Testing that binary + has precedence over >> +select 4 + 3 >> 2, (4 + 3) >> 2, 4 + (3 >> 2); +4 + 3 >> 2 (4 + 3) >> 2 4 + (3 >> 2) +1 1 4 +select 3 >> 2 + 1, (3 >> 2) + 1, 3 >> (2 + 1); +3 >> 2 + 1 (3 >> 2) + 1 3 >> (2 + 1) +0 1 0 +Testing that binary - has precedence over | +select 0xFF - 0x0F | 0x55, (0xFF - 0x0F) | 0x55, 0xFF - (0x0F | 0x55); +0xFF - 0x0F | 0x55 (0xFF - 0x0F) | 0x55 0xFF - (0x0F | 0x55) +245 245 160 +select 0x55 | 0xFF - 0xF0, (0x55 | 0xFF) - 0xF0, 0x55 | (0xFF - 0xF0); +0x55 | 0xFF - 0xF0 (0x55 | 0xFF) - 0xF0 0x55 | (0xFF - 0xF0) +95 15 95 +Testing that binary - has precedence over & +select 0xFF - 0xF0 & 0x55, (0xFF - 0xF0) & 0x55, 0xFF - (0xF0 & 0x55); +0xFF - 0xF0 & 0x55 (0xFF - 0xF0) & 0x55 0xFF - (0xF0 & 0x55) +5 5 175 +select 0x55 & 0xFF - 0xF0, (0x55 & 0xFF) - 0xF0, 0x55 & (0xFF - 0xF0); +0x55 & 0xFF - 0xF0 (0x55 & 0xFF) - 0xF0 0x55 & (0xFF - 0xF0) +5 -155 5 +Testing that binary - has precedence over << +select 16 - 3 << 2, (16 - 3) << 2, 16 - (3 << 2); +16 - 3 << 2 (16 - 3) << 2 16 - (3 << 2) +52 52 4 +select 4 << 3 - 2, (4 << 3) - 2, 4 << (3 - 2); +4 << 3 - 2 (4 << 3) - 2 4 << (3 - 2) +8 30 8 +Testing that binary - has precedence over >> +select 16 - 3 >> 2, (16 - 3) >> 2, 16 - (3 >> 2); +16 - 3 >> 2 (16 - 3) >> 2 16 - (3 >> 2) +3 3 16 +select 16 >> 3 - 2, (16 >> 3) - 2, 16 >> (3 - 2); +16 >> 3 - 2 (16 >> 3) - 2 16 >> (3 - 2) +8 0 8 +Testing that * is associative +select 2 * 3 * 4, (2 * 3) * 4, 2 * (3 * 4); +2 * 3 * 4 (2 * 3) * 4 2 * (3 * 4) +24 24 24 +Testing that * has precedence over | +select 2 * 0x40 | 0x0F, (2 * 0x40) | 0x0F, 2 * (0x40 | 0x0F); +2 * 0x40 | 0x0F (2 * 0x40) | 0x0F 2 * (0x40 | 0x0F) +143 143 158 +select 0x0F | 2 * 0x40, (0x0F | 2) * 0x40, 0x0F | (2 * 0x40); +0x0F | 2 * 0x40 (0x0F | 2) * 0x40 0x0F | (2 * 0x40) +143 960 143 +Testing that * has precedence over & +select 2 * 0x40 & 0x55, (2 * 0x40) & 0x55, 2 * (0x40 & 0x55); +2 * 0x40 & 0x55 (2 * 0x40) & 0x55 2 * (0x40 & 0x55) +0 0 128 +select 0xF0 & 2 * 0x40, (0xF0 & 2) * 0x40, 0xF0 & (2 * 0x40); +0xF0 & 2 * 0x40 (0xF0 & 2) * 0x40 0xF0 & (2 * 0x40) +128 0 128 +Testing that * has precedence over << +select 5 * 3 << 4, (5 * 3) << 4, 5 * (3 << 4); +5 * 3 << 4 (5 * 3) << 4 5 * (3 << 4) +240 240 240 +select 2 << 3 * 4, (2 << 3) * 4, 2 << (3 * 4); +2 << 3 * 4 (2 << 3) * 4 2 << (3 * 4) +8192 64 8192 +Testing that * has precedence over >> +select 3 * 4 >> 2, (3 * 4) >> 2, 3 * (4 >> 2); +3 * 4 >> 2 (3 * 4) >> 2 3 * (4 >> 2) +3 3 3 +select 4 >> 2 * 3, (4 >> 2) * 3, 4 >> (2 * 3); +4 >> 2 * 3 (4 >> 2) * 3 4 >> (2 * 3) +0 3 0 +Testing that * has precedence over binary + +select 2 * 3 + 4, (2 * 3) + 4, 2 * (3 + 4); +2 * 3 + 4 (2 * 3) + 4 2 * (3 + 4) +10 10 14 +select 2 + 3 * 4, (2 + 3) * 4, 2 + (3 * 4); +2 + 3 * 4 (2 + 3) * 4 2 + (3 * 4) +14 20 14 +Testing that * has precedence over binary - +select 4 * 3 - 2, (4 * 3) - 2, 4 * (3 - 2); +4 * 3 - 2 (4 * 3) - 2 4 * (3 - 2) +10 10 4 +select 4 - 3 * 2, (4 - 3) * 2, 4 - (3 * 2); +4 - 3 * 2 (4 - 3) * 2 4 - (3 * 2) +-2 2 -2 +Testing that / is left associative +select 15 / 5 / 3, (15 / 5) / 3, 15 / (5 / 3); +15 / 5 / 3 (15 / 5) / 3 15 / (5 / 3) +1.00000000 1.00000000 9.0000 +Testing that / has precedence over | +select 105 / 5 | 2, (105 / 5) | 2, 105 / (5 | 2); +105 / 5 | 2 (105 / 5) | 2 105 / (5 | 2) +23 23 15.0000 +select 105 | 2 / 5, (105 | 2) / 5, 105 | (2 / 5); +105 | 2 / 5 (105 | 2) / 5 105 | (2 / 5) +105 21.4000 105 +Testing that / has precedence over & +select 105 / 5 & 0x0F, (105 / 5) & 0x0F, 105 / (5 & 0x0F); +105 / 5 & 0x0F (105 / 5) & 0x0F 105 / (5 & 0x0F) +5 5 21.0000 +select 0x0F & 105 / 5, (0x0F & 105) / 5, 0x0F & (105 / 5); +0x0F & 105 / 5 (0x0F & 105) / 5 0x0F & (105 / 5) +5 1.8000 5 +Testing that / has precedence over << +select 0x80 / 4 << 2, (0x80 / 4) << 2, 0x80 / (4 << 2); +0x80 / 4 << 2 (0x80 / 4) << 2 0x80 / (4 << 2) +128 128 8.0000 +select 0x80 << 4 / 2, (0x80 << 4) / 2, 0x80 << (4 / 2); +0x80 << 4 / 2 (0x80 << 4) / 2 0x80 << (4 / 2) +512 1024.0000 512 +Testing that / has precedence over >> +select 0x80 / 4 >> 2, (0x80 / 4) >> 2, 0x80 / (4 >> 2); +0x80 / 4 >> 2 (0x80 / 4) >> 2 0x80 / (4 >> 2) +8 8 128.0000 +select 0x80 >> 4 / 2, (0x80 >> 4) / 2, 0x80 >> (4 / 2); +0x80 >> 4 / 2 (0x80 >> 4) / 2 0x80 >> (4 / 2) +32 4.0000 32 +Testing that / has precedence over binary + +select 0x80 / 2 + 2, (0x80 / 2) + 2, 0x80 / (2 + 2); +0x80 / 2 + 2 (0x80 / 2) + 2 0x80 / (2 + 2) +66.0000 66.0000 32.0000 +select 0x80 + 2 / 2, (0x80 + 2) / 2, 0x80 + (2 / 2); +0x80 + 2 / 2 (0x80 + 2) / 2 0x80 + (2 / 2) +129.0000 65.0000 129.0000 +Testing that / has precedence over binary - +select 0x80 / 4 - 2, (0x80 / 4) - 2, 0x80 / (4 - 2); +0x80 / 4 - 2 (0x80 / 4) - 2 0x80 / (4 - 2) +30.0000 30.0000 64.0000 +select 0x80 - 4 / 2, (0x80 - 4) / 2, 0x80 - (4 / 2); +0x80 - 4 / 2 (0x80 - 4) / 2 0x80 - (4 / 2) +126.0000 62.0000 126.0000 +Testing that ^ is associative +select 0xFF ^ 0xF0 ^ 0x0F, (0xFF ^ 0xF0) ^ 0x0F, 0xFF ^ (0xF0 ^ 0x0F); +0xFF ^ 0xF0 ^ 0x0F (0xFF ^ 0xF0) ^ 0x0F 0xFF ^ (0xF0 ^ 0x0F) +0 0 0 +select 0xFF ^ 0xF0 ^ 0x55, (0xFF ^ 0xF0) ^ 0x55, 0xFF ^ (0xF0 ^ 0x55); +0xFF ^ 0xF0 ^ 0x55 (0xFF ^ 0xF0) ^ 0x55 0xFF ^ (0xF0 ^ 0x55) +90 90 90 +Testing that ^ has precedence over | +select 0xFF ^ 0xF0 | 0x0F, (0xFF ^ 0xF0) | 0x0F, 0xFF ^ (0xF0 | 0x0F); +0xFF ^ 0xF0 | 0x0F (0xFF ^ 0xF0) | 0x0F 0xFF ^ (0xF0 | 0x0F) +15 15 0 +select 0xF0 | 0xFF ^ 0xF0, (0xF0 | 0xFF) ^ 0xF0, 0xF0 | (0xFF ^ 0xF0); +0xF0 | 0xFF ^ 0xF0 (0xF0 | 0xFF) ^ 0xF0 0xF0 | (0xFF ^ 0xF0) +255 15 255 +Testing that ^ has precedence over & +select 0xFF ^ 0xF0 & 0x0F, (0xFF ^ 0xF0) & 0x0F, 0xFF ^ (0xF0 & 0x0F); +0xFF ^ 0xF0 & 0x0F (0xFF ^ 0xF0) & 0x0F 0xFF ^ (0xF0 & 0x0F) +15 15 255 +select 0x0F & 0xFF ^ 0xF0, (0x0F & 0xFF) ^ 0xF0, 0x0F & (0xFF ^ 0xF0); +0x0F & 0xFF ^ 0xF0 (0x0F & 0xFF) ^ 0xF0 0x0F & (0xFF ^ 0xF0) +15 255 15 +Testing that ^ has precedence over << +select 0xFF ^ 0xF0 << 2, (0xFF ^ 0xF0) << 2, 0xFF ^ (0xF0 << 2); +0xFF ^ 0xF0 << 2 (0xFF ^ 0xF0) << 2 0xFF ^ (0xF0 << 2) +60 60 831 +select 0x0F << 2 ^ 0xFF, (0x0F << 2) ^ 0xFF, 0x0F << (2 ^ 0xFF); +0x0F << 2 ^ 0xFF (0x0F << 2) ^ 0xFF 0x0F << (2 ^ 0xFF) +0 195 0 +Testing that ^ has precedence over >> +select 0xFF ^ 0xF0 >> 2, (0xFF ^ 0xF0) >> 2, 0xFF ^ (0xF0 >> 2); +0xFF ^ 0xF0 >> 2 (0xFF ^ 0xF0) >> 2 0xFF ^ (0xF0 >> 2) +3 3 195 +select 0xFF >> 2 ^ 0xF0, (0xFF >> 2) ^ 0xF0, 0xFF >> (2 ^ 0xF0); +0xFF >> 2 ^ 0xF0 (0xFF >> 2) ^ 0xF0 0xFF >> (2 ^ 0xF0) +0 207 0 +Testing that ^ has precedence over binary + +select 0xFF ^ 0xF0 + 0x0F, (0xFF ^ 0xF0) + 0x0F, 0xFF ^ (0xF0 + 0x0F); +0xFF ^ 0xF0 + 0x0F (0xFF ^ 0xF0) + 0x0F 0xFF ^ (0xF0 + 0x0F) +30 30 0 +select 0x0F + 0xFF ^ 0xF0, (0x0F + 0xFF) ^ 0xF0, 0x0F + (0xFF ^ 0xF0); +0x0F + 0xFF ^ 0xF0 (0x0F + 0xFF) ^ 0xF0 0x0F + (0xFF ^ 0xF0) +30 510 30 +Testing that ^ has precedence over binary - +select 0xFF ^ 0xF0 - 1, (0xFF ^ 0xF0) - 1, 0xFF ^ (0xF0 - 1); +0xFF ^ 0xF0 - 1 (0xFF ^ 0xF0) - 1 0xFF ^ (0xF0 - 1) +14 14 16 +select 0x55 - 0x0F ^ 0x55, (0x55 - 0x0F) ^ 0x55, 0x55 - (0x0F ^ 0x55); +0x55 - 0x0F ^ 0x55 (0x55 - 0x0F) ^ 0x55 0x55 - (0x0F ^ 0x55) +-5 19 -5 +Testing that ^ has precedence over * +select 0xFF ^ 0xF0 * 2, (0xFF ^ 0xF0) * 2, 0xFF ^ (0xF0 * 2); +0xFF ^ 0xF0 * 2 (0xFF ^ 0xF0) * 2 0xFF ^ (0xF0 * 2) +30 30 287 +select 2 * 0xFF ^ 0xF0, (2 * 0xFF) ^ 0xF0, 2 * (0xFF ^ 0xF0); +2 * 0xFF ^ 0xF0 (2 * 0xFF) ^ 0xF0 2 * (0xFF ^ 0xF0) +30 270 30 +Testing that ^ has precedence over / +select 0xFF ^ 0xF0 / 2, (0xFF ^ 0xF0) / 2, 0xFF ^ (0xF0 / 2); +0xFF ^ 0xF0 / 2 (0xFF ^ 0xF0) / 2 0xFF ^ (0xF0 / 2) +7.5000 7.5000 135 +select 0xF2 / 2 ^ 0xF0, (0xF2 / 2) ^ 0xF0, 0xF2 / (2 ^ 0xF0); +0xF2 / 2 ^ 0xF0 (0xF2 / 2) ^ 0xF0 0xF2 / (2 ^ 0xF0) +1.0000 137 1.0000 +Testing that ^ has precedence over % +select 0xFF ^ 0xF0 % 0x20, (0xFF ^ 0xF0) % 0x20, 0xFF ^ (0xF0 % 0x20); +0xFF ^ 0xF0 % 0x20 (0xFF ^ 0xF0) % 0x20 0xFF ^ (0xF0 % 0x20) +15 15 239 +select 0xFF % 0x20 ^ 0xF0, (0xFF % 0x20) ^ 0xF0, 0xFF % (0x20 ^ 0xF0); +0xFF % 0x20 ^ 0xF0 (0xFF % 0x20) ^ 0xF0 0xFF % (0x20 ^ 0xF0) +47 239 47 +Testing that ^ has precedence over DIV +select 0xFF ^ 0xF0 DIV 2, (0xFF ^ 0xF0) DIV 2, 0xFF ^ (0xF0 DIV 2); +0xFF ^ 0xF0 DIV 2 (0xFF ^ 0xF0) DIV 2 0xFF ^ (0xF0 DIV 2) +7 7 135 +select 0xF2 DIV 2 ^ 0xF0, (0xF2 DIV 2) ^ 0xF0, 0xF2 DIV (2 ^ 0xF0); +0xF2 DIV 2 ^ 0xF0 (0xF2 DIV 2) ^ 0xF0 0xF2 DIV (2 ^ 0xF0) +1 137 1 +Testing that ^ has precedence over MOD +select 0xFF ^ 0xF0 MOD 0x20, (0xFF ^ 0xF0) MOD 0x20, 0xFF ^ (0xF0 MOD 0x20); +0xFF ^ 0xF0 MOD 0x20 (0xFF ^ 0xF0) MOD 0x20 0xFF ^ (0xF0 MOD 0x20) +15 15 239 +select 0xFF MOD 0x20 ^ 0xF0, (0xFF MOD 0x20) ^ 0xF0, 0xFF MOD (0x20 ^ 0xF0); +0xFF MOD 0x20 ^ 0xF0 (0xFF MOD 0x20) ^ 0xF0 0xFF MOD (0x20 ^ 0xF0) +47 239 47 diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 675a59f1fb7..2e0d437aeb6 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -969,6 +969,18 @@ CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create user 'mysqltest ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. CREATE FUNCTION bug_13627_f() returns int BEGIN create user 'mysqltest_1'; return 1; END | ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN grant select on t1 to 'mysqltest_1'; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug21975() returns int BEGIN grant select on t1 to 'mysqltest_1'; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN revoke select on t1 from 'mysqltest_1'; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug21975() returns int BEGIN revoke select on t1 from 'mysqltest_1'; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN revoke all privileges on *.* from 'mysqltest_1'; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug21975() returns int BEGIN revoke all privileges on *.* from 'mysqltest_1'; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop user 'mysqltest_1'; END | ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. CREATE FUNCTION bug_13627_f() returns int BEGIN drop user 'mysqltest_1'; return 1; END | diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 163bbb4aab4..2abff35b232 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6546,4 +6546,79 @@ DROP VIEW v1; DROP FUNCTION f1; DROP FUNCTION f2; DROP TABLE t1; +drop table if exists t1; +drop procedure if exists p1; +create table t1 (value varchar(15)); +create procedure p1() update t1 set value='updated' where value='old'; +call p1(); +insert into t1 (value) values ("old"); +select get_lock('b26162',120); +get_lock('b26162',120) +1 +select 'rl_acquirer', value from t1 where get_lock('b26162',120);; +set session low_priority_updates=on; +call p1();; +select 'rl_contender', value from t1; +rl_contender value +rl_contender old +select release_lock('b26162'); +release_lock('b26162') +1 +rl_acquirer value +rl_acquirer old +drop procedure p1; +drop table t1; +set session low_priority_updates=default; + +# Bug#13675. + +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP TABLE IF EXISTS t1; + +CREATE PROCEDURE p1(v DATETIME) CREATE TABLE t1 SELECT v; +CREATE PROCEDURE p2(v INT) CREATE TABLE t1 SELECT v; + +CALL p1(NOW()); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `v` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +DROP TABLE t1; + +CALL p1('text'); +Warnings: +Warning 1264 Out of range value for column 'v' at row 1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `v` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +DROP TABLE t1; + +CALL p2(10); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `v` bigint(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +DROP TABLE t1; + +CALL p2('text'); +Warnings: +Warning 1366 Incorrect integer value: 'text' for column 'v' at row 1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `v` bigint(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +DROP TABLE t1; + +DROP PROCEDURE p1; +DROP PROCEDURE p2; End of 5.0 tests diff --git a/mysql-test/suite/rpl/r/rpl_binlog_grant.result b/mysql-test/suite/rpl/r/rpl_binlog_grant.result new file mode 100644 index 00000000000..1692bcee21f --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_binlog_grant.result @@ -0,0 +1,50 @@ +drop database if exists d1; +create database d1; +use d1; +create table t (s1 int) engine=innodb; +set @@autocommit=0; +start transaction; +insert into t values (1); +grant select on t to x@y; +rollback; +show grants for x@y; +Grants for x@y +GRANT USAGE ON *.* TO 'x'@'y' +GRANT SELECT ON `d1`.`t` TO 'x'@'y' +show binlog events; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 106 Server ver: VERSION, Binlog ver: 4 +master-bin.000001 106 Query 1 193 drop database if exists d1 +master-bin.000001 193 Query 1 272 create database d1 +master-bin.000001 272 Query 1 370 use `d1`; create table t (s1 int) engine=innodb +master-bin.000001 370 Query 1 436 use `d1`; BEGIN +master-bin.000001 436 Query 1 521 use `d1`; insert into t values (1) +master-bin.000001 521 Xid 1 548 COMMIT /* xid=12 */ +master-bin.000001 548 Query 1 633 use `d1`; grant select on t to x@y +start transaction; +insert into t values (2); +revoke select on t from x@y; +commit; +select * from t; +s1 +1 +2 +show grants for x@y; +Grants for x@y +GRANT USAGE ON *.* TO 'x'@'y' +show binlog events; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 106 Server ver: VERSION, Binlog ver: 4 +master-bin.000001 106 Query 1 193 drop database if exists d1 +master-bin.000001 193 Query 1 272 create database d1 +master-bin.000001 272 Query 1 370 use `d1`; create table t (s1 int) engine=innodb +master-bin.000001 370 Query 1 436 use `d1`; BEGIN +master-bin.000001 436 Query 1 521 use `d1`; insert into t values (1) +master-bin.000001 521 Xid 1 548 COMMIT /* xid=12 */ +master-bin.000001 548 Query 1 633 use `d1`; grant select on t to x@y +master-bin.000001 633 Query 1 699 use `d1`; BEGIN +master-bin.000001 699 Query 1 784 use `d1`; insert into t values (2) +master-bin.000001 784 Xid 1 811 COMMIT /* xid=18 */ +master-bin.000001 811 Query 1 899 use `d1`; revoke select on t from x@y +drop user x@y; +drop database d1; diff --git a/mysql-test/suite/rpl/t/rpl_binlog_grant.test b/mysql-test/suite/rpl/t/rpl_binlog_grant.test new file mode 100644 index 00000000000..b6868f7ebf8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_grant.test @@ -0,0 +1,41 @@ +-- source include/have_innodb.inc +-- source include/not_embedded.inc +-- source include/have_binlog_format_mixed_or_statement.inc + +let $VERSION=`select version()`; + +# Bug #21975: grant/revoke statements in transaction +# used to disappear from binlog upon rallback. +# Now GRANT/REVOKE do implicitly commit +# transaction + +--disable_warnings +drop database if exists d1; +--enable_warnings +create database d1; +use d1; +create table t (s1 int) engine=innodb; +set @@autocommit=0; +start transaction; +insert into t values (1); +grant select on t to x@y; +# +# There is no active transaction here +# +rollback; +show grants for x@y; +--replace_result $VERSION VERSION +show binlog events; +start transaction; +insert into t values (2); +revoke select on t from x@y; +# +# There is no active transaction here +# +commit; +select * from t; +show grants for x@y; +--replace_result $VERSION VERSION +show binlog events; +drop user x@y; +drop database d1; diff --git a/mysql-test/t/comments.test b/mysql-test/t/comments.test index 8ae6ba5779e..3a18a8bd483 100644 --- a/mysql-test/t/comments.test +++ b/mysql-test/t/comments.test @@ -34,3 +34,34 @@ select 1/*!999992*/; select 1 + /*!00000 2 */ + 3 /*!99999 noise*/ + 4; +# +# Bug#28779 (mysql_query() allows execution of statements with unbalanced +# comments) +# + +--disable_warnings +drop table if exists table_28779; +--enable_warnings + +create table table_28779 (a int); + +--error 1064 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*' AND b = 'bar';"; + +--error 1064 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*' AND b = 'bar';*"; + +--error 1064 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*! AND 2=2;"; + +--error 1064 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*! AND 2=2;*"; + +--error 1064 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*!98765' AND b = 'bar';"; + +--error 1064 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*!98765' AND b = 'bar';*"; + +drop table table_28779; + diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test index d7232705b81..cbb36cbd2be 100644 --- a/mysql-test/t/events.test +++ b/mysql-test/t/events.test @@ -466,13 +466,17 @@ drop event закачка; set global event_scheduler=1; select get_lock("test_lock2_1", 20); create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20); ---sleep 1 +let $wait_condition= select count(*) = 3 from information_schema.processlist; +--source include/wait_condition.inc --echo "Should have only 3 processes: the scheduler, our conn and the locked event" select /*3*/ user, host, db, command, state, info from information_schema.processlist where (command!='Daemon' || user='event_scheduler') and (info is null or info not like '%processlist%') order by info; set global event_scheduler=off; ---sleep 0.8 +let $wait_condition= select count(*) =1 from information_schema.processlist + where (command!='Daemon' || user='event_scheduler') and (info is null or info not like '%processlist%') order by info; +--source include/wait_condition.inc --echo "Should have only our process now:" select /*4*/ user, host, db, command, state, info from information_schema.processlist where (command!='Daemon' || user='event_scheduler') and (info is null or info not like '%processlist%') order by info; +select release_lock("test_lock2_1"); drop event закачка21; let $wait_condition= select count(*) = 0 from information_schema.processlist diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 16f5fecf051..74944b11c02 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -274,6 +274,11 @@ EOF --exec $MYSQL --pager="540bytelengthstringxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -e "select 1" > /dev/null 2>&1 --exec $MYSQL --character-sets-dir="540bytelengthstringxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -e "select 1" 2>&1 +# +# bug #30164: Using client side macro inside server side comments generates broken queries +# +--exec $MYSQL test -e "/*! \C latin1 */ select 1;" + --echo End of 5.0 tests # diff --git a/mysql-test/t/parser_precedence.test b/mysql-test/t/parser_precedence.test new file mode 100644 index 00000000000..484c8759779 --- /dev/null +++ b/mysql-test/t/parser_precedence.test @@ -0,0 +1,333 @@ + +--disable_warnings +drop table if exists t1_30237_bool; +--enable_warnings + +create table t1_30237_bool(A boolean, B boolean, C boolean); + +insert into t1_30237_bool values +(FALSE, FALSE, FALSE), +(FALSE, FALSE, NULL), +(FALSE, FALSE, TRUE), +(FALSE, NULL, FALSE), +(FALSE, NULL, NULL), +(FALSE, NULL, TRUE), +(FALSE, TRUE, FALSE), +(FALSE, TRUE, NULL), +(FALSE, TRUE, TRUE), +(NULL, FALSE, FALSE), +(NULL, FALSE, NULL), +(NULL, FALSE, TRUE), +(NULL, NULL, FALSE), +(NULL, NULL, NULL), +(NULL, NULL, TRUE), +(NULL, TRUE, FALSE), +(NULL, TRUE, NULL), +(NULL, TRUE, TRUE), +(TRUE, FALSE, FALSE), +(TRUE, FALSE, NULL), +(TRUE, FALSE, TRUE), +(TRUE, NULL, FALSE), +(TRUE, NULL, NULL), +(TRUE, NULL, TRUE), +(TRUE, TRUE, FALSE), +(TRUE, TRUE, NULL), +(TRUE, TRUE, TRUE) ; + +--echo Testing OR, XOR, AND +select A, B, A OR B, A XOR B, A AND B + from t1_30237_bool where C is null order by A, B; + +--echo Testing that OR is associative +select A, B, C, (A OR B) OR C, A OR (B OR C), A OR B OR C + from t1_30237_bool order by A, B, C; + +select count(*) from t1_30237_bool + where ((A OR B) OR C) != (A OR (B OR C)); + +--echo Testing that XOR is associative +select A, B, C, (A XOR B) XOR C, A XOR (B XOR C), A XOR B XOR C + from t1_30237_bool order by A, B, C; + +select count(*) from t1_30237_bool + where ((A XOR B) XOR C) != (A XOR (B XOR C)); + +--echo Testing that AND is associative +select A, B, C, (A AND B) AND C, A AND (B AND C), A AND B AND C + from t1_30237_bool order by A, B, C; + +select count(*) from t1_30237_bool + where ((A AND B) AND C) != (A AND (B AND C)); + +--echo Testing that AND has precedence over OR +select A, B, C, (A OR B) AND C, A OR (B AND C), A OR B AND C + from t1_30237_bool order by A, B, C; +select count(*) from t1_30237_bool + where (A OR (B AND C)) != (A OR B AND C); +select A, B, C, (A AND B) OR C, A AND (B OR C), A AND B OR C + from t1_30237_bool order by A, B, C; +select count(*) from t1_30237_bool + where ((A AND B) OR C) != (A AND B OR C); + +--echo Testing that AND has precedence over XOR +select A, B, C, (A XOR B) AND C, A XOR (B AND C), A XOR B AND C + from t1_30237_bool order by A, B, C; +select count(*) from t1_30237_bool + where (A XOR (B AND C)) != (A XOR B AND C); +select A, B, C, (A AND B) XOR C, A AND (B XOR C), A AND B XOR C + from t1_30237_bool order by A, B, C; +select count(*) from t1_30237_bool + where ((A AND B) XOR C) != (A AND B XOR C); + +--echo Testing that XOR has precedence over OR +select A, B, C, (A XOR B) OR C, A XOR (B OR C), A XOR B OR C + from t1_30237_bool order by A, B, C; +select count(*) from t1_30237_bool + where ((A XOR B) OR C) != (A XOR B OR C); +select A, B, C, (A OR B) XOR C, A OR (B XOR C), A OR B XOR C + from t1_30237_bool order by A, B, C; +select count(*) from t1_30237_bool + where (A OR (B XOR C)) != (A OR B XOR C); + +drop table t1_30237_bool; + +--echo Testing that NOT has precedence over OR +select (NOT FALSE) OR TRUE, NOT (FALSE OR TRUE), NOT FALSE OR TRUE; + +--echo Testing that NOT has precedence over XOR +select (NOT FALSE) XOR FALSE, NOT (FALSE XOR FALSE), NOT FALSE XOR FALSE; + +--echo Testing that NOT has precedence over AND +select (NOT FALSE) AND FALSE, NOT (FALSE AND FALSE), NOT FALSE AND FALSE; + +--echo Testing that NOT is associative +select NOT NOT TRUE, NOT NOT NOT FALSE; + +--echo Testing that IS has precedence over NOT +select (NOT NULL) IS TRUE, NOT (NULL IS TRUE), NOT NULL IS TRUE; +select (NOT NULL) IS NOT TRUE, NOT (NULL IS NOT TRUE), NOT NULL IS NOT TRUE; +select (NOT NULL) IS FALSE, NOT (NULL IS FALSE), NOT NULL IS FALSE; +select (NOT NULL) IS NOT FALSE, NOT (NULL IS NOT FALSE), NOT NULL IS NOT FALSE; +select (NOT TRUE) IS UNKNOWN, NOT (TRUE IS UNKNOWN), NOT TRUE IS UNKNOWN; +select (NOT TRUE) IS NOT UNKNOWN, NOT (TRUE IS NOT UNKNOWN), NOT TRUE IS NOT UNKNOWN; +select (NOT TRUE) IS NULL, NOT (TRUE IS NULL), NOT TRUE IS NULL; +select (NOT TRUE) IS NOT NULL, NOT (TRUE IS NOT NULL), NOT TRUE IS NOT NULL; + +--echo Testing that IS [NOT] TRUE/FALSE/UNKNOWN predicates are not associative +# Documenting existing behavior in 5.0.48 +-- error ER_PARSE_ERROR +select TRUE IS TRUE IS TRUE IS TRUE; +-- error ER_PARSE_ERROR +select FALSE IS NOT TRUE IS NOT TRUE IS NOT TRUE; +-- error ER_PARSE_ERROR +select NULL IS FALSE IS FALSE IS FALSE; +-- error ER_PARSE_ERROR +select TRUE IS NOT FALSE IS NOT FALSE IS NOT FALSE; +-- error ER_PARSE_ERROR +select FALSE IS UNKNOWN IS UNKNOWN IS UNKNOWN; +-- error ER_PARSE_ERROR +select TRUE IS NOT UNKNOWN IS NOT UNKNOWN IS NOT UNKNOWN; + +--echo Testing that IS [NOT] NULL predicates are associative +# Documenting existing behavior in 5.0.48 +select FALSE IS NULL IS NULL IS NULL; +select TRUE IS NOT NULL IS NOT NULL IS NOT NULL; + +--echo Testing that comparison operators are left associative +select 1 <=> 2 <=> 2, (1 <=> 2) <=> 2, 1 <=> (2 <=> 2); +select 1 = 2 = 2, (1 = 2) = 2, 1 = (2 = 2); +select 1 != 2 != 3, (1 != 2) != 3, 1 != (2 != 3); +select 1 <> 2 <> 3, (1 <> 2) <> 3, 1 <> (2 <> 3); +select 1 < 2 < 3, (1 < 2) < 3, 1 < (2 < 3); +select 3 <= 2 <= 1, (3 <= 2) <= 1, 3 <= (2 <= 1); +select 1 > 2 > 3, (1 > 2) > 3, 1 > (2 > 3); +select 1 >= 2 >= 3, (1 >= 2) >= 3, 1 >= (2 >= 3); + +-- echo Testing that | is associative +select 0xF0 | 0x0F | 0x55, (0xF0 | 0x0F) | 0x55, 0xF0 | (0x0F | 0x55); + +-- echo Testing that & is associative +select 0xF5 & 0x5F & 0x55, (0xF5 & 0x5F) & 0x55, 0xF5 & (0x5F & 0x55); + +-- echo Testing that << is left associative +select 4 << 3 << 2, (4 << 3) << 2, 4 << (3 << 2); + +-- echo Testing that >> is left associative +select 256 >> 3 >> 2, (256 >> 3) >> 2, 256 >> (3 >> 2); + +--echo Testing that & has precedence over | +select 0xF0 & 0x0F | 0x55, (0xF0 & 0x0F) | 0x55, 0xF0 & (0x0F | 0x55); +select 0x55 | 0xF0 & 0x0F, (0x55 | 0xF0) & 0x0F, 0x55 | (0xF0 & 0x0F); + +--echo Testing that << has precedence over | +select 0x0F << 4 | 0x0F, (0x0F << 4) | 0x0F, 0x0F << (4 | 0x0F); +select 0x0F | 0x0F << 4, (0x0F | 0x0F) << 4, 0x0F | (0x0F << 4); + +--echo Testing that >> has precedence over | +select 0xF0 >> 4 | 0xFF, (0xF0 >> 4) | 0xFF, 0xF0 >> (4 | 0xFF); +select 0xFF | 0xF0 >> 4, (0xFF | 0xF0) >> 4, 0xFF | (0xF0 >> 4); + +--echo Testing that << has precedence over & +select 0x0F << 4 & 0xF0, (0x0F << 4) & 0xF0, 0x0F << (4 & 0xF0); +select 0xF0 & 0x0F << 4, (0xF0 & 0x0F) << 4, 0xF0 & (0x0F << 4); + +--echo Testing that >> has precedence over & +select 0xF0 >> 4 & 0x55, (0xF0 >> 4) & 0x55, 0xF0 >> (4 & 0x55); +select 0x0F & 0xF0 >> 4, (0x0F & 0xF0) >> 4, 0x0F & (0xF0 >> 4); + +--echo Testing that >> and << have the same precedence +select 0xFF >> 4 << 2, (0xFF >> 4) << 2, 0xFF >> (4 << 2); +select 0x0F << 4 >> 2, (0x0F << 4) >> 2, 0x0F << (4 >> 2); + +--echo Testing that binary + is associative +select 1 + 2 + 3, (1 + 2) + 3, 1 + (2 + 3); + +--echo Testing that binary - is left associative +select 1 - 2 - 3, (1 - 2) - 3, 1 - (2 - 3); + +--echo Testing that binary + and binary - have the same precedence +# evaluated left to right +select 1 + 2 - 3, (1 + 2) - 3, 1 + (2 - 3); +select 1 - 2 + 3, (1 - 2) + 3, 1 - (2 + 3); + +--echo Testing that binary + has precedence over | +select 0xF0 + 0x0F | 0x55, (0xF0 + 0x0F) | 0x55, 0xF0 + (0x0F | 0x55); +select 0x55 | 0xF0 + 0x0F, (0x55 | 0xF0) + 0x0F, 0x55 | (0xF0 + 0x0F); + +--echo Testing that binary + has precedence over & +select 0xF0 + 0x0F & 0x55, (0xF0 + 0x0F) & 0x55, 0xF0 + (0x0F & 0x55); +select 0x55 & 0xF0 + 0x0F, (0x55 & 0xF0) + 0x0F, 0x55 & (0xF0 + 0x0F); + +--echo Testing that binary + has precedence over << +select 2 + 3 << 4, (2 + 3) << 4, 2 + (3 << 4); +select 3 << 4 + 2, (3 << 4) + 2, 3 << (4 + 2); + +--echo Testing that binary + has precedence over >> +select 4 + 3 >> 2, (4 + 3) >> 2, 4 + (3 >> 2); +select 3 >> 2 + 1, (3 >> 2) + 1, 3 >> (2 + 1); + +--echo Testing that binary - has precedence over | +select 0xFF - 0x0F | 0x55, (0xFF - 0x0F) | 0x55, 0xFF - (0x0F | 0x55); +select 0x55 | 0xFF - 0xF0, (0x55 | 0xFF) - 0xF0, 0x55 | (0xFF - 0xF0); + +--echo Testing that binary - has precedence over & +select 0xFF - 0xF0 & 0x55, (0xFF - 0xF0) & 0x55, 0xFF - (0xF0 & 0x55); +select 0x55 & 0xFF - 0xF0, (0x55 & 0xFF) - 0xF0, 0x55 & (0xFF - 0xF0); + +--echo Testing that binary - has precedence over << +select 16 - 3 << 2, (16 - 3) << 2, 16 - (3 << 2); +select 4 << 3 - 2, (4 << 3) - 2, 4 << (3 - 2); + +--echo Testing that binary - has precedence over >> +select 16 - 3 >> 2, (16 - 3) >> 2, 16 - (3 >> 2); +select 16 >> 3 - 2, (16 >> 3) - 2, 16 >> (3 - 2); + +--echo Testing that * is associative +select 2 * 3 * 4, (2 * 3) * 4, 2 * (3 * 4); + +--echo Testing that * has precedence over | +select 2 * 0x40 | 0x0F, (2 * 0x40) | 0x0F, 2 * (0x40 | 0x0F); +select 0x0F | 2 * 0x40, (0x0F | 2) * 0x40, 0x0F | (2 * 0x40); + +--echo Testing that * has precedence over & +select 2 * 0x40 & 0x55, (2 * 0x40) & 0x55, 2 * (0x40 & 0x55); +select 0xF0 & 2 * 0x40, (0xF0 & 2) * 0x40, 0xF0 & (2 * 0x40); + +--echo Testing that * has precedence over << +# Actually, can't prove it for the first case, +# since << is a multiplication by a power of 2, +# and * is associative +select 5 * 3 << 4, (5 * 3) << 4, 5 * (3 << 4); +select 2 << 3 * 4, (2 << 3) * 4, 2 << (3 * 4); + +--echo Testing that * has precedence over >> +# >> is a multiplication by a (negative) power of 2, +# see above. +select 3 * 4 >> 2, (3 * 4) >> 2, 3 * (4 >> 2); +select 4 >> 2 * 3, (4 >> 2) * 3, 4 >> (2 * 3); + +--echo Testing that * has precedence over binary + +select 2 * 3 + 4, (2 * 3) + 4, 2 * (3 + 4); +select 2 + 3 * 4, (2 + 3) * 4, 2 + (3 * 4); + +--echo Testing that * has precedence over binary - +select 4 * 3 - 2, (4 * 3) - 2, 4 * (3 - 2); +select 4 - 3 * 2, (4 - 3) * 2, 4 - (3 * 2); + +--echo Testing that / is left associative +select 15 / 5 / 3, (15 / 5) / 3, 15 / (5 / 3); + +--echo Testing that / has precedence over | +select 105 / 5 | 2, (105 / 5) | 2, 105 / (5 | 2); +select 105 | 2 / 5, (105 | 2) / 5, 105 | (2 / 5); + +--echo Testing that / has precedence over & +select 105 / 5 & 0x0F, (105 / 5) & 0x0F, 105 / (5 & 0x0F); +select 0x0F & 105 / 5, (0x0F & 105) / 5, 0x0F & (105 / 5); + +--echo Testing that / has precedence over << +select 0x80 / 4 << 2, (0x80 / 4) << 2, 0x80 / (4 << 2); +select 0x80 << 4 / 2, (0x80 << 4) / 2, 0x80 << (4 / 2); + +--echo Testing that / has precedence over >> +select 0x80 / 4 >> 2, (0x80 / 4) >> 2, 0x80 / (4 >> 2); +select 0x80 >> 4 / 2, (0x80 >> 4) / 2, 0x80 >> (4 / 2); + +--echo Testing that / has precedence over binary + +select 0x80 / 2 + 2, (0x80 / 2) + 2, 0x80 / (2 + 2); +select 0x80 + 2 / 2, (0x80 + 2) / 2, 0x80 + (2 / 2); + +--echo Testing that / has precedence over binary - +select 0x80 / 4 - 2, (0x80 / 4) - 2, 0x80 / (4 - 2); +select 0x80 - 4 / 2, (0x80 - 4) / 2, 0x80 - (4 / 2); + +# TODO: %, DIV, MOD + +--echo Testing that ^ is associative +select 0xFF ^ 0xF0 ^ 0x0F, (0xFF ^ 0xF0) ^ 0x0F, 0xFF ^ (0xF0 ^ 0x0F); +select 0xFF ^ 0xF0 ^ 0x55, (0xFF ^ 0xF0) ^ 0x55, 0xFF ^ (0xF0 ^ 0x55); + +--echo Testing that ^ has precedence over | +select 0xFF ^ 0xF0 | 0x0F, (0xFF ^ 0xF0) | 0x0F, 0xFF ^ (0xF0 | 0x0F); +select 0xF0 | 0xFF ^ 0xF0, (0xF0 | 0xFF) ^ 0xF0, 0xF0 | (0xFF ^ 0xF0); + +--echo Testing that ^ has precedence over & +select 0xFF ^ 0xF0 & 0x0F, (0xFF ^ 0xF0) & 0x0F, 0xFF ^ (0xF0 & 0x0F); +select 0x0F & 0xFF ^ 0xF0, (0x0F & 0xFF) ^ 0xF0, 0x0F & (0xFF ^ 0xF0); + +--echo Testing that ^ has precedence over << +select 0xFF ^ 0xF0 << 2, (0xFF ^ 0xF0) << 2, 0xFF ^ (0xF0 << 2); +select 0x0F << 2 ^ 0xFF, (0x0F << 2) ^ 0xFF, 0x0F << (2 ^ 0xFF); + +--echo Testing that ^ has precedence over >> +select 0xFF ^ 0xF0 >> 2, (0xFF ^ 0xF0) >> 2, 0xFF ^ (0xF0 >> 2); +select 0xFF >> 2 ^ 0xF0, (0xFF >> 2) ^ 0xF0, 0xFF >> (2 ^ 0xF0); + +--echo Testing that ^ has precedence over binary + +select 0xFF ^ 0xF0 + 0x0F, (0xFF ^ 0xF0) + 0x0F, 0xFF ^ (0xF0 + 0x0F); +select 0x0F + 0xFF ^ 0xF0, (0x0F + 0xFF) ^ 0xF0, 0x0F + (0xFF ^ 0xF0); + +--echo Testing that ^ has precedence over binary - +select 0xFF ^ 0xF0 - 1, (0xFF ^ 0xF0) - 1, 0xFF ^ (0xF0 - 1); +select 0x55 - 0x0F ^ 0x55, (0x55 - 0x0F) ^ 0x55, 0x55 - (0x0F ^ 0x55); + +--echo Testing that ^ has precedence over * +select 0xFF ^ 0xF0 * 2, (0xFF ^ 0xF0) * 2, 0xFF ^ (0xF0 * 2); +select 2 * 0xFF ^ 0xF0, (2 * 0xFF) ^ 0xF0, 2 * (0xFF ^ 0xF0); + +--echo Testing that ^ has precedence over / +select 0xFF ^ 0xF0 / 2, (0xFF ^ 0xF0) / 2, 0xFF ^ (0xF0 / 2); +select 0xF2 / 2 ^ 0xF0, (0xF2 / 2) ^ 0xF0, 0xF2 / (2 ^ 0xF0); + +--echo Testing that ^ has precedence over % +select 0xFF ^ 0xF0 % 0x20, (0xFF ^ 0xF0) % 0x20, 0xFF ^ (0xF0 % 0x20); +select 0xFF % 0x20 ^ 0xF0, (0xFF % 0x20) ^ 0xF0, 0xFF % (0x20 ^ 0xF0); + +--echo Testing that ^ has precedence over DIV +select 0xFF ^ 0xF0 DIV 2, (0xFF ^ 0xF0) DIV 2, 0xFF ^ (0xF0 DIV 2); +select 0xF2 DIV 2 ^ 0xF0, (0xF2 DIV 2) ^ 0xF0, 0xF2 DIV (2 ^ 0xF0); + +--echo Testing that ^ has precedence over MOD +select 0xFF ^ 0xF0 MOD 0x20, (0xFF ^ 0xF0) MOD 0x20, 0xFF ^ (0xF0 MOD 0x20); +select 0xFF MOD 0x20 ^ 0xF0, (0xFF MOD 0x20) ^ 0xF0, 0xFF MOD (0x20 ^ 0xF0); + diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index ef9bed8b789..012f2b33225 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1387,6 +1387,21 @@ CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create user 'mysqltest CREATE FUNCTION bug_13627_f() returns int BEGIN create user 'mysqltest_1'; return 1; END | -- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN grant select on t1 to 'mysqltest_1'; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug21975() returns int BEGIN grant select on t1 to 'mysqltest_1'; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN revoke select on t1 from 'mysqltest_1'; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug21975() returns int BEGIN revoke select on t1 from 'mysqltest_1'; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN revoke all privileges on *.* from 'mysqltest_1'; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug21975() returns int BEGIN revoke all privileges on *.* from 'mysqltest_1'; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop user 'mysqltest_1'; END | -- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG CREATE FUNCTION bug_13627_f() returns int BEGIN drop user 'mysqltest_1'; return 1; END | diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 46ef6bc6ddd..1c8f1ca51c2 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7494,4 +7494,123 @@ DROP FUNCTION f1; DROP FUNCTION f2; DROP TABLE t1; +# +# Bug#29936 Stored Procedure DML ignores low_priority_updates setting +# + +--disable_warnings +drop table if exists t1; +drop procedure if exists p1; +--enable_warnings + +create table t1 (value varchar(15)); +create procedure p1() update t1 set value='updated' where value='old'; + +# load the procedure into sp cache and execute once +call p1(); + +insert into t1 (value) values ("old"); + +connect (rl_holder, localhost, root,,); +connect (rl_acquirer, localhost, root,,); +connect (rl_contender, localhost, root,,); +connect (rl_wait, localhost, root,,); + +connection rl_holder; +select get_lock('b26162',120); + +connection rl_acquirer; +--send select 'rl_acquirer', value from t1 where get_lock('b26162',120); + +# we must wait till this select opens and locks the tables +connection rl_wait; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "User lock" and + info = "select 'rl_acquirer', value from t1 where get_lock('b26162',120)"; +--source include/wait_condition.inc + +connection default; +set session low_priority_updates=on; +--send call p1(); + +connection rl_wait; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Locked" and + info = "update t1 set value='updated' where value='old'"; +--source include/wait_condition.inc + +connection rl_contender; +select 'rl_contender', value from t1; + +connection rl_holder; +select release_lock('b26162'); + +connection rl_acquirer; +--reap +connection default; +--reap + +disconnect rl_holder; +disconnect rl_acquirer; +disconnect rl_wait; +drop procedure p1; +drop table t1; +set session low_priority_updates=default; + +# +# Bug#13675: DATETIME/DATE type in store proc param seems to be converted as +# varbinary +# + +--echo +--echo # Bug#13675. +--echo + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; + +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo + +CREATE PROCEDURE p1(v DATETIME) CREATE TABLE t1 SELECT v; + +CREATE PROCEDURE p2(v INT) CREATE TABLE t1 SELECT v; + +--echo +CALL p1(NOW()); +SHOW CREATE TABLE t1; + +--echo +DROP TABLE t1; + +--echo +CALL p1('text'); +SHOW CREATE TABLE t1; + +--echo +DROP TABLE t1; + +--echo +CALL p2(10); +SHOW CREATE TABLE t1; + +--echo +DROP TABLE t1; + +--echo +CALL p2('text'); +SHOW CREATE TABLE t1; + +--echo +DROP TABLE t1; + +--echo +DROP PROCEDURE p1; +DROP PROCEDURE p2; + --echo End of 5.0 tests diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 4015e5618e8..40d0c2dfe91 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1424,6 +1424,7 @@ public: Item_cond(List<Item> &nlist) :Item_bool_func(), list(nlist), abort_on_null(0) {} bool add(Item *item) { return list.push_back(item); } + bool add_at_head(Item *item) { return list.push_front(item); } void add_at_head(List<Item> *nlist) { list.prepand(nlist); } bool fix_fields(THD *, Item **ref); @@ -1616,6 +1617,15 @@ public: Item *neg_transformer(THD *thd); }; +inline bool is_cond_and(Item *item) +{ + if (item->type() != Item::COND_ITEM) + return FALSE; + + Item_cond *cond_item= (Item_cond*) item; + return (cond_item->functype() == Item_func::COND_AND_FUNC); +} + class Item_cond_or :public Item_cond { public: @@ -1637,6 +1647,14 @@ public: Item *neg_transformer(THD *thd); }; +inline bool is_cond_or(Item *item) +{ + if (item->type() != Item::COND_ITEM) + return FALSE; + + Item_cond *cond_item= (Item_cond*) item; + return (cond_item->functype() == Item_func::COND_OR_FUNC); +} /* XOR is Item_cond, not an Item_int_func because we could like to diff --git a/sql/lock.cc b/sql/lock.cc index d9e9dd31f81..29a07858bc1 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -276,6 +276,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, thd->lock_id)]; if (rc > 1) /* a timeout or a deadlock */ { + if (sql_lock->table_count) + VOID(unlock_external(thd, sql_lock->table, sql_lock->table_count)); my_error(rc, MYF(0)); my_free((uchar*) sql_lock,MYF(0)); sql_lock= 0; diff --git a/sql/sp.cc b/sql/sp.cc index 437ffb3b484..4828618c0cb 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -575,7 +575,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, we'll update it later in switch_query_ctx(). */ - if ((ret= sp_use_new_db(thd, name->m_db, &old_db, 1, &dbchanged))) + if ((ret= sp_use_new_db(thd, name->m_db, &old_db, TRUE, &dbchanged))) goto end; thd->spcont= NULL; @@ -2028,34 +2028,41 @@ create_string(THD *thd, String *buf, -/* +/** Change the current database if needed. - SYNOPSIS - sp_use_new_db() - thd thread handle - new_db new database name (a string and its length) - old_db [IN] str points to a buffer where to store the old - database, length contains the size of the buffer - [OUT] if old db was not NULL, its name is copied - to the buffer pointed at by str and length is updated - accordingly. Otherwise str[0] is set to '\0' and length - is set to 0. The out parameter should be used only if - the database name has been changed (see dbchangedp). - dbchangedp [OUT] is set to TRUE if the current database is changed, - FALSE otherwise. A database is not changed if the old - name is the same as the new one, both names are empty, - or an error has occurred. - - RETURN VALUE - 0 success - 1 access denied or out of memory (the error message is - set in THD) + @param[in] thd thread handle + @param[in] new_db new database name + @param[in, out] old_db IN: str points to a buffer where to store + the old database, length contains the + size of the buffer + OUT: if old db was not NULL, its name is + copied to the buffer pointed at by str + and length is updated accordingly. + Otherwise str[0] is set to '\0' and + length is set to 0. The out parameter + should be used only if the database name + has been changed (see dbchangedp). + @param[in] force_switch Flag to mysql_change_db(). For more information, + see mysql_change_db() comment. + @param[out] dbchangedp is set to TRUE if the current database is + changed, FALSE otherwise. The current + database is not changed if the old name + is equal to the new one, both names are + empty, or an error has occurred. + + @return Operation status. + @retval 0 on success + @retval 1 access denied or out of memory + (the error message is set in THD) */ int -sp_use_new_db(THD *thd, LEX_STRING new_db, LEX_STRING *old_db, - bool no_access_check, bool *dbchangedp) +sp_use_new_db(THD *thd, + LEX_STRING new_db, + LEX_STRING *old_db, + bool force_switch, + bool *dbchangedp) { int ret; DBUG_ENTER("sp_use_new_db"); @@ -2086,7 +2093,7 @@ sp_use_new_db(THD *thd, LEX_STRING new_db, LEX_STRING *old_db, DBUG_RETURN(0); } - ret= mysql_change_db(thd, &new_db, no_access_check); + ret= mysql_change_db(thd, &new_db, force_switch); *dbchangedp= ret == 0; DBUG_RETURN(ret); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index b8535ee9958..e9275dff9e3 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -249,11 +249,14 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_CREATE_TRIGGER: case SQLCOM_CREATE_USER: case SQLCOM_ALTER_TABLE: + case SQLCOM_GRANT: + case SQLCOM_REVOKE: case SQLCOM_BEGIN: case SQLCOM_RENAME_TABLE: case SQLCOM_RENAME_USER: case SQLCOM_DROP_INDEX: case SQLCOM_DROP_DB: + case SQLCOM_REVOKE_ALL: case SQLCOM_DROP_USER: case SQLCOM_DROP_VIEW: case SQLCOM_DROP_TRIGGER: diff --git a/sql/sql_class.h b/sql/sql_class.h index 7117c08a7e1..0a3aa3ed20c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1802,11 +1802,27 @@ public: } } - /* - Initialize the current database from a NULL-terminated string with length - If we run out of memory, we free the current database and return TRUE. - This way the user will notice the error as there will be no current - database selected (in addition to the error message set by malloc). + /** + Set the current database; use deep copy of C-string. + + @param new_db a pointer to the new database name. + @param new_db_len length of the new database name. + + Initialize the current database from a NULL-terminated string with + length. If we run out of memory, we free the current database and + return TRUE. This way the user will notice the error as there will be + no current database selected (in addition to the error message set by + malloc). + + @note This operation just sets {thd->db, thd->db_length}. Switching the + current database usually involves other actions, like switching other + database attributes including security context. In the future, this + operation will be made private and more convenient interface will be + provided. + + @return Operation status + @retval FALSE Success + @retval TRUE Out-of-memory error */ bool set_db(const char *new_db, size_t new_db_len) { @@ -1821,6 +1837,19 @@ public: db_length= db ? new_db_len : 0; return new_db && !db; } + + /** + Set the current database; use shallow copy of C-string. + + @param new_db a pointer to the new database name. + @param new_db_len length of the new database name. + + @note This operation just sets {thd->db, thd->db_length}. Switching the + current database usually involves other actions, like switching other + database attributes including security context. In the future, this + operation will be made private and more convenient interface will be + provided. + */ void reset_db(char *new_db, size_t new_db_len) { db= new_db; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 15506fcbc80..9b6aa564128 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -39,6 +39,10 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, static long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path); static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error); +static void mysql_change_db_impl(THD *thd, + LEX_STRING *new_db_name, + ulong new_db_access, + CHARSET_INFO *new_db_charset); /* Database lock hash */ @@ -997,7 +1001,7 @@ exit: it to 0. */ if (thd->db && !strcmp(thd->db, db)) - thd->set_db(NULL, 0); + mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server); VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); start_waiting_global_read_lock(thd); exit2: @@ -1356,21 +1360,48 @@ static void mysql_change_db_impl(THD *thd, /** - @brief Change the current database. + @brief Change the current database and its attributes. @param thd thread handle @param new_db_name database name - @param force_switch if this flag is set (TRUE), mysql_change_db() will - switch to NULL db if the specified database is not - available anymore. Corresponding warning will be - thrown in this case. This flag is used to change - database in stored-routine-execution code. - - @details Check that the database name corresponds to a valid and existent - database, check access rights (unless called with no_access_check), and - set the current database. This function is called to change the current - database upon user request (COM_CHANGE_DB command) or temporarily, to - execute a stored routine. + @param force_switch if force_switch is FALSE, then the operation will fail if + + - new_db_name is NULL or empty; + + - OR new database name is invalid + (check_db_name() failed); + + - OR user has no privilege on the new database; + + - OR new database does not exist; + + if force_switch is TRUE, then + + - if new_db_name is NULL or empty, the current + database will be NULL, @@collation_database will + be set to @@collation_server, the operation will + succeed. + + - if new database name is invalid + (check_db_name() failed), the current database + will be NULL, @@collation_database will be set to + @@collation_server, but the operation will fail; + + - user privileges will not be checked + (THD::db_access however is updated); + + TODO: is this really the intention? + (see sp-security.test). + + - if new database does not exist,the current database + will be NULL, @@collation_database will be set to + @@collation_server, a warning will be thrown, the + operation will succeed. + + @details The function checks that the database name corresponds to a + valid and existent database, checks access rights and changes the current + database with database attributes (@@collation_database session variable, + THD::db_access). This function is not the only way to switch the database that is currently employed. When the replication slave thread switches the @@ -1407,8 +1438,13 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) if (force_switch) { /* - This can only happen when we restore the old db in THD after - execution of a routine is complete. Change db to NULL. + This can happen only if we're switching the current database back + after loading stored program. The thing is that loading of stored + program can happen when there is no current database. + + TODO: actually, new_db_name and new_db_name->str seem to be always + non-NULL. In case of stored program, new_db_name->str == "" and + new_db_name->length == 0. */ mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server); @@ -1426,7 +1462,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) if (my_strcasecmp(system_charset_info, new_db_name->str, INFORMATION_SCHEMA_NAME.str) == 0) { - /* Switch database to INFORMATION_SCHEMA. */ + /* Switch the current database to INFORMATION_SCHEMA. */ mysql_change_db_impl(thd, &INFORMATION_SCHEMA_NAME, SELECT_ACL, system_charset_info); @@ -1453,8 +1489,8 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) even if we are called from sp_head::execute(). It's next to impossible however to get this error when we are called - from sp_head::execute(). But let's switch database to NULL in this case - to be sure. + from sp_head::execute(). But let's switch the current database to NULL + in this case to be sure. */ if (check_db_name(&new_db_file_name)) @@ -1463,10 +1499,8 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) my_free(new_db_file_name.str, MYF(0)); if (force_switch) - { - /* Change db to NULL. */ mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server); - } + DBUG_RETURN(TRUE); } @@ -1501,6 +1535,8 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) { if (force_switch) { + /* Throw a warning and free new_db_file_name. */ + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR), new_db_file_name.str); @@ -1511,12 +1547,19 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server); + /* The operation succeed. */ + DBUG_RETURN(FALSE); } else { + /* Report an error and free new_db_file_name. */ + my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str); my_free(new_db_file_name.str, MYF(0)); + + /* The operation failed. */ + DBUG_RETURN(TRUE); } } @@ -1829,7 +1872,7 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) /* Step9: Let's do "use newdb" if we renamed the current database */ if (change_to_newdb) - error|= mysql_change_db(thd, new_db, 0); + error|= mysql_change_db(thd, new_db, FALSE); exit: pthread_mutex_lock(&LOCK_lock_db); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 8b9896870c0..1adce48c539 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -444,7 +444,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, cond->cleanup(); // File was reopened if ((!cond->fixed && cond->fix_fields(thd, &cond)) || cond->check_cols(1)) - goto err0; + goto err; } if (keyname) @@ -452,13 +452,13 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, if ((keyno=find_type(keyname, &table->s->keynames, 1+2)-1)<0) { my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), keyname, tables->alias); - goto err0; + goto err; } } if (insert_fields(thd, &thd->lex->select_lex.context, tables->db, tables->alias, &it, 0)) - goto err0; + goto err; protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 66f5540d286..6b94505e46e 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -323,7 +323,6 @@ void lex_start(THD *thd) lex->length=0; lex->part_info= 0; lex->select_lex.in_sum_expr=0; - lex->select_lex.expr_list.empty(); lex->select_lex.ftfunc_list_alloc.empty(); lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc; lex->select_lex.group_list.empty(); @@ -720,6 +719,7 @@ static inline uint int_token(const char *str,uint length) int MYSQLlex(void *arg, void *yythd) { reg1 uchar c; + bool comment_closed; int tokval, result_state; uint length; enum my_lex_states state; @@ -1212,7 +1212,10 @@ int MYSQLlex(void *arg, void *yythd) /* The special comment format is very strict: '/' '*' '!', followed by exactly - 2 digits (major), then 3 digits (minor). + 1 digit (major), 2 digits (minor), then 2 digits (dot). + 32302 -> 3.23.02 + 50032 -> 5.0.32 + 50114 -> 5.1.14 */ char version_str[6]; version_str[0]= lip->yyPeekn(0); @@ -1231,7 +1234,7 @@ int MYSQLlex(void *arg, void *yythd) ulong version; version=strtol(version_str, NULL, 10); - /* Accept 'M' 'M' 'm' 'm' 'm' */ + /* Accept 'M' 'm' 'm' 'd' 'd' */ lip->yySkipn(5); if (version <= MYSQL_VERSION_ID) @@ -1255,16 +1258,36 @@ int MYSQLlex(void *arg, void *yythd) lip->yySkip(); // Accept / lip->yySkip(); // Accept * } - - while (! lip->eof() && - ((c=lip->yyGet()) != '*' || lip->yyPeek() != '/')) + /* + Discard: + - regular '/' '*' comments, + - special comments '/' '*' '!' for a future version, + by scanning until we find a closing '*' '/' marker. + Note: There is no such thing as nesting comments, + the first '*' '/' sequence seen will mark the end. + */ + comment_closed= FALSE; + while (! lip->eof()) { - if (c == '\n') + c= lip->yyGet(); + if (c == '*') + { + if (lip->yyPeek() == '/') + { + lip->yySkip(); + comment_closed= TRUE; + state = MY_LEX_START; + break; + } + } + else if (c == '\n') lip->yylineno++; } - if (! lip->eof()) - lip->yySkip(); // remove last '/' + /* Unbalanced comments with a missing '*' '/' are a syntax error */ + if (! comment_closed) + return (ABORT_SYM); state = MY_LEX_START; // Try again + lip->in_comment= NO_COMMENT; lip->set_echo(TRUE); break; case MY_LEX_END_LONG_COMMENT: @@ -1316,6 +1339,9 @@ int MYSQLlex(void *arg, void *yythd) lip->set_echo(FALSE); lip->yySkip(); lip->set_echo(TRUE); + /* Unbalanced comments with a missing '*' '/' are a syntax error */ + if (lip->in_comment != NO_COMMENT) + return (ABORT_SYM); lip->next_state=MY_LEX_END; // Mark for next loop return(END_OF_INPUT); } @@ -1556,7 +1582,6 @@ void st_select_lex::init_select() options= 0; sql_cache= SQL_CACHE_UNSPECIFIED; braces= 0; - expr_list.empty(); interval_list.empty(); ftfunc_list_alloc.empty(); inner_sum_func_list= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 057d59d3ccf..da0134a7f72 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -596,7 +596,6 @@ public: const char *type; /* type of select for EXPLAIN */ SQL_LIST order_list; /* ORDER clause */ - List<List_item> expr_list; SQL_LIST *gorder_list; Item *select_limit, *offset_limit; /* LIMIT clause parameters */ // Arrays of pointers to top elements of all_fields list diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2e4ce65f1c4..bbd6cb16d11 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3381,6 +3381,8 @@ end_with_restore_list: } case SQLCOM_REVOKE_ALL: { + if (end_active_trans(thd)) + goto error; if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) && check_global_access(thd,CREATE_USER_ACL)) break; @@ -3392,6 +3394,9 @@ end_with_restore_list: case SQLCOM_REVOKE: case SQLCOM_GRANT: { + if (end_active_trans(thd)) + goto error; + if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL, first_table ? first_table->db : select_lex->db, first_table ? &first_table->grant.privilege : 0, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2d6baf5b846..efd8c20e6d7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -31,7 +31,7 @@ #define MYSQL_YACC #define YYINITDEPTH 100 -#define YYMAXDEPTH 3200 /* Because of 64K stack */ +#define YYMAXDEPTH 3200 /* Because of 64K stack */ #define Lex (YYTHD->lex) #define Select Lex->current_select #include "mysql_priv.h" @@ -506,12 +506,12 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %} -%pure_parser /* We have threads */ +%pure_parser /* We have threads */ /* - Currently there is 286 shift/reduce conflict. We should not introduce - new conflicts any more. + Currently there are 280 shift/reduce conflicts. + We should not introduce new conflicts any more. */ -%expect 286 +%expect 280 /* Comments for TOKENS. @@ -1091,7 +1091,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); /* A dummy token to force the priority of table_ref production in a join. */ %left TABLE_REF_PRIORITY %left SET_VAR -%left OR_OR_SYM OR_SYM OR2_SYM XOR +%left OR_OR_SYM OR_SYM OR2_SYM +%left XOR %left AND_SYM AND_AND_SYM %left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE %left EQ EQUAL_SYM GE GT_SYM LE LT NE IS LIKE REGEXP IN_SYM @@ -1104,6 +1105,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %left NEG '~' %right NOT_SYM NOT2_SYM %right BINARY COLLATE_SYM +%left INTERVAL_SYM %type <lex_str> IDENT IDENT_QUOTED TEXT_STRING DECIMAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM @@ -1152,8 +1154,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <item> literal text_literal insert_ident order_ident simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr - variable variable_aux bool_term bool_factor bool_test bool_pri - predicate bit_expr bit_term bit_factor value_expr term factor + variable variable_aux bool_pri + predicate bit_expr table_wild simple_expr udf_expr expr_or_default set_expr_or_default interval_expr param_marker geometry_function @@ -1171,7 +1173,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); NUM_literal %type <item_list> - expr_list udf_expr_list udf_expr_list2 when_list + expr_list opt_udf_expr_list udf_expr_list when_list ident_list ident_list_arg opt_expr_list %type <var_type> @@ -1245,7 +1247,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); select_item_list select_item values_list no_braces opt_limit_clause delete_limit_clause fields opt_values values procedure_list procedure_list2 procedure_item - expr_list2 udf_expr_list3 handler + handler opt_precision opt_ignore opt_column opt_restrict grant revoke set lock unlock string_list field_options field_option field_opt_list opt_binary table_lock_list table_lock @@ -1315,10 +1317,11 @@ rule: <-- starts at col 1 } ; <-- on a line by itself, starts at col 9 -Also, please do not use any <TAB>, but spaces. -Having a uniform indentation in this file helps -code reviews, patches, merges, and make maintenance easier. -Thanks. + Also, please do not use any <TAB>, but spaces. + Having a uniform indentation in this file helps + code reviews, patches, merges, and make maintenance easier. + Tip: grep [[:cntrl:]] sql_yacc.yy + Thanks. */ query: @@ -5157,7 +5160,7 @@ opt_bin_charset: MYSQL_YYABORT; } } - | charset charset_name { Lex->charset=$2; } + | charset charset_name { Lex->charset=$2; } ; opt_primary: @@ -5379,7 +5382,7 @@ alter: lex->create_info.row_type= ROW_TYPE_NOT_USED; lex->alter_info.reset(); lex->no_write_to_binlog= 0; - lex->create_info.storage_media= HA_SM_DEFAULT; + lex->create_info.storage_media= HA_SM_DEFAULT; } alter_commands {} @@ -6564,83 +6567,131 @@ optional_braces: ; /* all possible expressions */ -expr: - bool_term { Select->expr_list.push_front(new List<Item>); } - bool_or_expr +expr: + expr or expr %prec OR_SYM { - List<Item> *list= Select->expr_list.pop(); - if (list->elements) + /* + Design notes: + Do not use a manually maintained stack like thd->lex->xxx_list, + but use the internal bison stack ($$, $1 and $3) instead. + Using the bison stack is: + - more robust to changes in the grammar, + - guaranteed to be in sync with the parser state, + - better for performances (no memory allocation). + */ + Item_cond_or *item1; + Item_cond_or *item3; + if (is_cond_or($1)) { - list->push_front($1); - $$= new Item_cond_or(*list); - /* optimize construction of logical OR to reduce - amount of objects for complex expressions */ + item1= (Item_cond_or*) $1; + if (is_cond_or($3)) + { + item3= (Item_cond_or*) $3; + /* + (X1 OR X2) OR (Y1 OR Y2) ==> OR (X1, X2, Y1, Y2) + */ + item3->add_at_head(item1->argument_list()); + $$ = $3; + } + else + { + /* + (X1 OR X2) OR Y ==> OR (X1, X2, Y) + */ + item1->add($3); + $$ = $1; + } + } + else if (is_cond_or($3)) + { + item3= (Item_cond_or*) $3; + /* + X OR (Y1 OR Y2) ==> OR (X, Y1, Y2) + */ + item3->add_at_head($1); + $$ = $3; } else - $$= $1; - delete list; + { + /* X OR Y */ + $$ = new (YYTHD->mem_root) Item_cond_or($1, $3); + } } - ; - -bool_or_expr: - /* empty */ - | bool_or_expr or bool_term - { Select->expr_list.head()->push_back($3); } - ; - -bool_term: - bool_term XOR bool_term { $$= new Item_cond_xor($1,$3); } - | bool_factor { Select->expr_list.push_front(new List<Item>); } - bool_and_expr + | expr XOR expr %prec XOR + { + /* XOR is a proprietary extension */ + $$ = new (YYTHD->mem_root) Item_cond_xor($1, $3); + } + | expr and expr %prec AND_SYM { - List<Item> *list= Select->expr_list.pop(); - if (list->elements) + /* See comments in rule expr: expr or expr */ + Item_cond_and *item1; + Item_cond_and *item3; + if (is_cond_and($1)) { - list->push_front($1); - $$= new Item_cond_and(*list); - /* optimize construction of logical AND to reduce - amount of objects for complex expressions */ + item1= (Item_cond_and*) $1; + if (is_cond_and($3)) + { + item3= (Item_cond_and*) $3; + /* + (X1 AND X2) AND (Y1 AND Y2) ==> AND (X1, X2, Y1, Y2) + */ + item3->add_at_head(item1->argument_list()); + $$ = $3; + } + else + { + /* + (X1 AND X2) AND Y ==> AND (X1, X2, Y) + */ + item1->add($3); + $$ = $1; + } + } + else if (is_cond_and($3)) + { + item3= (Item_cond_and*) $3; + /* + X AND (Y1 AND Y2) ==> AND (X, Y1, Y2) + */ + item3->add_at_head($1); + $$ = $3; } else - $$= $1; - delete list; + { + /* X AND Y */ + $$ = new (YYTHD->mem_root) Item_cond_and($1, $3); + } } - ; - -bool_and_expr: - /* empty */ - | bool_and_expr and bool_factor - { Select->expr_list.head()->push_back($3); } - ; - -bool_factor: - NOT_SYM bool_factor { $$= negate_expression(YYTHD, $2); } - | bool_test - ; - -bool_test: - bool_pri IS TRUE_SYM + | NOT_SYM expr %prec NOT_SYM + { $$= negate_expression(YYTHD, $2); } + | bool_pri IS TRUE_SYM %prec IS { $$= new (YYTHD->mem_root) Item_func_istrue($1); } - | bool_pri IS not TRUE_SYM + | bool_pri IS not TRUE_SYM %prec IS { $$= new (YYTHD->mem_root) Item_func_isnottrue($1); } - | bool_pri IS FALSE_SYM + | bool_pri IS FALSE_SYM %prec IS { $$= new (YYTHD->mem_root) Item_func_isfalse($1); } - | bool_pri IS not FALSE_SYM + | bool_pri IS not FALSE_SYM %prec IS { $$= new (YYTHD->mem_root) Item_func_isnotfalse($1); } - | bool_pri IS UNKNOWN_SYM { $$= new Item_func_isnull($1); } - | bool_pri IS not UNKNOWN_SYM { $$= new Item_func_isnotnull($1); } + | bool_pri IS UNKNOWN_SYM %prec IS + { $$= new Item_func_isnull($1); } + | bool_pri IS not UNKNOWN_SYM %prec IS + { $$= new Item_func_isnotnull($1); } | bool_pri ; bool_pri: - bool_pri IS NULL_SYM { $$= new Item_func_isnull($1); } - | bool_pri IS not NULL_SYM { $$= new Item_func_isnotnull($1); } - | bool_pri EQUAL_SYM predicate { $$= new Item_func_equal($1,$3); } + bool_pri IS NULL_SYM %prec IS + { $$= new Item_func_isnull($1); } + | bool_pri IS not NULL_SYM %prec IS + { $$= new Item_func_isnotnull($1); } + | bool_pri EQUAL_SYM predicate %prec EQUAL_SYM + { $$= new Item_func_equal($1,$3); } | bool_pri comp_op predicate %prec EQ { $$= (*$2)(0)->create($1,$3); } | bool_pri comp_op all_or_any '(' subselect ')' %prec EQ { $$= all_any_subquery_creator($1, $2, $3, $5); } - | predicate + | predicate ; ; predicate: @@ -6700,44 +6751,34 @@ predicate: ; bit_expr: - bit_expr '|' bit_term { $$= new Item_func_bit_or($1,$3); } - | bit_term - ; - -bit_term: - bit_term '&' bit_factor { $$= new Item_func_bit_and($1,$3); } - | bit_factor - ; - -bit_factor: - bit_factor SHIFT_LEFT value_expr + bit_expr '|' bit_expr %prec '|' + { $$= new Item_func_bit_or($1,$3); } + | bit_expr '&' bit_expr %prec '&' + { $$= new Item_func_bit_and($1,$3); } + | bit_expr SHIFT_LEFT bit_expr %prec SHIFT_LEFT { $$= new Item_func_shift_left($1,$3); } - | bit_factor SHIFT_RIGHT value_expr + | bit_expr SHIFT_RIGHT bit_expr %prec SHIFT_RIGHT { $$= new Item_func_shift_right($1,$3); } - | value_expr - ; - -value_expr: - value_expr '+' term { $$= new Item_func_plus($1,$3); } - | value_expr '-' term { $$= new Item_func_minus($1,$3); } - | value_expr '+' interval_expr interval + | bit_expr '+' bit_expr %prec '+' + { $$= new Item_func_plus($1,$3); } + | bit_expr '-' bit_expr %prec '-' + { $$= new Item_func_minus($1,$3); } + | bit_expr '+' interval_expr interval %prec '+' { $$= new Item_date_add_interval($1,$3,$4,0); } - | value_expr '-' interval_expr interval + | bit_expr '-' interval_expr interval %prec '-' { $$= new Item_date_add_interval($1,$3,$4,1); } - | term - ; - -term: - term '*' factor { $$= new Item_func_mul($1,$3); } - | term '/' factor { $$= new Item_func_div($1,$3); } - | term '%' factor { $$= new Item_func_mod($1,$3); } - | term DIV_SYM factor { $$= new Item_func_int_div($1,$3); } - | term MOD_SYM factor { $$= new Item_func_mod($1,$3); } - | factor - ; - -factor: - factor '^' simple_expr { $$= new Item_func_bit_xor($1,$3); } + | bit_expr '*' bit_expr %prec '*' + { $$= new Item_func_mul($1,$3); } + | bit_expr '/' bit_expr %prec '/' + { $$= new Item_func_div($1,$3); } + | bit_expr '%' bit_expr %prec '%' + { $$= new Item_func_mod($1,$3); } + | bit_expr DIV_SYM bit_expr %prec DIV_SYM + { $$= new Item_func_int_div($1,$3); } + | bit_expr MOD_SYM bit_expr %prec MOD_SYM + { $$= new Item_func_mod($1,$3); } + | bit_expr '^' bit_expr + { $$= new Item_func_bit_xor($1,$3); } | simple_expr ; @@ -6776,7 +6817,8 @@ all_or_any: ; interval_expr: - INTERVAL_SYM expr { $$=$2; } + INTERVAL_SYM expr %prec INTERVAL_SYM + { $$=$2; } ; simple_expr: @@ -6799,7 +6841,7 @@ simple_expr: | sum_expr | simple_expr OR_OR_SYM simple_expr { $$= new (YYTHD->mem_root) Item_func_concat($1, $3); } - | '+' simple_expr %prec NEG { $$= $2; } + | '+' simple_expr %prec NEG { $$= $2; } | '-' simple_expr %prec NEG { $$= new (YYTHD->mem_root) Item_func_neg($2); } | '~' simple_expr %prec NEG @@ -7210,7 +7252,7 @@ function_call_generic: $<udf>$= udf; #endif } - udf_expr_list ')' + opt_udf_expr_list ')' { THD *thd= YYTHD; Create_func *builder; @@ -7307,27 +7349,23 @@ opt_query_expansion: | WITH QUERY_SYM EXPANSION_SYM { $$= FT_EXPAND; } ; +opt_udf_expr_list: + /* empty */ { $$= NULL; } + | udf_expr_list { $$= $1; } + ; + udf_expr_list: - /* empty */ { $$= NULL; } - | udf_expr_list2 { $$= $1;} - ; - -udf_expr_list2: - { Select->expr_list.push_front(new List<Item>); } - udf_expr_list3 - { $$= Select->expr_list.pop(); } - ; - -udf_expr_list3: - udf_expr - { - Select->expr_list.head()->push_back($1); - } - | udf_expr_list3 ',' udf_expr - { - Select->expr_list.head()->push_back($3); - } - ; + udf_expr + { + $$= new (YYTHD->mem_root) List<Item>; + $$->push_back($1); + } + | udf_expr_list ',' udf_expr + { + $1->push_back($3); + $$= $1; + } + ; udf_expr: remember_name expr remember_end select_alias @@ -7525,13 +7563,17 @@ opt_expr_list: ; expr_list: - { Select->expr_list.push_front(new List<Item>); } - expr_list2 - { $$= Select->expr_list.pop(); }; - -expr_list2: - expr { Select->expr_list.head()->push_back($1); } - | expr_list2 ',' expr { Select->expr_list.head()->push_back($3); }; + expr + { + $$= new (YYTHD->mem_root) List<Item>; + $$->push_back($1); + } + | expr_list ',' expr + { + $1->push_back($3); + $$= $1; + } + ; ident_list_arg: ident_list { $$= $1; } @@ -7539,13 +7581,17 @@ ident_list_arg: ; ident_list: - { Select->expr_list.push_front(new List<Item>); } - ident_list2 - { $$= Select->expr_list.pop(); }; - -ident_list2: - simple_ident { Select->expr_list.head()->push_back($1); } - | ident_list2 ',' simple_ident { Select->expr_list.head()->push_back($3); }; + simple_ident + { + $$= new (YYTHD->mem_root) List<Item>; + $$->push_back($1); + } + | ident_list ',' simple_ident + { + $1->push_back($3); + $$= $1; + } + ; opt_expr: /* empty */ { $$= NULL; } |