diff options
-rwxr-xr-x | BUILD/SETUP.sh | 25 | ||||
-rwxr-xr-x | BUILD/compile-amd64-gcov | 17 | ||||
-rwxr-xr-x | BUILD/compile-amd64-gprof | 9 | ||||
-rwxr-xr-x | BUILD/compile-pentium-gcov | 13 | ||||
-rwxr-xr-x | BUILD/compile-pentium-gprof | 4 | ||||
-rwxr-xr-x | BUILD/compile-pentium64-gcov | 17 | ||||
-rwxr-xr-x | BUILD/compile-pentium64-gprof | 9 | ||||
-rw-r--r-- | mysql-test/r/parser_precedence.result | 356 | ||||
-rw-r--r-- | mysql-test/t/parser_precedence.test | 93 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 18 | ||||
-rw-r--r-- | sql/sql_lex.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.h | 1 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 217 |
13 files changed, 686 insertions, 95 deletions
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 6b3708f475f..dc439e68c45 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -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/mysql-test/r/parser_precedence.result b/mysql-test/r/parser_precedence.result new file mode 100644 index 00000000000..e2d35521ca9 --- /dev/null +++ b/mysql-test/r/parser_precedence.result @@ -0,0 +1,356 @@ +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; diff --git a/mysql-test/t/parser_precedence.test b/mysql-test/t/parser_precedence.test new file mode 100644 index 00000000000..a3a80776fb1 --- /dev/null +++ b/mysql-test/t/parser_precedence.test @@ -0,0 +1,93 @@ + +--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; + diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 47914c59b4c..6115ed33adc 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1425,6 +1425,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); @@ -1618,6 +1619,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: @@ -1639,6 +1649,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/sql_lex.cc b/sql/sql_lex.cc index 78b4f034f98..7fe2ed04d51 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(); @@ -1555,7 +1554,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 2e72a87c35d..f80ddfb8339 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_yacc.yy b/sql/sql_yacc.yy index 8f66e41b338..7b03f7d4eae 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -508,10 +508,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %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. @@ -1089,7 +1089,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 @@ -1102,6 +1103,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 @@ -1150,7 +1152,7 @@ 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 + variable variable_aux bool_factor bool_test bool_pri predicate bit_expr bit_term bit_factor value_expr term factor table_wild simple_expr udf_expr expr_or_default set_expr_or_default interval_expr @@ -1169,7 +1171,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> @@ -1243,7 +1245,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 @@ -6554,53 +6556,103 @@ optional_braces: ; /* all possible expressions */ -expr: - bool_term { Select->expr_list.push_front(new List<Item>); } - bool_or_expr +expr: + bool_factor + | 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 { - List<Item> *list= Select->expr_list.pop(); - if (list->elements) + /* XOR is a proprietary extension */ + $$ = new (YYTHD->mem_root) Item_cond_xor($1, $3); + } + | expr and expr %prec AND_SYM + { + /* 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: @@ -6766,7 +6818,8 @@ all_or_any: ; interval_expr: - INTERVAL_SYM expr { $$=$2; } + INTERVAL_SYM expr %prec INTERVAL_SYM + { $$=$2; } ; simple_expr: @@ -7200,7 +7253,7 @@ function_call_generic: $<udf>$= udf; #endif } - udf_expr_list ')' + opt_udf_expr_list ')' { THD *thd= YYTHD; Create_func *builder; @@ -7297,27 +7350,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 @@ -7515,13 +7564,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; } @@ -7529,13 +7582,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; } |