Merge weblab.(none):/home/marcsql/TREE/mysql-5.1-base
into weblab.(none):/home/marcsql/TREE/mysql-5.1-rt50-merge mysql-test/r/sp.result: Auto merged mysql-test/t/mysql.test: Auto merged mysql-test/t/query_cache.test: Auto merged mysql-test/t/sp.test: Auto merged sql/item_cmpfunc.h: Auto merged sql/rpl_utility.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_cache.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged
This commit is contained in:
commit
c458f7f6a3
@ -105,7 +105,7 @@ if [ "x$warning_mode" != "xpedantic" ]; then
|
|||||||
# Added unless --with-debug=full
|
# Added unless --with-debug=full
|
||||||
debug_extra_cflags="-O1 -Wuninitialized"
|
debug_extra_cflags="-O1 -Wuninitialized"
|
||||||
else
|
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"
|
c_warnings="$warnings"
|
||||||
cxx_warnings="$warnings -std=c++98"
|
cxx_warnings="$warnings -std=c++98"
|
||||||
# NOTE: warning mode should not influence optimize/debug mode.
|
# NOTE: warning mode should not influence optimize/debug mode.
|
||||||
@ -207,3 +207,28 @@ then
|
|||||||
echo "$CC" | grep "ccache" > /dev/null || CC="ccache $CC"
|
echo "$CC" | grep "ccache" > /dev/null || CC="ccache $CC"
|
||||||
echo "$CXX" | grep "ccache" > /dev/null || CXX="ccache $CXX"
|
echo "$CXX" | grep "ccache" > /dev/null || CXX="ccache $CXX"
|
||||||
fi
|
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"
|
||||||
|
|
||||||
|
17
BUILD/compile-amd64-gcov
Executable file
17
BUILD/compile-amd64-gcov
Executable file
@ -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"
|
9
BUILD/compile-amd64-gprof
Executable file
9
BUILD/compile-amd64-gprof
Executable file
@ -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"
|
@ -20,18 +20,11 @@ export CCACHE_GCOV_VERSION_ENABLED
|
|||||||
path=`dirname $0`
|
path=`dirname $0`
|
||||||
. "$path/SETUP.sh"
|
. "$path/SETUP.sh"
|
||||||
|
|
||||||
# GCC4 needs -fprofile-arcs -ftest-coverage on the linker command line (as well
|
export LDFLAGS="$gcov_link_flags"
|
||||||
# as on the compiler command line), and this requires setting LDFLAGS for BDB.
|
|
||||||
export LDFLAGS="-fprofile-arcs -ftest-coverage"
|
|
||||||
|
|
||||||
# The -fprofile-arcs and -ftest-coverage options cause GCC to instrument the
|
extra_flags="$pentium_cflags $debug_cflags $max_cflags $gcov_compile_flags"
|
||||||
# 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"
|
|
||||||
c_warnings="$c_warnings $debug_extra_warnings"
|
c_warnings="$c_warnings $debug_extra_warnings"
|
||||||
cxx_warnings="$cxx_warnings $debug_extra_warnings"
|
cxx_warnings="$cxx_warnings $debug_extra_warnings"
|
||||||
|
extra_configs="$pentium_configs $debug_configs $gcov_configs $max_configs"
|
||||||
|
|
||||||
. "$path/FINISH.sh"
|
. "$path/FINISH.sh"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
path=`dirname $0`
|
path=`dirname $0`
|
||||||
. "$path/SETUP.sh"
|
. "$path/SETUP.sh"
|
||||||
|
|
||||||
extra_flags="$pentium_cflags -O2 -pg -g"
|
extra_flags="$pentium_cflags $gprof_compile_flags"
|
||||||
extra_configs="$pentium_configs $debug_configs --disable-shared $static_link"
|
extra_configs="$pentium_configs $debug_configs $gprof_link_flags"
|
||||||
|
|
||||||
. "$path/FINISH.sh"
|
. "$path/FINISH.sh"
|
||||||
|
17
BUILD/compile-pentium64-gcov
Executable file
17
BUILD/compile-pentium64-gcov
Executable file
@ -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"
|
9
BUILD/compile-pentium64-gprof
Executable file
9
BUILD/compile-pentium64-gprof
Executable file
@ -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"
|
@ -1263,6 +1263,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
|
|||||||
char buff[80], *pos, *out;
|
char buff[80], *pos, *out;
|
||||||
COMMANDS *com;
|
COMMANDS *com;
|
||||||
bool need_space= 0;
|
bool need_space= 0;
|
||||||
|
bool ss_comment= 0;
|
||||||
DBUG_ENTER("add_line");
|
DBUG_ENTER("add_line");
|
||||||
|
|
||||||
if (!line[0] && buffer.is_empty())
|
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)))
|
if ((com=find_command(NullS,(char) inchar)))
|
||||||
{
|
{
|
||||||
const String tmp(line,(uint) (out-line), charset_info);
|
const String tmp(line,(uint) (out-line), charset_info);
|
||||||
buffer.append(tmp);
|
buffer.append(tmp);
|
||||||
if ((*com->func)(&buffer,pos-1) > 0)
|
if ((*com->func)(&buffer,pos-1) > 0)
|
||||||
DBUG_RETURN(1); // Quit
|
DBUG_RETURN(1); // Quit
|
||||||
if (com->takes_params)
|
if (com->takes_params)
|
||||||
{
|
{
|
||||||
for (pos++ ;
|
if (ss_comment)
|
||||||
*pos && (*pos != *delimiter ||
|
{
|
||||||
!is_prefix(pos + 1, delimiter + 1)) ; pos++)
|
/*
|
||||||
; // Remove parameters
|
If a client-side macro appears inside a server-side comment,
|
||||||
if (!*pos)
|
discard all characters in the comment after the macro (that is,
|
||||||
pos--;
|
until the end of the comment rather than the next delimiter)
|
||||||
else
|
*/
|
||||||
pos+= delimiter_length - 1; // Point at last delim char
|
for (pos++; *pos && (*pos != '*' || *(pos + 1) != '/'); pos++)
|
||||||
}
|
;
|
||||||
out=line;
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -1386,7 +1401,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
|
|||||||
out=line;
|
out=line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (*ml_comment && inchar == '*' && *(pos + 1) == '/')
|
else if (*ml_comment && !ss_comment && inchar == '*' && *(pos + 1) == '/')
|
||||||
{
|
{
|
||||||
pos++;
|
pos++;
|
||||||
*ml_comment= 0;
|
*ml_comment= 0;
|
||||||
@ -1394,6 +1409,11 @@ static bool add_line(String &buffer,char *line,char *in_string,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Add found char to buffer
|
{ // 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)
|
if (inchar == *in_string)
|
||||||
*in_string= 0;
|
*in_string= 0;
|
||||||
else if (!*ml_comment && !*in_string &&
|
else if (!*ml_comment && !*in_string &&
|
||||||
|
@ -562,12 +562,6 @@ int __void__;
|
|||||||
#define PURIFY_OR_LINT_INIT(var)
|
#define PURIFY_OR_LINT_INIT(var)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Define some useful general macros */
|
|
||||||
#if !defined(max)
|
|
||||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
|
||||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(HAVE_UINT)
|
#if !defined(HAVE_UINT)
|
||||||
#undef HAVE_UINT
|
#undef HAVE_UINT
|
||||||
#define HAVE_UINT
|
#define HAVE_UINT
|
||||||
@ -1508,4 +1502,10 @@ inline void operator delete[](void*, void*) { /* Do nothing */ }
|
|||||||
/* Length of decimal number represented by INT64. */
|
/* Length of decimal number represented by INT64. */
|
||||||
#define MY_INT64_NUM_DECIMAL_DIGITS 21
|
#define MY_INT64_NUM_DECIMAL_DIGITS 21
|
||||||
|
|
||||||
|
/* Define some useful general macros (should be done after all headers). */
|
||||||
|
#if !defined(max)
|
||||||
|
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* my_global_h */
|
#endif /* my_global_h */
|
||||||
|
@ -785,5 +785,28 @@ void mysql_query_cache_invalidate4(MYSQL_THD thd,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
/**
|
||||||
|
Provide a handler data getter to simplify coding
|
||||||
|
*/
|
||||||
|
inline
|
||||||
|
void *
|
||||||
|
thd_get_ha_data(const MYSQL_THD thd, const struct handlerton *hton)
|
||||||
|
{
|
||||||
|
return *thd_ha_data(thd, hton);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Provide a handler data setter to simplify coding
|
||||||
|
*/
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
thd_set_ha_data(const MYSQL_THD thd, const struct handlerton *hton,
|
||||||
|
const void *ha_data)
|
||||||
|
{
|
||||||
|
*thd_ha_data(thd, hton)= (void*) ha_data;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -144,4 +144,29 @@ disconnect con1;
|
|||||||
disconnect con2;
|
disconnect con2;
|
||||||
drop table t1, t2;
|
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.
|
||||||
|
@ -479,3 +479,22 @@ handler t1 open;
|
|||||||
--echo --> client 1
|
--echo --> client 1
|
||||||
connection default;
|
connection default;
|
||||||
drop table t1;
|
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;
|
||||||
|
@ -275,5 +275,223 @@ drop table t1;
|
|||||||
--echo ---- disconnect connection con1 ----
|
--echo ---- disconnect connection con1 ----
|
||||||
disconnect con1;
|
disconnect con1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #25843 Changing default database between PREPARE and EXECUTE of statement
|
||||||
|
# breaks binlog.
|
||||||
|
#
|
||||||
|
# There were actually two problems discovered by this bug:
|
||||||
|
#
|
||||||
|
# 1. Default (current) database is not fixed at the creation time.
|
||||||
|
# That leads to wrong output of DATABASE() function.
|
||||||
|
#
|
||||||
|
# 2. Database attributes (@@collation_database) are not fixed at the creation
|
||||||
|
# time. That leads to wrong resultset.
|
||||||
|
#
|
||||||
|
# Binlog breakage and Query Cache wrong output happened because of the first
|
||||||
|
# problem.
|
||||||
|
#
|
||||||
|
|
||||||
|
--echo ########################################################################
|
||||||
|
--echo #
|
||||||
|
--echo # BUG#25843: Changing default database between PREPARE and EXECUTE of
|
||||||
|
--echo # statement breaks binlog.
|
||||||
|
--echo #
|
||||||
|
--echo ########################################################################
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo #
|
||||||
|
--echo # Check that default database and its attributes are fixed at the
|
||||||
|
--echo # creation time.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
# Prepare data structures.
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--disable_warnings
|
||||||
|
DROP DATABASE IF EXISTS mysqltest1;
|
||||||
|
DROP DATABASE IF EXISTS mysqltest2;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
--echo
|
||||||
|
CREATE DATABASE mysqltest1 COLLATE utf8_unicode_ci;
|
||||||
|
CREATE DATABASE mysqltest2 COLLATE utf8_general_ci;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
CREATE TABLE mysqltest1.t1(msg VARCHAR(255));
|
||||||
|
CREATE TABLE mysqltest2.t1(msg VARCHAR(255));
|
||||||
|
|
||||||
|
# - Create a prepared statement with mysqltest1 as default database;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
use mysqltest1;
|
||||||
|
|
||||||
|
PREPARE stmt_a_1 FROM 'INSERT INTO t1 VALUES(DATABASE())';
|
||||||
|
PREPARE stmt_a_2 FROM 'INSERT INTO t1 VALUES(@@collation_database)';
|
||||||
|
|
||||||
|
# - Execute on mysqltest1.
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
EXECUTE stmt_a_1;
|
||||||
|
EXECUTE stmt_a_2;
|
||||||
|
|
||||||
|
# - Execute on mysqltest2.
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
use mysqltest2;
|
||||||
|
|
||||||
|
EXECUTE stmt_a_1;
|
||||||
|
EXECUTE stmt_a_2;
|
||||||
|
|
||||||
|
# - Check the results;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
SELECT * FROM mysqltest1.t1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
SELECT * FROM mysqltest2.t1;
|
||||||
|
|
||||||
|
# - Drop prepared statements.
|
||||||
|
|
||||||
|
--echo
|
||||||
|
DROP PREPARE stmt_a_1;
|
||||||
|
DROP PREPARE stmt_a_2;
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo #
|
||||||
|
--echo # The Query Cache test case.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
DELETE FROM mysqltest1.t1;
|
||||||
|
DELETE FROM mysqltest2.t1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
INSERT INTO mysqltest1.t1 VALUES('mysqltest1.t1');
|
||||||
|
INSERT INTO mysqltest2.t1 VALUES('mysqltest2.t1');
|
||||||
|
|
||||||
|
--echo
|
||||||
|
use mysqltest1;
|
||||||
|
PREPARE stmt_b_1 FROM 'SELECT * FROM t1';
|
||||||
|
|
||||||
|
--echo
|
||||||
|
use mysqltest2;
|
||||||
|
PREPARE stmt_b_2 FROM 'SELECT * FROM t1';
|
||||||
|
|
||||||
|
--echo
|
||||||
|
EXECUTE stmt_b_1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
EXECUTE stmt_b_2;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
use mysqltest1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
EXECUTE stmt_b_1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
EXECUTE stmt_b_2;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
DROP PREPARE stmt_b_1;
|
||||||
|
DROP PREPARE stmt_b_2;
|
||||||
|
|
||||||
|
# Cleanup.
|
||||||
|
|
||||||
|
--echo
|
||||||
|
use test;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
DROP DATABASE mysqltest1;
|
||||||
|
DROP DATABASE mysqltest2;
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo #
|
||||||
|
--echo # Check that prepared statements work properly when there is no current
|
||||||
|
--echo # database.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
CREATE DATABASE mysqltest1 COLLATE utf8_unicode_ci;
|
||||||
|
CREATE DATABASE mysqltest2 COLLATE utf8_general_ci;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
use mysqltest1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
PREPARE stmt_c_1 FROM 'SELECT DATABASE(), @@collation_database';
|
||||||
|
|
||||||
|
--echo
|
||||||
|
use mysqltest2;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
PREPARE stmt_c_2 FROM 'SELECT DATABASE(), @@collation_database';
|
||||||
|
|
||||||
|
--echo
|
||||||
|
DROP DATABASE mysqltest2;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
|
||||||
|
# -- Here we have: current db: NULL; stmt db: mysqltest1;
|
||||||
|
--echo
|
||||||
|
EXECUTE stmt_c_1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
|
||||||
|
# -- Here we have: current db: NULL; stmt db: mysqltest2 (non-existent);
|
||||||
|
--echo
|
||||||
|
EXECUTE stmt_c_2;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
|
||||||
|
# -- Create prepared statement, which has no current database.
|
||||||
|
|
||||||
|
--echo
|
||||||
|
PREPARE stmt_c_3 FROM 'SELECT DATABASE(), @@collation_database';
|
||||||
|
|
||||||
|
# -- Here we have: current db: NULL; stmt db: NULL;
|
||||||
|
--echo
|
||||||
|
EXECUTE stmt_c_3;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
use mysqltest1;
|
||||||
|
|
||||||
|
# -- Here we have: current db: mysqltest1; stmt db: mysqltest2 (non-existent);
|
||||||
|
--echo
|
||||||
|
EXECUTE stmt_c_2;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
|
||||||
|
# -- Here we have: current db: mysqltest1; stmt db: NULL;
|
||||||
|
--echo
|
||||||
|
EXECUTE stmt_c_3;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
DROP DATABASE mysqltest1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
use test;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo ########################################################################
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
set @@global.query_cache_size=@initial_query_cache_size;
|
set @@global.query_cache_size=@initial_query_cache_size;
|
||||||
flush status; # reset Qcache status variables for next tests
|
flush status; # reset Qcache status variables for next tests
|
||||||
|
@ -36,3 +36,18 @@ select 1/*!999992*/;
|
|||||||
select 1 + /*!00000 2 */ + 3 /*!99999 noise*/ + 4;
|
select 1 + /*!00000 2 */ + 3 /*!99999 noise*/ + 4;
|
||||||
1 + 2 + 3 + 4
|
1 + 2 + 3 + 4
|
||||||
10
|
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;
|
||||||
|
@ -112,3 +112,14 @@ id x
|
|||||||
commit;
|
commit;
|
||||||
# Switch to connection default + disconnect con1 and con2
|
# Switch to connection default + disconnect con1 and con2
|
||||||
drop table t1, t2;
|
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.
|
||||||
|
@ -454,8 +454,11 @@ create event закачка on schedule every 10 hour do select get_lock("test_l
|
|||||||
select definer, name, db from mysql.event;
|
select definer, name, db from mysql.event;
|
||||||
definer name db
|
definer name db
|
||||||
root@localhost закачка events_test
|
root@localhost закачка events_test
|
||||||
"Should be only 1 process"
|
"Should be only 0 process"
|
||||||
select /*1*/ 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 /*1*/ user, host, db, command, state, info
|
||||||
|
from information_schema.processlist
|
||||||
|
where (user='event_scheduler')
|
||||||
|
order by info;
|
||||||
user host db command state info
|
user host db command state info
|
||||||
select release_lock("test_lock1");
|
select release_lock("test_lock1");
|
||||||
release_lock("test_lock1")
|
release_lock("test_lock1")
|
||||||
@ -472,14 +475,15 @@ get_lock("test_lock2", 20)
|
|||||||
1
|
1
|
||||||
"Create an event which tries to acquire a mutex. The event locks on the mutex"
|
"Create an event which tries to acquire a mutex. The event locks on the mutex"
|
||||||
create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
|
create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
|
||||||
"Let some time pass to the event starts"
|
|
||||||
"Should have only 2 processes: the scheduler and the locked event"
|
"Should have only 2 processes: the scheduler and the locked event"
|
||||||
select /*2*/ 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 /*2*/ user, host, db, command, state, info
|
||||||
|
from information_schema.processlist
|
||||||
|
where (info like "select get_lock%" OR user='event_scheduler')
|
||||||
|
order by info;
|
||||||
user host db command state info
|
user host db command state info
|
||||||
event_scheduler localhost NULL Daemon Waiting for next activation NULL
|
event_scheduler localhost NULL Daemon Waiting for next activation NULL
|
||||||
root localhost events_test Connect User lock select get_lock("test_lock2", 20)
|
root localhost events_test Connect User lock select get_lock("test_lock2", 20)
|
||||||
"Release the mutex, the event worker should finish."
|
"Release the mutex, the event worker should finish."
|
||||||
"Release the mutex, the event worker should finish."
|
|
||||||
select release_lock("test_lock2");
|
select release_lock("test_lock2");
|
||||||
release_lock("test_lock2")
|
release_lock("test_lock2")
|
||||||
1
|
1
|
||||||
@ -489,16 +493,25 @@ select get_lock("test_lock2_1", 20);
|
|||||||
get_lock("test_lock2_1", 20)
|
get_lock("test_lock2_1", 20)
|
||||||
1
|
1
|
||||||
create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20);
|
create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20);
|
||||||
"Should have only 3 processes: the scheduler, our conn and the locked event"
|
"Should have only 2 processes: the scheduler 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;
|
select /*3*/ user, host, db, command, state, info
|
||||||
|
from information_schema.processlist
|
||||||
|
where (info like "select get_lock%" OR user='event_scheduler')
|
||||||
|
order by info;
|
||||||
user host db command state info
|
user host db command state info
|
||||||
event_scheduler localhost NULL Daemon Waiting for next activation NULL
|
event_scheduler localhost NULL Daemon Waiting for next activation NULL
|
||||||
root localhost events_test Connect User lock select get_lock("test_lock2_1", 20)
|
root localhost events_test Connect User lock select get_lock("test_lock2_1", 20)
|
||||||
set global event_scheduler=off;
|
set global event_scheduler=off;
|
||||||
"Should have only our process now:"
|
"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 /*4*/ user, host, db, command, state, info
|
||||||
|
from information_schema.processlist
|
||||||
|
where (info like "select get_lock%" OR user='event_scheduler')
|
||||||
|
order by info;
|
||||||
user host db command state info
|
user host db command state info
|
||||||
root localhost events_test Connect User lock select get_lock("test_lock2_1", 20)
|
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;
|
drop event закачка21;
|
||||||
create table t_16 (s1 int);
|
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;
|
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;
|
||||||
|
@ -522,3 +522,16 @@ handler t1 open;
|
|||||||
ERROR HY000: Table storage engine for 't1' doesn't have this option
|
ERROR HY000: Table storage engine for 't1' doesn't have this option
|
||||||
--> client 1
|
--> client 1
|
||||||
drop table t1;
|
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;
|
||||||
|
@ -522,3 +522,16 @@ handler t1 open;
|
|||||||
ERROR HY000: Table storage engine for 't1' doesn't have this option
|
ERROR HY000: Table storage engine for 't1' doesn't have this option
|
||||||
--> client 1
|
--> client 1
|
||||||
drop table t1;
|
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;
|
||||||
|
@ -407,3 +407,22 @@ select if( @stamp1 = @stamp2, "correct", "wrong");
|
|||||||
if( @stamp1 = @stamp2, "correct", "wrong")
|
if( @stamp1 = @stamp2, "correct", "wrong")
|
||||||
correct
|
correct
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
connection: default
|
||||||
|
set low_priority_updates=1;
|
||||||
|
drop table if exists t1;
|
||||||
|
create table t1 (a int, b int, unique key t1$a (a));
|
||||||
|
lock table t1 read;
|
||||||
|
connection: update
|
||||||
|
set low_priority_updates=1;
|
||||||
|
show variables like 'low_priority_updates';
|
||||||
|
Variable_name Value
|
||||||
|
low_priority_updates ON
|
||||||
|
insert into t1 values (1, 2) ON DUPLICATE KEY UPDATE b = 2;;
|
||||||
|
connection: select
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
connection: default
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
drop table t1;
|
||||||
|
set low_priority_updates=default;
|
||||||
|
@ -176,5 +176,7 @@ ERROR at line 1: DELIMITER cannot contain a backslash character
|
|||||||
ERROR at line 1: DELIMITER cannot contain a backslash character
|
ERROR at line 1: DELIMITER cannot contain a backslash character
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
End of 5.0 tests
|
End of 5.0 tests
|
||||||
WARNING: --server-arg option not supported in this configuration.
|
WARNING: --server-arg option not supported in this configuration.
|
||||||
|
747
mysql-test/r/parser_precedence.result
Normal file
747
mysql-test/r/parser_precedence.result
Normal file
@ -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
|
@ -371,5 +371,163 @@ Variable_name Value
|
|||||||
Qcache_hits 21
|
Qcache_hits 21
|
||||||
drop table t1;
|
drop table t1;
|
||||||
---- disconnect connection con1 ----
|
---- disconnect connection con1 ----
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# BUG#25843: Changing default database between PREPARE and EXECUTE of
|
||||||
|
# statement breaks binlog.
|
||||||
|
#
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check that default database and its attributes are fixed at the
|
||||||
|
# creation time.
|
||||||
|
#
|
||||||
|
|
||||||
|
DROP DATABASE IF EXISTS mysqltest1;
|
||||||
|
DROP DATABASE IF EXISTS mysqltest2;
|
||||||
|
|
||||||
|
CREATE DATABASE mysqltest1 COLLATE utf8_unicode_ci;
|
||||||
|
CREATE DATABASE mysqltest2 COLLATE utf8_general_ci;
|
||||||
|
|
||||||
|
CREATE TABLE mysqltest1.t1(msg VARCHAR(255));
|
||||||
|
CREATE TABLE mysqltest2.t1(msg VARCHAR(255));
|
||||||
|
|
||||||
|
use mysqltest1;
|
||||||
|
PREPARE stmt_a_1 FROM 'INSERT INTO t1 VALUES(DATABASE())';
|
||||||
|
PREPARE stmt_a_2 FROM 'INSERT INTO t1 VALUES(@@collation_database)';
|
||||||
|
|
||||||
|
EXECUTE stmt_a_1;
|
||||||
|
EXECUTE stmt_a_2;
|
||||||
|
|
||||||
|
use mysqltest2;
|
||||||
|
EXECUTE stmt_a_1;
|
||||||
|
EXECUTE stmt_a_2;
|
||||||
|
|
||||||
|
SELECT * FROM mysqltest1.t1;
|
||||||
|
msg
|
||||||
|
mysqltest1
|
||||||
|
utf8_unicode_ci
|
||||||
|
mysqltest1
|
||||||
|
utf8_unicode_ci
|
||||||
|
|
||||||
|
SELECT * FROM mysqltest2.t1;
|
||||||
|
msg
|
||||||
|
|
||||||
|
DROP PREPARE stmt_a_1;
|
||||||
|
DROP PREPARE stmt_a_2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# The Query Cache test case.
|
||||||
|
#
|
||||||
|
|
||||||
|
DELETE FROM mysqltest1.t1;
|
||||||
|
DELETE FROM mysqltest2.t1;
|
||||||
|
|
||||||
|
INSERT INTO mysqltest1.t1 VALUES('mysqltest1.t1');
|
||||||
|
INSERT INTO mysqltest2.t1 VALUES('mysqltest2.t1');
|
||||||
|
|
||||||
|
use mysqltest1;
|
||||||
|
PREPARE stmt_b_1 FROM 'SELECT * FROM t1';
|
||||||
|
|
||||||
|
use mysqltest2;
|
||||||
|
PREPARE stmt_b_2 FROM 'SELECT * FROM t1';
|
||||||
|
|
||||||
|
EXECUTE stmt_b_1;
|
||||||
|
msg
|
||||||
|
mysqltest1.t1
|
||||||
|
|
||||||
|
EXECUTE stmt_b_2;
|
||||||
|
msg
|
||||||
|
mysqltest2.t1
|
||||||
|
|
||||||
|
use mysqltest1;
|
||||||
|
|
||||||
|
EXECUTE stmt_b_1;
|
||||||
|
msg
|
||||||
|
mysqltest1.t1
|
||||||
|
|
||||||
|
EXECUTE stmt_b_2;
|
||||||
|
msg
|
||||||
|
mysqltest2.t1
|
||||||
|
|
||||||
|
DROP PREPARE stmt_b_1;
|
||||||
|
DROP PREPARE stmt_b_2;
|
||||||
|
|
||||||
|
use test;
|
||||||
|
|
||||||
|
DROP DATABASE mysqltest1;
|
||||||
|
DROP DATABASE mysqltest2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check that prepared statements work properly when there is no current
|
||||||
|
# database.
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE DATABASE mysqltest1 COLLATE utf8_unicode_ci;
|
||||||
|
CREATE DATABASE mysqltest2 COLLATE utf8_general_ci;
|
||||||
|
|
||||||
|
use mysqltest1;
|
||||||
|
|
||||||
|
PREPARE stmt_c_1 FROM 'SELECT DATABASE(), @@collation_database';
|
||||||
|
|
||||||
|
use mysqltest2;
|
||||||
|
|
||||||
|
PREPARE stmt_c_2 FROM 'SELECT DATABASE(), @@collation_database';
|
||||||
|
|
||||||
|
DROP DATABASE mysqltest2;
|
||||||
|
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
|
||||||
|
EXECUTE stmt_c_1;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
mysqltest1 utf8_unicode_ci
|
||||||
|
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
|
||||||
|
EXECUTE stmt_c_2;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
Warnings:
|
||||||
|
Note 1049 Unknown database 'mysqltest2'
|
||||||
|
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
|
||||||
|
PREPARE stmt_c_3 FROM 'SELECT DATABASE(), @@collation_database';
|
||||||
|
|
||||||
|
EXECUTE stmt_c_3;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
|
||||||
|
use mysqltest1;
|
||||||
|
|
||||||
|
EXECUTE stmt_c_2;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
Warnings:
|
||||||
|
Note 1049 Unknown database 'mysqltest2'
|
||||||
|
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
mysqltest1 utf8_unicode_ci
|
||||||
|
|
||||||
|
EXECUTE stmt_c_3;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
mysqltest1 utf8_unicode_ci
|
||||||
|
|
||||||
|
DROP DATABASE mysqltest1;
|
||||||
|
|
||||||
|
use test;
|
||||||
|
|
||||||
|
########################################################################
|
||||||
set @@global.query_cache_size=@initial_query_cache_size;
|
set @@global.query_cache_size=@initial_query_cache_size;
|
||||||
flush status;
|
flush status;
|
||||||
|
@ -371,5 +371,163 @@ Variable_name Value
|
|||||||
Qcache_hits 19
|
Qcache_hits 19
|
||||||
drop table t1;
|
drop table t1;
|
||||||
---- disconnect connection con1 ----
|
---- disconnect connection con1 ----
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# BUG#25843: Changing default database between PREPARE and EXECUTE of
|
||||||
|
# statement breaks binlog.
|
||||||
|
#
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check that default database and its attributes are fixed at the
|
||||||
|
# creation time.
|
||||||
|
#
|
||||||
|
|
||||||
|
DROP DATABASE IF EXISTS mysqltest1;
|
||||||
|
DROP DATABASE IF EXISTS mysqltest2;
|
||||||
|
|
||||||
|
CREATE DATABASE mysqltest1 COLLATE utf8_unicode_ci;
|
||||||
|
CREATE DATABASE mysqltest2 COLLATE utf8_general_ci;
|
||||||
|
|
||||||
|
CREATE TABLE mysqltest1.t1(msg VARCHAR(255));
|
||||||
|
CREATE TABLE mysqltest2.t1(msg VARCHAR(255));
|
||||||
|
|
||||||
|
use mysqltest1;
|
||||||
|
PREPARE stmt_a_1 FROM 'INSERT INTO t1 VALUES(DATABASE())';
|
||||||
|
PREPARE stmt_a_2 FROM 'INSERT INTO t1 VALUES(@@collation_database)';
|
||||||
|
|
||||||
|
EXECUTE stmt_a_1;
|
||||||
|
EXECUTE stmt_a_2;
|
||||||
|
|
||||||
|
use mysqltest2;
|
||||||
|
EXECUTE stmt_a_1;
|
||||||
|
EXECUTE stmt_a_2;
|
||||||
|
|
||||||
|
SELECT * FROM mysqltest1.t1;
|
||||||
|
msg
|
||||||
|
mysqltest1
|
||||||
|
utf8_unicode_ci
|
||||||
|
mysqltest1
|
||||||
|
utf8_unicode_ci
|
||||||
|
|
||||||
|
SELECT * FROM mysqltest2.t1;
|
||||||
|
msg
|
||||||
|
|
||||||
|
DROP PREPARE stmt_a_1;
|
||||||
|
DROP PREPARE stmt_a_2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# The Query Cache test case.
|
||||||
|
#
|
||||||
|
|
||||||
|
DELETE FROM mysqltest1.t1;
|
||||||
|
DELETE FROM mysqltest2.t1;
|
||||||
|
|
||||||
|
INSERT INTO mysqltest1.t1 VALUES('mysqltest1.t1');
|
||||||
|
INSERT INTO mysqltest2.t1 VALUES('mysqltest2.t1');
|
||||||
|
|
||||||
|
use mysqltest1;
|
||||||
|
PREPARE stmt_b_1 FROM 'SELECT * FROM t1';
|
||||||
|
|
||||||
|
use mysqltest2;
|
||||||
|
PREPARE stmt_b_2 FROM 'SELECT * FROM t1';
|
||||||
|
|
||||||
|
EXECUTE stmt_b_1;
|
||||||
|
msg
|
||||||
|
mysqltest1.t1
|
||||||
|
|
||||||
|
EXECUTE stmt_b_2;
|
||||||
|
msg
|
||||||
|
mysqltest2.t1
|
||||||
|
|
||||||
|
use mysqltest1;
|
||||||
|
|
||||||
|
EXECUTE stmt_b_1;
|
||||||
|
msg
|
||||||
|
mysqltest1.t1
|
||||||
|
|
||||||
|
EXECUTE stmt_b_2;
|
||||||
|
msg
|
||||||
|
mysqltest2.t1
|
||||||
|
|
||||||
|
DROP PREPARE stmt_b_1;
|
||||||
|
DROP PREPARE stmt_b_2;
|
||||||
|
|
||||||
|
use test;
|
||||||
|
|
||||||
|
DROP DATABASE mysqltest1;
|
||||||
|
DROP DATABASE mysqltest2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check that prepared statements work properly when there is no current
|
||||||
|
# database.
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE DATABASE mysqltest1 COLLATE utf8_unicode_ci;
|
||||||
|
CREATE DATABASE mysqltest2 COLLATE utf8_general_ci;
|
||||||
|
|
||||||
|
use mysqltest1;
|
||||||
|
|
||||||
|
PREPARE stmt_c_1 FROM 'SELECT DATABASE(), @@collation_database';
|
||||||
|
|
||||||
|
use mysqltest2;
|
||||||
|
|
||||||
|
PREPARE stmt_c_2 FROM 'SELECT DATABASE(), @@collation_database';
|
||||||
|
|
||||||
|
DROP DATABASE mysqltest2;
|
||||||
|
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
|
||||||
|
EXECUTE stmt_c_1;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
mysqltest1 utf8_unicode_ci
|
||||||
|
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
|
||||||
|
EXECUTE stmt_c_2;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
Warnings:
|
||||||
|
Note 1049 Unknown database 'mysqltest2'
|
||||||
|
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
|
||||||
|
PREPARE stmt_c_3 FROM 'SELECT DATABASE(), @@collation_database';
|
||||||
|
|
||||||
|
EXECUTE stmt_c_3;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
|
||||||
|
use mysqltest1;
|
||||||
|
|
||||||
|
EXECUTE stmt_c_2;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
Warnings:
|
||||||
|
Note 1049 Unknown database 'mysqltest2'
|
||||||
|
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
mysqltest1 utf8_unicode_ci
|
||||||
|
|
||||||
|
EXECUTE stmt_c_3;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
NULL latin1_swedish_ci
|
||||||
|
|
||||||
|
SELECT DATABASE(), @@collation_database;
|
||||||
|
DATABASE() @@collation_database
|
||||||
|
mysqltest1 utf8_unicode_ci
|
||||||
|
|
||||||
|
DROP DATABASE mysqltest1;
|
||||||
|
|
||||||
|
use test;
|
||||||
|
|
||||||
|
########################################################################
|
||||||
set @@global.query_cache_size=@initial_query_cache_size;
|
set @@global.query_cache_size=@initial_query_cache_size;
|
||||||
flush status;
|
flush status;
|
||||||
|
@ -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.
|
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 |
|
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.
|
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 |
|
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.
|
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 |
|
CREATE FUNCTION bug_13627_f() returns int BEGIN drop user 'mysqltest_1'; return 1; END |
|
||||||
|
@ -6546,4 +6546,79 @@ DROP VIEW v1;
|
|||||||
DROP FUNCTION f1;
|
DROP FUNCTION f1;
|
||||||
DROP FUNCTION f2;
|
DROP FUNCTION f2;
|
||||||
DROP TABLE t1;
|
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
|
End of 5.0 tests
|
||||||
|
50
mysql-test/suite/rpl/r/rpl_binlog_grant.result
Normal file
50
mysql-test/suite/rpl/r/rpl_binlog_grant.result
Normal file
@ -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;
|
@ -26,5 +26,55 @@ from-master-2-'',
|
|||||||
from-var-from-master-3
|
from-var-from-master-3
|
||||||
drop table t1;
|
drop table t1;
|
||||||
stop slave;
|
stop slave;
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# BUG#25843: Changing default database between PREPARE and EXECUTE of
|
||||||
|
# statement breaks binlog.
|
||||||
|
#
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
# Connection: slave
|
||||||
|
|
||||||
|
|
||||||
|
START SLAVE;
|
||||||
|
|
||||||
|
# Connection: master
|
||||||
|
|
||||||
|
|
||||||
|
CREATE DATABASE mysqltest1;
|
||||||
|
CREATE TABLE t1(db_name CHAR(32), db_col_name CHAR(32));
|
||||||
|
|
||||||
|
PREPARE stmt_d_1 FROM 'INSERT INTO t1 VALUES(DATABASE(), @@collation_database)';
|
||||||
|
|
||||||
|
EXECUTE stmt_d_1;
|
||||||
|
|
||||||
|
use mysqltest1;
|
||||||
|
|
||||||
|
EXECUTE stmt_d_1;
|
||||||
|
|
||||||
|
|
||||||
|
# Connection: slave
|
||||||
|
|
||||||
|
|
||||||
|
SELECT * FROM t1;
|
||||||
|
db_name db_col_name
|
||||||
|
test latin1_swedish_ci
|
||||||
|
test latin1_swedish_ci
|
||||||
|
|
||||||
|
# Connection: master
|
||||||
|
|
||||||
|
|
||||||
|
DROP DATABASE mysqltest1;
|
||||||
|
|
||||||
|
use test;
|
||||||
|
|
||||||
|
|
||||||
|
# Connection: slave
|
||||||
|
|
||||||
|
|
||||||
|
STOP SLAVE;
|
||||||
|
|
||||||
|
########################################################################
|
||||||
reset master;
|
reset master;
|
||||||
reset slave;
|
reset slave;
|
||||||
|
41
mysql-test/suite/rpl/t/rpl_binlog_grant.test
Normal file
41
mysql-test/suite/rpl/t/rpl_binlog_grant.test
Normal file
@ -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;
|
@ -46,6 +46,101 @@ stop slave;
|
|||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #25843 Changing default database between PREPARE and EXECUTE of statement
|
||||||
|
# breaks binlog.
|
||||||
|
#
|
||||||
|
# There were actually two problems discovered by this bug:
|
||||||
|
#
|
||||||
|
# 1. Default (current) database is not fixed at the creation time.
|
||||||
|
# That leads to wrong output of DATABASE() function.
|
||||||
|
#
|
||||||
|
# 2. Database attributes (@@collation_database) are not fixed at the creation
|
||||||
|
# time. That leads to wrong resultset.
|
||||||
|
#
|
||||||
|
# Binlog breakage and Query Cache wrong output happened because of the first
|
||||||
|
# problem.
|
||||||
|
#
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo ########################################################################
|
||||||
|
--echo #
|
||||||
|
--echo # BUG#25843: Changing default database between PREPARE and EXECUTE of
|
||||||
|
--echo # statement breaks binlog.
|
||||||
|
--echo #
|
||||||
|
--echo ########################################################################
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo # Connection: slave
|
||||||
|
--echo
|
||||||
|
--connection slave
|
||||||
|
|
||||||
|
--echo
|
||||||
|
START SLAVE;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo # Connection: master
|
||||||
|
--echo
|
||||||
|
--connection master
|
||||||
|
|
||||||
|
--echo
|
||||||
|
CREATE DATABASE mysqltest1;
|
||||||
|
CREATE TABLE t1(db_name CHAR(32), db_col_name CHAR(32));
|
||||||
|
|
||||||
|
--echo
|
||||||
|
PREPARE stmt_d_1 FROM 'INSERT INTO t1 VALUES(DATABASE(), @@collation_database)';
|
||||||
|
|
||||||
|
--echo
|
||||||
|
EXECUTE stmt_d_1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
use mysqltest1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
EXECUTE stmt_d_1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--save_master_pos
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo # Connection: slave
|
||||||
|
--echo
|
||||||
|
--connection slave
|
||||||
|
--sync_with_master
|
||||||
|
|
||||||
|
--echo
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo # Connection: master
|
||||||
|
--echo
|
||||||
|
--connection master
|
||||||
|
|
||||||
|
--echo
|
||||||
|
DROP DATABASE mysqltest1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
use test;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--save_master_pos
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo # Connection: slave
|
||||||
|
--echo
|
||||||
|
--connection slave
|
||||||
|
--sync_with_master
|
||||||
|
|
||||||
|
--echo
|
||||||
|
STOP SLAVE;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo ########################################################################
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
reset master;
|
reset master;
|
||||||
reset slave;
|
reset slave;
|
||||||
disconnect master;
|
disconnect master;
|
||||||
|
@ -34,3 +34,34 @@ select 1/*!999992*/;
|
|||||||
|
|
||||||
select 1 + /*!00000 2 */ + 3 /*!99999 noise*/ + 4;
|
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;
|
||||||
|
|
||||||
|
@ -432,8 +432,11 @@ create event закачка on schedule every 10 hour do select get_lock("test_l
|
|||||||
--echo "Should return 1 row"
|
--echo "Should return 1 row"
|
||||||
select definer, name, db from mysql.event;
|
select definer, name, db from mysql.event;
|
||||||
|
|
||||||
--echo "Should be only 1 process"
|
--echo "Should be only 0 process"
|
||||||
select /*1*/ 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 /*1*/ user, host, db, command, state, info
|
||||||
|
from information_schema.processlist
|
||||||
|
where (user='event_scheduler')
|
||||||
|
order by info;
|
||||||
select release_lock("test_lock1");
|
select release_lock("test_lock1");
|
||||||
drop event закачка;
|
drop event закачка;
|
||||||
--echo "Should have 0 events"
|
--echo "Should have 0 events"
|
||||||
@ -447,14 +450,28 @@ set global event_scheduler=on;
|
|||||||
select get_lock("test_lock2", 20);
|
select get_lock("test_lock2", 20);
|
||||||
--echo "Create an event which tries to acquire a mutex. The event locks on the mutex"
|
--echo "Create an event which tries to acquire a mutex. The event locks on the mutex"
|
||||||
create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
|
create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
|
||||||
--echo "Let some time pass to the event starts"
|
|
||||||
--sleep 1
|
|
||||||
--echo "Should have only 2 processes: the scheduler and the locked event"
|
--echo "Should have only 2 processes: the scheduler and the locked event"
|
||||||
select /*2*/ 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;--echo "Release the mutex, the event worker should finish."
|
let $wait_condition= select count(*) = 2 from information_schema.processlist
|
||||||
|
where ( (state like 'User lock%' AND info like 'select get_lock%')
|
||||||
|
OR (command='Daemon' AND user='event_scheduler'));
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
select /*2*/ user, host, db, command, state, info
|
||||||
|
from information_schema.processlist
|
||||||
|
where (info like "select get_lock%" OR user='event_scheduler')
|
||||||
|
order by info;
|
||||||
--echo "Release the mutex, the event worker should finish."
|
--echo "Release the mutex, the event worker should finish."
|
||||||
select release_lock("test_lock2");
|
select release_lock("test_lock2");
|
||||||
drop event закачка;
|
drop event закачка;
|
||||||
|
|
||||||
|
# Wait for release_lock("test_lock2") to complete,
|
||||||
|
# to avoid polluting the next test information_schema.processlist
|
||||||
|
let $wait_condition= select count(*) = 0 from information_schema.processlist
|
||||||
|
where (state like 'User lock%' AND info like 'select get_lock%');
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
## 1. get a lock
|
## 1. get a lock
|
||||||
## 2. create an event
|
## 2. create an event
|
||||||
@ -466,13 +483,30 @@ drop event закачка;
|
|||||||
set global event_scheduler=1;
|
set global event_scheduler=1;
|
||||||
select get_lock("test_lock2_1", 20);
|
select get_lock("test_lock2_1", 20);
|
||||||
create event закачка21 on schedule every 10 hour do 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
|
|
||||||
--echo "Should have only 3 processes: the scheduler, our conn and the locked event"
|
--echo "Should have only 2 processes: the scheduler 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;
|
let $wait_condition= select count(*) = 2 from information_schema.processlist
|
||||||
|
where ( (state like 'User lock%' AND info like 'select get_lock%')
|
||||||
|
OR (command='Daemon' AND user='event_scheduler'));
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
select /*3*/ user, host, db, command, state, info
|
||||||
|
from information_schema.processlist
|
||||||
|
where (info like "select get_lock%" OR user='event_scheduler')
|
||||||
|
order by info;
|
||||||
|
|
||||||
set global event_scheduler=off;
|
set global event_scheduler=off;
|
||||||
--sleep 0.8
|
|
||||||
|
let $wait_condition= select count(*) =1 from information_schema.processlist
|
||||||
|
where (info like "select get_lock%" OR user='event_scheduler');
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
--echo "Should have only our process now:"
|
--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 /*4*/ user, host, db, command, state, info
|
||||||
|
from information_schema.processlist
|
||||||
|
where (info like "select get_lock%" OR user='event_scheduler')
|
||||||
|
order by info;
|
||||||
|
select release_lock("test_lock2_1");
|
||||||
drop event закачка21;
|
drop event закачка21;
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 0 from information_schema.processlist
|
select count(*) = 0 from information_schema.processlist
|
||||||
|
@ -306,3 +306,38 @@ insert into t1(f1) values(1) on duplicate key update f1=1;
|
|||||||
select @stamp2:=f2 from t1;
|
select @stamp2:=f2 from t1;
|
||||||
select if( @stamp1 = @stamp2, "correct", "wrong");
|
select if( @stamp1 = @stamp2, "correct", "wrong");
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#28587 SELECT is blocked by INSERT waiting on read lock, even with low_priority_updates
|
||||||
|
#
|
||||||
|
--echo connection: default
|
||||||
|
set low_priority_updates=1;
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t1;
|
||||||
|
--enable_warnings
|
||||||
|
create table t1 (a int, b int, unique key t1$a (a));
|
||||||
|
lock table t1 read;
|
||||||
|
connect (update,localhost,root,,);
|
||||||
|
connection update;
|
||||||
|
--echo connection: update
|
||||||
|
set low_priority_updates=1;
|
||||||
|
show variables like 'low_priority_updates';
|
||||||
|
let $ID= `select connection_id()`;
|
||||||
|
--send insert into t1 values (1, 2) ON DUPLICATE KEY UPDATE b = 2;
|
||||||
|
connection default;
|
||||||
|
# we must wait till the insert opens and locks the table
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = "Locked" and id = $ID;
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
connect (select,localhost,root,,);
|
||||||
|
--echo connection: select
|
||||||
|
select * from t1;
|
||||||
|
connection default;
|
||||||
|
--echo connection: default
|
||||||
|
select * from t1;
|
||||||
|
connection default;
|
||||||
|
disconnect update;
|
||||||
|
disconnect select;
|
||||||
|
drop table t1;
|
||||||
|
set low_priority_updates=default;
|
||||||
|
@ -277,6 +277,11 @@ remove_file $MYSQLTEST_VARDIR/tmp/bug21412.sql;
|
|||||||
--exec $MYSQL --pager="540bytelengthstringxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -e "select 1" > /dev/null 2>&1
|
--exec $MYSQL --pager="540bytelengthstringxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -e "select 1" > /dev/null 2>&1
|
||||||
--exec $MYSQL --character-sets-dir="540bytelengthstringxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -e "select 1" 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
|
--echo End of 5.0 tests
|
||||||
|
|
||||||
#
|
#
|
||||||
|
333
mysql-test/t/parser_precedence.test
Normal file
333
mysql-test/t/parser_precedence.test
Normal file
@ -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);
|
||||||
|
|
@ -1386,6 +1386,21 @@ CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create user 'mysqltest
|
|||||||
-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
|
-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
|
||||||
CREATE FUNCTION bug_13627_f() returns int BEGIN create user 'mysqltest_1'; return 1; END |
|
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
|
-- 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 |
|
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
|
-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
|
||||||
|
@ -7494,4 +7494,123 @@ DROP FUNCTION f1;
|
|||||||
DROP FUNCTION f2;
|
DROP FUNCTION f2;
|
||||||
DROP TABLE t1;
|
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
|
--echo End of 5.0 tests
|
||||||
|
@ -216,10 +216,12 @@ inline void free_share(NDB_SHARE **share, bool have_lock= FALSE)
|
|||||||
|
|
||||||
inline
|
inline
|
||||||
Thd_ndb *
|
Thd_ndb *
|
||||||
get_thd_ndb(THD *thd) { return (Thd_ndb *) thd->ha_data[ndbcluster_hton->slot]; }
|
get_thd_ndb(THD *thd)
|
||||||
|
{ return (Thd_ndb *) thd_get_ha_data(thd, ndbcluster_hton); }
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
set_thd_ndb(THD *thd, Thd_ndb *thd_ndb) { thd->ha_data[ndbcluster_hton->slot]= thd_ndb; }
|
set_thd_ndb(THD *thd, Thd_ndb *thd_ndb)
|
||||||
|
{ thd_set_ha_data(thd, ndbcluster_hton, thd_ndb); }
|
||||||
|
|
||||||
Ndb* check_ndb_in_thd(THD* thd);
|
Ndb* check_ndb_in_thd(THD* thd);
|
||||||
|
@ -561,7 +561,7 @@ static my_bool closecon_handlerton(THD *thd, plugin_ref plugin,
|
|||||||
be rolled back already
|
be rolled back already
|
||||||
*/
|
*/
|
||||||
if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
|
if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
|
||||||
thd->ha_data[hton->slot])
|
thd_get_ha_data(thd, hton))
|
||||||
hton->close_connection(hton, thd);
|
hton->close_connection(hton, thd);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -1509,7 +1509,7 @@ void handler::ha_statistic_increment(ulong SSV::*offset) const
|
|||||||
|
|
||||||
void **handler::ha_data(THD *thd) const
|
void **handler::ha_data(THD *thd) const
|
||||||
{
|
{
|
||||||
return (void **) thd->ha_data + ht->slot;
|
return thd_ha_data(thd, ht);
|
||||||
}
|
}
|
||||||
|
|
||||||
THD *handler::ha_thd(void) const
|
THD *handler::ha_thd(void) const
|
||||||
|
@ -1424,6 +1424,7 @@ public:
|
|||||||
Item_cond(List<Item> &nlist)
|
Item_cond(List<Item> &nlist)
|
||||||
:Item_bool_func(), list(nlist), abort_on_null(0) {}
|
:Item_bool_func(), list(nlist), abort_on_null(0) {}
|
||||||
bool add(Item *item) { return list.push_back(item); }
|
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); }
|
void add_at_head(List<Item> *nlist) { list.prepand(nlist); }
|
||||||
bool fix_fields(THD *, Item **ref);
|
bool fix_fields(THD *, Item **ref);
|
||||||
|
|
||||||
@ -1616,6 +1617,15 @@ public:
|
|||||||
Item *neg_transformer(THD *thd);
|
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
|
class Item_cond_or :public Item_cond
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -1637,6 +1647,14 @@ public:
|
|||||||
Item *neg_transformer(THD *thd);
|
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
|
XOR is Item_cond, not an Item_int_func because we could like to
|
||||||
|
@ -276,6 +276,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
|
|||||||
thd->lock_id)];
|
thd->lock_id)];
|
||||||
if (rc > 1) /* a timeout or a deadlock */
|
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_error(rc, MYF(0));
|
||||||
my_free((uchar*) sql_lock,MYF(0));
|
my_free((uchar*) sql_lock,MYF(0));
|
||||||
sql_lock= 0;
|
sql_lock= 0;
|
||||||
|
56
sql/log.cc
56
sql/log.cc
@ -656,8 +656,14 @@ int Log_to_csv_event_handler::
|
|||||||
|
|
||||||
table= open_performance_schema_table(thd, & table_list,
|
table= open_performance_schema_table(thd, & table_list,
|
||||||
& open_tables_backup);
|
& open_tables_backup);
|
||||||
result= (table ? 0 : 1);
|
if (table)
|
||||||
close_performance_schema_table(thd, & open_tables_backup);
|
{
|
||||||
|
result= 0;
|
||||||
|
close_performance_schema_table(thd, & open_tables_backup);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result= 1;
|
||||||
|
|
||||||
DBUG_RETURN(result);
|
DBUG_RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1215,10 +1221,10 @@ binlog_trans_log_savepos(THD *thd, my_off_t *pos)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("binlog_trans_log_savepos");
|
DBUG_ENTER("binlog_trans_log_savepos");
|
||||||
DBUG_ASSERT(pos != NULL);
|
DBUG_ASSERT(pos != NULL);
|
||||||
if (thd->ha_data[binlog_hton->slot] == NULL)
|
if (thd_get_ha_data(thd, binlog_hton) == NULL)
|
||||||
thd->binlog_setup_trx_data();
|
thd->binlog_setup_trx_data();
|
||||||
binlog_trx_data *const trx_data=
|
binlog_trx_data *const trx_data=
|
||||||
(binlog_trx_data*) thd->ha_data[binlog_hton->slot];
|
(binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
|
||||||
DBUG_ASSERT(mysql_bin_log.is_open());
|
DBUG_ASSERT(mysql_bin_log.is_open());
|
||||||
*pos= trx_data->position();
|
*pos= trx_data->position();
|
||||||
DBUG_PRINT("return", ("*pos: %lu", (ulong) *pos));
|
DBUG_PRINT("return", ("*pos: %lu", (ulong) *pos));
|
||||||
@ -1247,12 +1253,12 @@ binlog_trans_log_truncate(THD *thd, my_off_t pos)
|
|||||||
DBUG_ENTER("binlog_trans_log_truncate");
|
DBUG_ENTER("binlog_trans_log_truncate");
|
||||||
DBUG_PRINT("enter", ("pos: %lu", (ulong) pos));
|
DBUG_PRINT("enter", ("pos: %lu", (ulong) pos));
|
||||||
|
|
||||||
DBUG_ASSERT(thd->ha_data[binlog_hton->slot] != NULL);
|
DBUG_ASSERT(thd_get_ha_data(thd, binlog_hton) != NULL);
|
||||||
/* Only true if binlog_trans_log_savepos() wasn't called before */
|
/* Only true if binlog_trans_log_savepos() wasn't called before */
|
||||||
DBUG_ASSERT(pos != ~(my_off_t) 0);
|
DBUG_ASSERT(pos != ~(my_off_t) 0);
|
||||||
|
|
||||||
binlog_trx_data *const trx_data=
|
binlog_trx_data *const trx_data=
|
||||||
(binlog_trx_data*) thd->ha_data[binlog_hton->slot];
|
(binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
|
||||||
trx_data->truncate(pos);
|
trx_data->truncate(pos);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -1283,9 +1289,9 @@ int binlog_init(void *p)
|
|||||||
static int binlog_close_connection(handlerton *hton, THD *thd)
|
static int binlog_close_connection(handlerton *hton, THD *thd)
|
||||||
{
|
{
|
||||||
binlog_trx_data *const trx_data=
|
binlog_trx_data *const trx_data=
|
||||||
(binlog_trx_data*) thd->ha_data[binlog_hton->slot];
|
(binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
|
||||||
DBUG_ASSERT(trx_data->empty());
|
DBUG_ASSERT(trx_data->empty());
|
||||||
thd->ha_data[binlog_hton->slot]= 0;
|
thd_set_ha_data(thd, binlog_hton, NULL);
|
||||||
trx_data->~binlog_trx_data();
|
trx_data->~binlog_trx_data();
|
||||||
my_free((uchar*)trx_data, MYF(0));
|
my_free((uchar*)trx_data, MYF(0));
|
||||||
return 0;
|
return 0;
|
||||||
@ -1408,7 +1414,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("binlog_commit");
|
DBUG_ENTER("binlog_commit");
|
||||||
binlog_trx_data *const trx_data=
|
binlog_trx_data *const trx_data=
|
||||||
(binlog_trx_data*) thd->ha_data[binlog_hton->slot];
|
(binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
|
||||||
|
|
||||||
if (trx_data->empty())
|
if (trx_data->empty())
|
||||||
{
|
{
|
||||||
@ -1435,7 +1441,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
|
|||||||
DBUG_ENTER("binlog_rollback");
|
DBUG_ENTER("binlog_rollback");
|
||||||
int error=0;
|
int error=0;
|
||||||
binlog_trx_data *const trx_data=
|
binlog_trx_data *const trx_data=
|
||||||
(binlog_trx_data*) thd->ha_data[binlog_hton->slot];
|
(binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
|
||||||
|
|
||||||
if (trx_data->empty()) {
|
if (trx_data->empty()) {
|
||||||
trx_data->reset();
|
trx_data->reset();
|
||||||
@ -3251,23 +3257,22 @@ int THD::binlog_setup_trx_data()
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("THD::binlog_setup_trx_data");
|
DBUG_ENTER("THD::binlog_setup_trx_data");
|
||||||
binlog_trx_data *trx_data=
|
binlog_trx_data *trx_data=
|
||||||
(binlog_trx_data*) ha_data[binlog_hton->slot];
|
(binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
|
||||||
|
|
||||||
if (trx_data)
|
if (trx_data)
|
||||||
DBUG_RETURN(0); // Already set up
|
DBUG_RETURN(0); // Already set up
|
||||||
|
|
||||||
ha_data[binlog_hton->slot]= trx_data=
|
trx_data= (binlog_trx_data*) my_malloc(sizeof(binlog_trx_data), MYF(MY_ZEROFILL));
|
||||||
(binlog_trx_data*) my_malloc(sizeof(binlog_trx_data), MYF(MY_ZEROFILL));
|
|
||||||
if (!trx_data ||
|
if (!trx_data ||
|
||||||
open_cached_file(&trx_data->trans_log, mysql_tmpdir,
|
open_cached_file(&trx_data->trans_log, mysql_tmpdir,
|
||||||
LOG_PREFIX, binlog_cache_size, MYF(MY_WME)))
|
LOG_PREFIX, binlog_cache_size, MYF(MY_WME)))
|
||||||
{
|
{
|
||||||
my_free((uchar*)trx_data, MYF(MY_ALLOW_ZERO_PTR));
|
my_free((uchar*)trx_data, MYF(MY_ALLOW_ZERO_PTR));
|
||||||
ha_data[binlog_hton->slot]= 0;
|
|
||||||
DBUG_RETURN(1); // Didn't manage to set it up
|
DBUG_RETURN(1); // Didn't manage to set it up
|
||||||
}
|
}
|
||||||
|
thd_set_ha_data(this, binlog_hton, trx_data);
|
||||||
|
|
||||||
trx_data= new (ha_data[binlog_hton->slot]) binlog_trx_data;
|
trx_data= new (thd_get_ha_data(this, binlog_hton)) binlog_trx_data;
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@ -3303,7 +3308,7 @@ int THD::binlog_setup_trx_data()
|
|||||||
void
|
void
|
||||||
THD::binlog_start_trans_and_stmt()
|
THD::binlog_start_trans_and_stmt()
|
||||||
{
|
{
|
||||||
binlog_trx_data *trx_data= (binlog_trx_data*) ha_data[binlog_hton->slot];
|
binlog_trx_data *trx_data= (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
|
||||||
DBUG_ENTER("binlog_start_trans_and_stmt");
|
DBUG_ENTER("binlog_start_trans_and_stmt");
|
||||||
DBUG_PRINT("enter", ("trx_data: 0x%lx trx_data->before_stmt_pos: %lu",
|
DBUG_PRINT("enter", ("trx_data: 0x%lx trx_data->before_stmt_pos: %lu",
|
||||||
(long) trx_data,
|
(long) trx_data,
|
||||||
@ -3323,7 +3328,7 @@ THD::binlog_start_trans_and_stmt()
|
|||||||
|
|
||||||
void THD::binlog_set_stmt_begin() {
|
void THD::binlog_set_stmt_begin() {
|
||||||
binlog_trx_data *trx_data=
|
binlog_trx_data *trx_data=
|
||||||
(binlog_trx_data*) ha_data[binlog_hton->slot];
|
(binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The call to binlog_trans_log_savepos() might create the trx_data
|
The call to binlog_trans_log_savepos() might create the trx_data
|
||||||
@ -3333,14 +3338,15 @@ void THD::binlog_set_stmt_begin() {
|
|||||||
*/
|
*/
|
||||||
my_off_t pos= 0;
|
my_off_t pos= 0;
|
||||||
binlog_trans_log_savepos(this, &pos);
|
binlog_trans_log_savepos(this, &pos);
|
||||||
trx_data= (binlog_trx_data*) ha_data[binlog_hton->slot];
|
trx_data= (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
|
||||||
trx_data->before_stmt_pos= pos;
|
trx_data->before_stmt_pos= pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
int THD::binlog_flush_transaction_cache()
|
int THD::binlog_flush_transaction_cache()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("binlog_flush_transaction_cache");
|
DBUG_ENTER("binlog_flush_transaction_cache");
|
||||||
binlog_trx_data *trx_data= (binlog_trx_data*) ha_data[binlog_hton->slot];
|
binlog_trx_data *trx_data= (binlog_trx_data*)
|
||||||
|
thd_get_ha_data(this, binlog_hton);
|
||||||
DBUG_PRINT("enter", ("trx_data=0x%lu", (ulong) trx_data));
|
DBUG_PRINT("enter", ("trx_data=0x%lu", (ulong) trx_data));
|
||||||
if (trx_data)
|
if (trx_data)
|
||||||
DBUG_PRINT("enter", ("trx_data->before_stmt_pos=%lu",
|
DBUG_PRINT("enter", ("trx_data->before_stmt_pos=%lu",
|
||||||
@ -3403,7 +3409,7 @@ Rows_log_event*
|
|||||||
THD::binlog_get_pending_rows_event() const
|
THD::binlog_get_pending_rows_event() const
|
||||||
{
|
{
|
||||||
binlog_trx_data *const trx_data=
|
binlog_trx_data *const trx_data=
|
||||||
(binlog_trx_data*) ha_data[binlog_hton->slot];
|
(binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
|
||||||
/*
|
/*
|
||||||
This is less than ideal, but here's the story: If there is no
|
This is less than ideal, but here's the story: If there is no
|
||||||
trx_data, prepare_pending_rows_event() has never been called
|
trx_data, prepare_pending_rows_event() has never been called
|
||||||
@ -3416,11 +3422,11 @@ THD::binlog_get_pending_rows_event() const
|
|||||||
void
|
void
|
||||||
THD::binlog_set_pending_rows_event(Rows_log_event* ev)
|
THD::binlog_set_pending_rows_event(Rows_log_event* ev)
|
||||||
{
|
{
|
||||||
if (ha_data[binlog_hton->slot] == NULL)
|
if (thd_get_ha_data(this, binlog_hton) == NULL)
|
||||||
binlog_setup_trx_data();
|
binlog_setup_trx_data();
|
||||||
|
|
||||||
binlog_trx_data *const trx_data=
|
binlog_trx_data *const trx_data=
|
||||||
(binlog_trx_data*) ha_data[binlog_hton->slot];
|
(binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
|
||||||
|
|
||||||
DBUG_ASSERT(trx_data);
|
DBUG_ASSERT(trx_data);
|
||||||
trx_data->set_pending(ev);
|
trx_data->set_pending(ev);
|
||||||
@ -3443,7 +3449,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
|
|||||||
int error= 0;
|
int error= 0;
|
||||||
|
|
||||||
binlog_trx_data *const trx_data=
|
binlog_trx_data *const trx_data=
|
||||||
(binlog_trx_data*) thd->ha_data[binlog_hton->slot];
|
(binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
|
||||||
|
|
||||||
DBUG_ASSERT(trx_data);
|
DBUG_ASSERT(trx_data);
|
||||||
|
|
||||||
@ -3594,7 +3600,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
binlog_trx_data *const trx_data=
|
binlog_trx_data *const trx_data=
|
||||||
(binlog_trx_data*) thd->ha_data[binlog_hton->slot];
|
(binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
|
||||||
IO_CACHE *trans_log= &trx_data->trans_log;
|
IO_CACHE *trans_log= &trx_data->trans_log;
|
||||||
my_off_t trans_log_pos= my_b_tell(trans_log);
|
my_off_t trans_log_pos= my_b_tell(trans_log);
|
||||||
if (event_info->get_cache_stmt() || trans_log_pos != 0)
|
if (event_info->get_cache_stmt() || trans_log_pos != 0)
|
||||||
@ -5031,7 +5037,7 @@ int TC_LOG_BINLOG::log_xid(THD *thd, my_xid xid)
|
|||||||
DBUG_ENTER("TC_LOG_BINLOG::log");
|
DBUG_ENTER("TC_LOG_BINLOG::log");
|
||||||
Xid_log_event xle(thd, xid);
|
Xid_log_event xle(thd, xid);
|
||||||
binlog_trx_data *trx_data=
|
binlog_trx_data *trx_data=
|
||||||
(binlog_trx_data*) thd->ha_data[binlog_hton->slot];
|
(binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
|
||||||
/*
|
/*
|
||||||
We always commit the entire transaction when writing an XID. Also
|
We always commit the entire transaction when writing an XID. Also
|
||||||
note that the return value is inverted.
|
note that the return value is inverted.
|
||||||
|
@ -937,9 +937,16 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent);
|
|||||||
bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db,
|
bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db,
|
||||||
char *new_table_name, char *new_table_alias,
|
char *new_table_name, char *new_table_alias,
|
||||||
bool skip_error);
|
bool skip_error);
|
||||||
|
|
||||||
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
|
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
|
||||||
bool force_switch);
|
bool force_switch);
|
||||||
|
|
||||||
|
bool mysql_opt_change_db(THD *thd,
|
||||||
|
const LEX_STRING *new_db_name,
|
||||||
|
LEX_STRING *saved_db_name,
|
||||||
|
bool force_switch,
|
||||||
|
bool *cur_db_changed);
|
||||||
|
|
||||||
void mysql_parse(THD *thd, const char *inBuf, uint length,
|
void mysql_parse(THD *thd, const char *inBuf, uint length,
|
||||||
const char ** semicolon);
|
const char ** semicolon);
|
||||||
|
|
||||||
|
@ -241,8 +241,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
ulong m_size; // Number of elements in the types array
|
ulong m_size; // Number of elements in the types array
|
||||||
field_type *m_type; // Array of type descriptors
|
field_type *m_type; // Array of type descriptors
|
||||||
uint16 *m_field_metadata;
|
|
||||||
uint m_field_metadata_size;
|
uint m_field_metadata_size;
|
||||||
|
uint16 *m_field_metadata;
|
||||||
uchar *m_null_bits;
|
uchar *m_null_bits;
|
||||||
uchar *m_memory;
|
uchar *m_memory;
|
||||||
};
|
};
|
||||||
|
144
sql/sp.cc
144
sql/sp.cc
@ -520,9 +520,10 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
|||||||
{
|
{
|
||||||
LEX *old_lex= thd->lex, newlex;
|
LEX *old_lex= thd->lex, newlex;
|
||||||
String defstr;
|
String defstr;
|
||||||
char old_db_buf[NAME_LEN+1];
|
char saved_cur_db_name_buf[NAME_LEN+1];
|
||||||
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
|
LEX_STRING saved_cur_db_name=
|
||||||
bool dbchanged;
|
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
|
||||||
|
bool cur_db_changed;
|
||||||
ulong old_sql_mode= thd->variables.sql_mode;
|
ulong old_sql_mode= thd->variables.sql_mode;
|
||||||
ha_rows old_select_limit= thd->variables.select_limit;
|
ha_rows old_select_limit= thd->variables.select_limit;
|
||||||
sp_rcontext *old_spcont= thd->spcont;
|
sp_rcontext *old_spcont= thd->spcont;
|
||||||
@ -567,16 +568,17 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Change current database if needed.
|
Change the current database (if needed).
|
||||||
|
|
||||||
collation_database will be updated here. However, it can be wrong,
|
TODO: why do we force switch here?
|
||||||
because it will contain the current value of the database collation.
|
|
||||||
We need collation_database to be fixed at the creation time -- so
|
|
||||||
we'll update it later in switch_query_ctx().
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((ret= sp_use_new_db(thd, name->m_db, &old_db, 1, &dbchanged)))
|
if (mysql_opt_change_db(thd, &name->m_db, &saved_cur_db_name, TRUE,
|
||||||
|
&cur_db_changed))
|
||||||
|
{
|
||||||
|
ret= SP_INTERNAL_ERROR;
|
||||||
goto end;
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
thd->spcont= NULL;
|
thd->spcont= NULL;
|
||||||
|
|
||||||
@ -585,34 +587,42 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
|||||||
|
|
||||||
lex_start(thd);
|
lex_start(thd);
|
||||||
|
|
||||||
if (parse_sql(thd, &lip, creation_ctx) || newlex.sphead == NULL)
|
ret= parse_sql(thd, &lip, creation_ctx) || newlex.sphead == NULL;
|
||||||
{
|
|
||||||
sp_head *sp= newlex.sphead;
|
|
||||||
|
|
||||||
if (dbchanged && (ret= mysql_change_db(thd, &old_db, TRUE)))
|
/*
|
||||||
goto end;
|
Force switching back to the saved current database (if changed),
|
||||||
delete sp;
|
because it may be NULL. In this case, mysql_change_db() would
|
||||||
ret= SP_PARSE_ERROR;
|
generate an error.
|
||||||
}
|
*/
|
||||||
else
|
|
||||||
|
if (cur_db_changed && mysql_change_db(thd, &saved_cur_db_name, TRUE))
|
||||||
{
|
{
|
||||||
if (dbchanged && (ret= mysql_change_db(thd, &old_db, TRUE)))
|
delete newlex.sphead;
|
||||||
goto end;
|
ret= SP_INTERNAL_ERROR;
|
||||||
*sphp= newlex.sphead;
|
goto end;
|
||||||
(*sphp)->set_definer(&definer_user_name, &definer_host_name);
|
|
||||||
(*sphp)->set_info(created, modified, &chistics, sql_mode);
|
|
||||||
(*sphp)->set_creation_ctx(creation_ctx);
|
|
||||||
(*sphp)->optimize();
|
|
||||||
/*
|
|
||||||
Not strictly necessary to invoke this method here, since we know
|
|
||||||
that we've parsed CREATE PROCEDURE/FUNCTION and not an
|
|
||||||
UPDATE/DELETE/INSERT/REPLACE/LOAD/CREATE TABLE, but we try to
|
|
||||||
maintain the invariant that this method is called for each
|
|
||||||
distinct statement, in case its logic is extended with other
|
|
||||||
types of analyses in future.
|
|
||||||
*/
|
|
||||||
newlex.set_trg_event_type_for_tables();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
delete newlex.sphead;
|
||||||
|
ret= SP_PARSE_ERROR;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
*sphp= newlex.sphead;
|
||||||
|
(*sphp)->set_definer(&definer_user_name, &definer_host_name);
|
||||||
|
(*sphp)->set_info(created, modified, &chistics, sql_mode);
|
||||||
|
(*sphp)->set_creation_ctx(creation_ctx);
|
||||||
|
(*sphp)->optimize();
|
||||||
|
/*
|
||||||
|
Not strictly necessary to invoke this method here, since we know
|
||||||
|
that we've parsed CREATE PROCEDURE/FUNCTION and not an
|
||||||
|
UPDATE/DELETE/INSERT/REPLACE/LOAD/CREATE TABLE, but we try to
|
||||||
|
maintain the invariant that this method is called for each
|
||||||
|
distinct statement, in case its logic is extended with other
|
||||||
|
types of analyses in future.
|
||||||
|
*/
|
||||||
|
newlex.set_trg_event_type_for_tables();
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
@ -2025,69 +2035,3 @@ create_string(THD *thd, String *buf,
|
|||||||
buf->append(body, bodylen);
|
buf->append(body, bodylen);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
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)
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
sp_use_new_db(THD *thd, LEX_STRING new_db, LEX_STRING *old_db,
|
|
||||||
bool no_access_check, bool *dbchangedp)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
DBUG_ENTER("sp_use_new_db");
|
|
||||||
DBUG_PRINT("enter", ("newdb: %s", new_db.str));
|
|
||||||
|
|
||||||
/*
|
|
||||||
A stored routine always belongs to some database. The
|
|
||||||
old database (old_db) might be NULL, but to restore the
|
|
||||||
old database we will use mysql_change_db.
|
|
||||||
*/
|
|
||||||
DBUG_ASSERT(new_db.str && new_db.length);
|
|
||||||
|
|
||||||
if (thd->db)
|
|
||||||
{
|
|
||||||
old_db->length= (strmake(old_db->str, thd->db, old_db->length) -
|
|
||||||
old_db->str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
old_db->str[0]= '\0';
|
|
||||||
old_db->length= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't change the database if the new name is the same as the old one. */
|
|
||||||
if (my_strcasecmp(system_charset_info, old_db->str, new_db.str) == 0)
|
|
||||||
{
|
|
||||||
*dbchangedp= FALSE;
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret= mysql_change_db(thd, &new_db, no_access_check);
|
|
||||||
|
|
||||||
*dbchangedp= ret == 0;
|
|
||||||
DBUG_RETURN(ret);
|
|
||||||
}
|
|
||||||
|
11
sql/sp.h
11
sql/sp.h
@ -85,15 +85,4 @@ extern "C" uchar* sp_sroutine_key(const uchar *ptr, size_t *plen,
|
|||||||
*/
|
*/
|
||||||
TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup);
|
TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup);
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Do a "use new_db". The current db is stored at old_db. If new_db is the
|
|
||||||
same as the current one, nothing is changed. dbchangedp is set to true if
|
|
||||||
the db was actually changed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
sp_use_new_db(THD *thd, LEX_STRING new_db, LEX_STRING *old_db,
|
|
||||||
bool no_access_check, bool *dbchangedp);
|
|
||||||
|
|
||||||
#endif /* _SP_H_ */
|
#endif /* _SP_H_ */
|
||||||
|
@ -249,11 +249,14 @@ sp_get_flags_for_command(LEX *lex)
|
|||||||
case SQLCOM_CREATE_TRIGGER:
|
case SQLCOM_CREATE_TRIGGER:
|
||||||
case SQLCOM_CREATE_USER:
|
case SQLCOM_CREATE_USER:
|
||||||
case SQLCOM_ALTER_TABLE:
|
case SQLCOM_ALTER_TABLE:
|
||||||
|
case SQLCOM_GRANT:
|
||||||
|
case SQLCOM_REVOKE:
|
||||||
case SQLCOM_BEGIN:
|
case SQLCOM_BEGIN:
|
||||||
case SQLCOM_RENAME_TABLE:
|
case SQLCOM_RENAME_TABLE:
|
||||||
case SQLCOM_RENAME_USER:
|
case SQLCOM_RENAME_USER:
|
||||||
case SQLCOM_DROP_INDEX:
|
case SQLCOM_DROP_INDEX:
|
||||||
case SQLCOM_DROP_DB:
|
case SQLCOM_DROP_DB:
|
||||||
|
case SQLCOM_REVOKE_ALL:
|
||||||
case SQLCOM_DROP_USER:
|
case SQLCOM_DROP_USER:
|
||||||
case SQLCOM_DROP_VIEW:
|
case SQLCOM_DROP_VIEW:
|
||||||
case SQLCOM_DROP_TRIGGER:
|
case SQLCOM_DROP_TRIGGER:
|
||||||
@ -1013,9 +1016,10 @@ bool
|
|||||||
sp_head::execute(THD *thd)
|
sp_head::execute(THD *thd)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("sp_head::execute");
|
DBUG_ENTER("sp_head::execute");
|
||||||
char old_db_buf[NAME_LEN+1];
|
char saved_cur_db_name_buf[NAME_LEN+1];
|
||||||
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
|
LEX_STRING saved_cur_db_name=
|
||||||
bool dbchanged;
|
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
|
||||||
|
bool cur_db_changed= FALSE;
|
||||||
sp_rcontext *ctx;
|
sp_rcontext *ctx;
|
||||||
bool err_status= FALSE;
|
bool err_status= FALSE;
|
||||||
uint ip= 0;
|
uint ip= 0;
|
||||||
@ -1070,8 +1074,11 @@ sp_head::execute(THD *thd)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (m_db.length &&
|
if (m_db.length &&
|
||||||
(err_status= sp_use_new_db(thd, m_db, &old_db, 0, &dbchanged)))
|
(err_status= mysql_opt_change_db(thd, &m_db, &saved_cur_db_name, FALSE,
|
||||||
|
&cur_db_changed)))
|
||||||
|
{
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if ((ctx= thd->spcont))
|
if ((ctx= thd->spcont))
|
||||||
ctx->clear_handler();
|
ctx->clear_handler();
|
||||||
@ -1252,14 +1259,14 @@ sp_head::execute(THD *thd)
|
|||||||
If the DB has changed, the pointer has changed too, but the
|
If the DB has changed, the pointer has changed too, but the
|
||||||
original thd->db will then have been freed
|
original thd->db will then have been freed
|
||||||
*/
|
*/
|
||||||
if (dbchanged)
|
if (cur_db_changed && !thd->killed)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
No access check when changing back to where we came from.
|
Force switching back to the saved current database, because it may be
|
||||||
(It would generate an error from mysql_change_db() when old_db=="")
|
NULL. In this case, mysql_change_db() would generate an error.
|
||||||
*/
|
*/
|
||||||
if (! thd->killed)
|
|
||||||
err_status|= mysql_change_db(thd, &old_db, TRUE);
|
err_status|= mysql_change_db(thd, &saved_cur_db_name, TRUE);
|
||||||
}
|
}
|
||||||
m_flags&= ~IS_INVOKED;
|
m_flags&= ~IS_INVOKED;
|
||||||
DBUG_PRINT("info",
|
DBUG_PRINT("info",
|
||||||
|
@ -7747,6 +7747,9 @@ open_performance_schema_table(THD *thd, TABLE_LIST *one_table,
|
|||||||
*/
|
*/
|
||||||
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
thd->restore_backup_open_tables_state(backup);
|
||||||
|
|
||||||
thd->utime_after_lock= save_utime_after_lock;
|
thd->utime_after_lock= save_utime_after_lock;
|
||||||
DBUG_RETURN(table);
|
DBUG_RETURN(table);
|
||||||
}
|
}
|
||||||
@ -7762,24 +7765,25 @@ void close_performance_schema_table(THD *thd, Open_tables_state *backup)
|
|||||||
{
|
{
|
||||||
bool found_old_table;
|
bool found_old_table;
|
||||||
|
|
||||||
if (thd->lock)
|
/*
|
||||||
{
|
If open_performance_schema_table() fails,
|
||||||
/*
|
this function should not be called.
|
||||||
Note:
|
*/
|
||||||
We do not create explicitly a separate transaction for the
|
DBUG_ASSERT(thd->lock != NULL);
|
||||||
performance table I/O, but borrow the current transaction.
|
|
||||||
lock + unlock will autocommit the change done in the
|
|
||||||
performance schema table: this is the expected result.
|
|
||||||
The current transaction should not be affected by this code.
|
|
||||||
TODO: Note that if a transactional engine is used for log tables,
|
|
||||||
this code will need to be revised, as a separate transaction
|
|
||||||
might be needed.
|
|
||||||
*/
|
|
||||||
mysql_unlock_tables(thd, thd->lock);
|
|
||||||
thd->lock= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
safe_mutex_assert_not_owner(&LOCK_open);
|
/*
|
||||||
|
Note:
|
||||||
|
We do not create explicitly a separate transaction for the
|
||||||
|
performance table I/O, but borrow the current transaction.
|
||||||
|
lock + unlock will autocommit the change done in the
|
||||||
|
performance schema table: this is the expected result.
|
||||||
|
The current transaction should not be affected by this code.
|
||||||
|
TODO: Note that if a transactional engine is used for log tables,
|
||||||
|
this code will need to be revised, as a separate transaction
|
||||||
|
might be needed.
|
||||||
|
*/
|
||||||
|
mysql_unlock_tables(thd, thd->lock);
|
||||||
|
thd->lock= 0;
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_open);
|
pthread_mutex_lock(&LOCK_open);
|
||||||
|
|
||||||
|
@ -387,7 +387,6 @@ THD::THD()
|
|||||||
init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
|
init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
|
||||||
stmt_arena= this;
|
stmt_arena= this;
|
||||||
thread_stack= 0;
|
thread_stack= 0;
|
||||||
db= 0;
|
|
||||||
catalog= (char*)"std"; // the only catalog we have for now
|
catalog= (char*)"std"; // the only catalog we have for now
|
||||||
main_security_ctx.init();
|
main_security_ctx.init();
|
||||||
security_ctx= &main_security_ctx;
|
security_ctx= &main_security_ctx;
|
||||||
@ -395,7 +394,7 @@ THD::THD()
|
|||||||
query_start_used= 0;
|
query_start_used= 0;
|
||||||
count_cuted_fields= CHECK_FIELD_IGNORE;
|
count_cuted_fields= CHECK_FIELD_IGNORE;
|
||||||
killed= NOT_KILLED;
|
killed= NOT_KILLED;
|
||||||
db_length= col_access=0;
|
col_access=0;
|
||||||
query_error= thread_specific_used= FALSE;
|
query_error= thread_specific_used= FALSE;
|
||||||
hash_clear(&handler_tables_hash);
|
hash_clear(&handler_tables_hash);
|
||||||
tmp_table=0;
|
tmp_table=0;
|
||||||
@ -2040,7 +2039,9 @@ Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg,
|
|||||||
lex(lex_arg),
|
lex(lex_arg),
|
||||||
query(0),
|
query(0),
|
||||||
query_length(0),
|
query_length(0),
|
||||||
cursor(0)
|
cursor(0),
|
||||||
|
db(NULL),
|
||||||
|
db_length(0)
|
||||||
{
|
{
|
||||||
name.str= NULL;
|
name.str= NULL;
|
||||||
}
|
}
|
||||||
|
@ -593,6 +593,22 @@ public:
|
|||||||
uint32 query_length; // current query length
|
uint32 query_length; // current query length
|
||||||
Server_side_cursor *cursor;
|
Server_side_cursor *cursor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Name of the current (default) database.
|
||||||
|
|
||||||
|
If there is the current (default) database, "db" contains its name. If
|
||||||
|
there is no current (default) database, "db" is NULL and "db_length" is
|
||||||
|
0. In other words, "db", "db_length" must either be NULL, or contain a
|
||||||
|
valid database name.
|
||||||
|
|
||||||
|
@note this attribute is set and alloced by the slave SQL thread (for
|
||||||
|
the THD of that thread); that thread is (and must remain, for now) the
|
||||||
|
only responsible for freeing this member.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *db;
|
||||||
|
uint db_length;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/* This constructor is called for backup statements */
|
/* This constructor is called for backup statements */
|
||||||
@ -1024,18 +1040,21 @@ public:
|
|||||||
*/
|
*/
|
||||||
char *thread_stack;
|
char *thread_stack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Currently selected catalog.
|
||||||
|
*/
|
||||||
|
char *catalog;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
db - currently selected database
|
WARNING: some members of THD (currently 'Statement::db',
|
||||||
catalog - currently selected catalog
|
'catalog' and 'query') are set and alloced by the slave SQL thread
|
||||||
WARNING: some members of THD (currently 'db', 'catalog' and 'query') are
|
(for the THD of that thread); that thread is (and must remain, for now)
|
||||||
set and alloced by the slave SQL thread (for the THD of that thread); that
|
the only responsible for freeing these 3 members. If you add members
|
||||||
thread is (and must remain, for now) the only responsible for freeing these
|
here, and you add code to set them in replication, don't forget to
|
||||||
3 members. If you add members here, and you add code to set them in
|
free_them_and_set_them_to_0 in replication properly. For details see
|
||||||
replication, don't forget to free_them_and_set_them_to_0 in replication
|
the 'err:' label of the handle_slave_sql() in sql/slave.cc.
|
||||||
properly. For details see the 'err:' label of the handle_slave_sql()
|
*/
|
||||||
in sql/slave.cc.
|
|
||||||
*/
|
|
||||||
char *db, *catalog;
|
|
||||||
Security_context main_security_ctx;
|
Security_context main_security_ctx;
|
||||||
Security_context *security_ctx;
|
Security_context *security_ctx;
|
||||||
|
|
||||||
@ -1390,7 +1409,6 @@ public:
|
|||||||
uint tmp_table, global_read_lock;
|
uint tmp_table, global_read_lock;
|
||||||
uint server_status,open_options;
|
uint server_status,open_options;
|
||||||
enum enum_thread_type system_thread;
|
enum enum_thread_type system_thread;
|
||||||
uint db_length;
|
|
||||||
uint select_number; //number of select (used for EXPLAIN)
|
uint select_number; //number of select (used for EXPLAIN)
|
||||||
/* variables.transaction_isolation is reset to this after each commit */
|
/* variables.transaction_isolation is reset to this after each commit */
|
||||||
enum_tx_isolation session_tx_isolation;
|
enum_tx_isolation session_tx_isolation;
|
||||||
@ -1802,11 +1820,26 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Initialize the current database from a NULL-terminated string with length
|
Set the current database; use deep copy of C-string.
|
||||||
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
|
@param new_db a pointer to the new database name.
|
||||||
database selected (in addition to the error message set by malloc).
|
@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 {db, 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)
|
bool set_db(const char *new_db, size_t new_db_len)
|
||||||
{
|
{
|
||||||
@ -1821,6 +1854,18 @@ public:
|
|||||||
db_length= db ? new_db_len : 0;
|
db_length= db ? new_db_len : 0;
|
||||||
return new_db && !db;
|
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 {db, 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)
|
void reset_db(char *new_db, size_t new_db_len)
|
||||||
{
|
{
|
||||||
db= new_db;
|
db= new_db;
|
||||||
|
181
sql/sql_db.cc
181
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 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 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 */
|
/* Database lock hash */
|
||||||
@ -997,7 +1001,7 @@ exit:
|
|||||||
it to 0.
|
it to 0.
|
||||||
*/
|
*/
|
||||||
if (thd->db && !strcmp(thd->db, db))
|
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));
|
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
|
||||||
start_waiting_global_read_lock(thd);
|
start_waiting_global_read_lock(thd);
|
||||||
exit2:
|
exit2:
|
||||||
@ -1355,22 +1359,108 @@ static void mysql_change_db_impl(THD *thd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Change the current database.
|
Backup the current database name before switch.
|
||||||
|
|
||||||
|
@param[in] thd thread handle
|
||||||
|
@param[in, out] saved_db_name IN: "str" points to a buffer where to store
|
||||||
|
the old database name, "length" contains the
|
||||||
|
buffer size
|
||||||
|
OUT: if the current (default) database is
|
||||||
|
not NULL, its name is copied to the
|
||||||
|
buffer pointed at by "str"
|
||||||
|
and "length" is updated accordingly.
|
||||||
|
Otherwise "str" is set to NULL and
|
||||||
|
"length" is set to 0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void backup_current_db_name(THD *thd,
|
||||||
|
LEX_STRING *saved_db_name)
|
||||||
|
{
|
||||||
|
if (!thd->db)
|
||||||
|
{
|
||||||
|
/* No current (default) database selected. */
|
||||||
|
|
||||||
|
saved_db_name->str= NULL;
|
||||||
|
saved_db_name->length= 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strmake(saved_db_name->str, thd->db, saved_db_name->length);
|
||||||
|
saved_db_name->length= thd->db_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return TRUE if db1_name is equal to db2_name, FALSE otherwise.
|
||||||
|
|
||||||
|
The function allows to compare database names according to the MySQL
|
||||||
|
rules. The database names db1 and db2 are equal if:
|
||||||
|
- db1 is NULL and db2 is NULL;
|
||||||
|
or
|
||||||
|
- db1 is not-NULL, db2 is not-NULL, db1 is equal (ignoring case) to
|
||||||
|
db2 in system character set (UTF8).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
cmp_db_names(const char *db1_name,
|
||||||
|
const char *db2_name)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
/* db1 is NULL and db2 is NULL */
|
||||||
|
!db1_name && !db2_name ||
|
||||||
|
|
||||||
|
/* db1 is not-NULL, db2 is not-NULL, db1 == db2. */
|
||||||
|
db1_name && db2_name &&
|
||||||
|
my_strcasecmp(system_charset_info, db1_name, db2_name) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Change the current database and its attributes unconditionally.
|
||||||
|
|
||||||
@param thd thread handle
|
@param thd thread handle
|
||||||
@param new_db_name database name
|
@param new_db_name database name
|
||||||
@param force_switch if this flag is set (TRUE), mysql_change_db() will
|
@param force_switch if force_switch is FALSE, then the operation will fail if
|
||||||
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
|
- new_db_name is NULL or empty;
|
||||||
database, check access rights (unless called with no_access_check), and
|
|
||||||
set the current database. This function is called to change the current
|
- OR new database name is invalid
|
||||||
database upon user request (COM_CHANGE_DB command) or temporarily, to
|
(check_db_name() failed);
|
||||||
execute a stored routine.
|
|
||||||
|
- 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
|
This function is not the only way to switch the database that is
|
||||||
currently employed. When the replication slave thread switches the
|
currently employed. When the replication slave thread switches the
|
||||||
@ -1407,8 +1497,13 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
|
|||||||
if (force_switch)
|
if (force_switch)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
This can only happen when we restore the old db in THD after
|
This can happen only if we're switching the current database back
|
||||||
execution of a routine is complete. Change db to NULL.
|
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);
|
mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
|
||||||
@ -1426,7 +1521,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,
|
if (my_strcasecmp(system_charset_info, new_db_name->str,
|
||||||
INFORMATION_SCHEMA_NAME.str) == 0)
|
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,
|
mysql_change_db_impl(thd, &INFORMATION_SCHEMA_NAME, SELECT_ACL,
|
||||||
system_charset_info);
|
system_charset_info);
|
||||||
@ -1453,8 +1548,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().
|
even if we are called from sp_head::execute().
|
||||||
|
|
||||||
It's next to impossible however to get this error when we are called
|
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
|
from sp_head::execute(). But let's switch the current database to NULL
|
||||||
to be sure.
|
in this case to be sure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (check_db_name(&new_db_file_name))
|
if (check_db_name(&new_db_file_name))
|
||||||
@ -1463,10 +1558,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));
|
my_free(new_db_file_name.str, MYF(0));
|
||||||
|
|
||||||
if (force_switch)
|
if (force_switch)
|
||||||
{
|
|
||||||
/* Change db to NULL. */
|
|
||||||
mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
|
mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
|
||||||
}
|
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1501,6 +1594,8 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
|
|||||||
{
|
{
|
||||||
if (force_switch)
|
if (force_switch)
|
||||||
{
|
{
|
||||||
|
/* Throw a warning and free new_db_file_name. */
|
||||||
|
|
||||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
|
ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
|
||||||
new_db_file_name.str);
|
new_db_file_name.str);
|
||||||
@ -1511,12 +1606,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);
|
mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
|
||||||
|
|
||||||
|
/* The operation succeed. */
|
||||||
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* Report an error and free new_db_file_name. */
|
||||||
|
|
||||||
my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
|
my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
|
||||||
my_free(new_db_file_name.str, MYF(0));
|
my_free(new_db_file_name.str, MYF(0));
|
||||||
|
|
||||||
|
/* The operation failed. */
|
||||||
|
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1534,6 +1636,43 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Change the current database and its attributes if needed.
|
||||||
|
|
||||||
|
@param thd thread handle
|
||||||
|
@param new_db_name database name
|
||||||
|
@param[in, out] saved_db_name IN: "str" points to a buffer where to store
|
||||||
|
the old database name, "length" contains the
|
||||||
|
buffer size
|
||||||
|
OUT: if the current (default) database is
|
||||||
|
not NULL, its name is copied to the
|
||||||
|
buffer pointed at by "str"
|
||||||
|
and "length" is updated accordingly.
|
||||||
|
Otherwise "str" is set to NULL and
|
||||||
|
"length" is set to 0.
|
||||||
|
@param force_switch @see mysql_change_db()
|
||||||
|
@param[out] cur_db_changed out-flag to indicate whether the current
|
||||||
|
database has been changed (valid only if
|
||||||
|
the function suceeded)
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool mysql_opt_change_db(THD *thd,
|
||||||
|
const LEX_STRING *new_db_name,
|
||||||
|
LEX_STRING *saved_db_name,
|
||||||
|
bool force_switch,
|
||||||
|
bool *cur_db_changed)
|
||||||
|
{
|
||||||
|
*cur_db_changed= !cmp_db_names(thd->db, new_db_name->str);
|
||||||
|
|
||||||
|
if (!*cur_db_changed)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
backup_current_db_name(thd, saved_db_name);
|
||||||
|
|
||||||
|
return mysql_change_db(thd, new_db_name, force_switch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lock_databases(THD *thd, const char *db1, uint length1,
|
lock_databases(THD *thd, const char *db1, uint length1,
|
||||||
const char *db2, uint length2)
|
const char *db2, uint length2)
|
||||||
@ -1829,7 +1968,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 */
|
/* Step9: Let's do "use newdb" if we renamed the current database */
|
||||||
if (change_to_newdb)
|
if (change_to_newdb)
|
||||||
error|= mysql_change_db(thd, new_db, 0);
|
error|= mysql_change_db(thd, new_db, FALSE);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
pthread_mutex_lock(&LOCK_lock_db);
|
pthread_mutex_lock(&LOCK_lock_db);
|
||||||
|
@ -444,7 +444,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|||||||
cond->cleanup(); // File was reopened
|
cond->cleanup(); // File was reopened
|
||||||
if ((!cond->fixed &&
|
if ((!cond->fixed &&
|
||||||
cond->fix_fields(thd, &cond)) || cond->check_cols(1))
|
cond->fix_fields(thd, &cond)) || cond->check_cols(1))
|
||||||
goto err0;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyname)
|
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)
|
if ((keyno=find_type(keyname, &table->s->keynames, 1+2)-1)<0)
|
||||||
{
|
{
|
||||||
my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), keyname, tables->alias);
|
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,
|
if (insert_fields(thd, &thd->lex->select_lex.context,
|
||||||
tables->db, tables->alias, &it, 0))
|
tables->db, tables->alias, &it, 0))
|
||||||
goto err0;
|
goto err;
|
||||||
|
|
||||||
protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
|
protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
|
||||||
|
|
||||||
|
@ -397,7 +397,7 @@ void upgrade_lock_type(THD *thd, thr_lock_type *lock_type,
|
|||||||
if (duplic == DUP_UPDATE ||
|
if (duplic == DUP_UPDATE ||
|
||||||
duplic == DUP_REPLACE && *lock_type == TL_WRITE_CONCURRENT_INSERT)
|
duplic == DUP_REPLACE && *lock_type == TL_WRITE_CONCURRENT_INSERT)
|
||||||
{
|
{
|
||||||
*lock_type= TL_WRITE;
|
*lock_type= TL_WRITE_DEFAULT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +323,6 @@ void lex_start(THD *thd)
|
|||||||
lex->length=0;
|
lex->length=0;
|
||||||
lex->part_info= 0;
|
lex->part_info= 0;
|
||||||
lex->select_lex.in_sum_expr=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_alloc.empty();
|
||||||
lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
|
lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
|
||||||
lex->select_lex.group_list.empty();
|
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)
|
int MYSQLlex(void *arg, void *yythd)
|
||||||
{
|
{
|
||||||
reg1 uchar c;
|
reg1 uchar c;
|
||||||
|
bool comment_closed;
|
||||||
int tokval, result_state;
|
int tokval, result_state;
|
||||||
uint length;
|
uint length;
|
||||||
enum my_lex_states state;
|
enum my_lex_states state;
|
||||||
@ -1212,7 +1212,10 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
/*
|
/*
|
||||||
The special comment format is very strict:
|
The special comment format is very strict:
|
||||||
'/' '*' '!', followed by exactly
|
'/' '*' '!', 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];
|
char version_str[6];
|
||||||
version_str[0]= lip->yyPeekn(0);
|
version_str[0]= lip->yyPeekn(0);
|
||||||
@ -1231,7 +1234,7 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
ulong version;
|
ulong version;
|
||||||
version=strtol(version_str, NULL, 10);
|
version=strtol(version_str, NULL, 10);
|
||||||
|
|
||||||
/* Accept 'M' 'M' 'm' 'm' 'm' */
|
/* Accept 'M' 'm' 'm' 'd' 'd' */
|
||||||
lip->yySkipn(5);
|
lip->yySkipn(5);
|
||||||
|
|
||||||
if (version <= MYSQL_VERSION_ID)
|
if (version <= MYSQL_VERSION_ID)
|
||||||
@ -1255,16 +1258,36 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
lip->yySkip(); // Accept /
|
lip->yySkip(); // Accept /
|
||||||
lip->yySkip(); // Accept *
|
lip->yySkip(); // Accept *
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
while (! lip->eof() &&
|
Discard:
|
||||||
((c=lip->yyGet()) != '*' || lip->yyPeek() != '/'))
|
- 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++;
|
lip->yylineno++;
|
||||||
}
|
}
|
||||||
if (! lip->eof())
|
/* Unbalanced comments with a missing '*' '/' are a syntax error */
|
||||||
lip->yySkip(); // remove last '/'
|
if (! comment_closed)
|
||||||
|
return (ABORT_SYM);
|
||||||
state = MY_LEX_START; // Try again
|
state = MY_LEX_START; // Try again
|
||||||
|
lip->in_comment= NO_COMMENT;
|
||||||
lip->set_echo(TRUE);
|
lip->set_echo(TRUE);
|
||||||
break;
|
break;
|
||||||
case MY_LEX_END_LONG_COMMENT:
|
case MY_LEX_END_LONG_COMMENT:
|
||||||
@ -1316,6 +1339,9 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
lip->set_echo(FALSE);
|
lip->set_echo(FALSE);
|
||||||
lip->yySkip();
|
lip->yySkip();
|
||||||
lip->set_echo(TRUE);
|
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
|
lip->next_state=MY_LEX_END; // Mark for next loop
|
||||||
return(END_OF_INPUT);
|
return(END_OF_INPUT);
|
||||||
}
|
}
|
||||||
@ -1556,7 +1582,6 @@ void st_select_lex::init_select()
|
|||||||
options= 0;
|
options= 0;
|
||||||
sql_cache= SQL_CACHE_UNSPECIFIED;
|
sql_cache= SQL_CACHE_UNSPECIFIED;
|
||||||
braces= 0;
|
braces= 0;
|
||||||
expr_list.empty();
|
|
||||||
interval_list.empty();
|
interval_list.empty();
|
||||||
ftfunc_list_alloc.empty();
|
ftfunc_list_alloc.empty();
|
||||||
inner_sum_func_list= 0;
|
inner_sum_func_list= 0;
|
||||||
|
@ -596,7 +596,6 @@ public:
|
|||||||
const char *type; /* type of select for EXPLAIN */
|
const char *type; /* type of select for EXPLAIN */
|
||||||
|
|
||||||
SQL_LIST order_list; /* ORDER clause */
|
SQL_LIST order_list; /* ORDER clause */
|
||||||
List<List_item> expr_list;
|
|
||||||
SQL_LIST *gorder_list;
|
SQL_LIST *gorder_list;
|
||||||
Item *select_limit, *offset_limit; /* LIMIT clause parameters */
|
Item *select_limit, *offset_limit; /* LIMIT clause parameters */
|
||||||
// Arrays of pointers to top elements of all_fields list
|
// Arrays of pointers to top elements of all_fields list
|
||||||
|
@ -3381,6 +3381,8 @@ end_with_restore_list:
|
|||||||
}
|
}
|
||||||
case SQLCOM_REVOKE_ALL:
|
case SQLCOM_REVOKE_ALL:
|
||||||
{
|
{
|
||||||
|
if (end_active_trans(thd))
|
||||||
|
goto error;
|
||||||
if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
|
if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
|
||||||
check_global_access(thd,CREATE_USER_ACL))
|
check_global_access(thd,CREATE_USER_ACL))
|
||||||
break;
|
break;
|
||||||
@ -3392,6 +3394,9 @@ end_with_restore_list:
|
|||||||
case SQLCOM_REVOKE:
|
case SQLCOM_REVOKE:
|
||||||
case SQLCOM_GRANT:
|
case SQLCOM_GRANT:
|
||||||
{
|
{
|
||||||
|
if (end_active_trans(thd))
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
|
if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
|
||||||
first_table ? first_table->db : select_lex->db,
|
first_table ? first_table->db : select_lex->db,
|
||||||
first_table ? &first_table->grant.privilege : 0,
|
first_table ? &first_table->grant.privilege : 0,
|
||||||
|
@ -2868,6 +2868,19 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
|||||||
init_param_array(this);
|
init_param_array(this);
|
||||||
lex->set_trg_event_type_for_tables();
|
lex->set_trg_event_type_for_tables();
|
||||||
|
|
||||||
|
/* Remember the current database. */
|
||||||
|
|
||||||
|
if (thd->db && thd->db_length)
|
||||||
|
{
|
||||||
|
db= this->strmake(thd->db, thd->db_length);
|
||||||
|
db_length= thd->db_length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
db= NULL;
|
||||||
|
db_length= 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
While doing context analysis of the query (in check_prepared_statement)
|
While doing context analysis of the query (in check_prepared_statement)
|
||||||
we allocate a lot of additional memory: for open tables, JOINs, derived
|
we allocate a lot of additional memory: for open tables, JOINs, derived
|
||||||
@ -2974,6 +2987,13 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
|
|||||||
Query_arena *old_stmt_arena;
|
Query_arena *old_stmt_arena;
|
||||||
bool error= TRUE;
|
bool error= TRUE;
|
||||||
|
|
||||||
|
char saved_cur_db_name_buf[NAME_LEN+1];
|
||||||
|
LEX_STRING saved_cur_db_name=
|
||||||
|
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
|
||||||
|
bool cur_db_changed;
|
||||||
|
|
||||||
|
LEX_STRING stmt_db_name= { db, db_length };
|
||||||
|
|
||||||
status_var_increment(thd->status_var.com_stmt_execute);
|
status_var_increment(thd->status_var.com_stmt_execute);
|
||||||
|
|
||||||
/* Check if we got an error when sending long data */
|
/* Check if we got an error when sending long data */
|
||||||
@ -3022,6 +3042,21 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
thd->set_n_backup_statement(this, &stmt_backup);
|
thd->set_n_backup_statement(this, &stmt_backup);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Change the current database (if needed).
|
||||||
|
|
||||||
|
Force switching, because the database of the prepared statement may be
|
||||||
|
NULL (prepared statements can be created while no current database
|
||||||
|
selected).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (mysql_opt_change_db(thd, &stmt_db_name, &saved_cur_db_name, TRUE,
|
||||||
|
&cur_db_changed))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
/* Allocate query. */
|
||||||
|
|
||||||
if (expanded_query->length() &&
|
if (expanded_query->length() &&
|
||||||
alloc_query(thd, (char*) expanded_query->ptr(),
|
alloc_query(thd, (char*) expanded_query->ptr(),
|
||||||
expanded_query->length()+1))
|
expanded_query->length()+1))
|
||||||
@ -3050,6 +3085,8 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
|
|||||||
|
|
||||||
thd->protocol= protocol; /* activate stmt protocol */
|
thd->protocol= protocol; /* activate stmt protocol */
|
||||||
|
|
||||||
|
/* Go! */
|
||||||
|
|
||||||
if (open_cursor)
|
if (open_cursor)
|
||||||
error= mysql_open_cursor(thd, (uint) ALWAYS_MATERIALIZED_CURSOR,
|
error= mysql_open_cursor(thd, (uint) ALWAYS_MATERIALIZED_CURSOR,
|
||||||
&result, &cursor);
|
&result, &cursor);
|
||||||
@ -3068,6 +3105,17 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Restore the current database (if changed).
|
||||||
|
|
||||||
|
Force switching back to the saved current database (if changed),
|
||||||
|
because it may be NULL. In this case, mysql_change_db() would generate
|
||||||
|
an error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (cur_db_changed)
|
||||||
|
mysql_change_db(thd, &saved_cur_db_name, TRUE);
|
||||||
|
|
||||||
thd->protocol= &thd->protocol_text; /* use normal protocol */
|
thd->protocol= &thd->protocol_text; /* use normal protocol */
|
||||||
|
|
||||||
/* Assert that if an error, no cursor is open */
|
/* Assert that if an error, no cursor is open */
|
||||||
|
334
sql/sql_yacc.yy
334
sql/sql_yacc.yy
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
#define MYSQL_YACC
|
#define MYSQL_YACC
|
||||||
#define YYINITDEPTH 100
|
#define YYINITDEPTH 100
|
||||||
#define YYMAXDEPTH 3200 /* Because of 64K stack */
|
#define YYMAXDEPTH 3200 /* Because of 64K stack */
|
||||||
#define Lex (YYTHD->lex)
|
#define Lex (YYTHD->lex)
|
||||||
#define Select Lex->current_select
|
#define Select Lex->current_select
|
||||||
#include "mysql_priv.h"
|
#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);
|
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
|
Currently there are 280 shift/reduce conflicts.
|
||||||
new conflicts any more.
|
We should not introduce new conflicts any more.
|
||||||
*/
|
*/
|
||||||
%expect 286
|
%expect 280
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Comments for TOKENS.
|
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. */
|
/* A dummy token to force the priority of table_ref production in a join. */
|
||||||
%left TABLE_REF_PRIORITY
|
%left TABLE_REF_PRIORITY
|
||||||
%left SET_VAR
|
%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 AND_SYM AND_AND_SYM
|
||||||
%left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE
|
%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
|
%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 '~'
|
%left NEG '~'
|
||||||
%right NOT_SYM NOT2_SYM
|
%right NOT_SYM NOT2_SYM
|
||||||
%right BINARY COLLATE_SYM
|
%right BINARY COLLATE_SYM
|
||||||
|
%left INTERVAL_SYM
|
||||||
|
|
||||||
%type <lex_str>
|
%type <lex_str>
|
||||||
IDENT IDENT_QUOTED TEXT_STRING DECIMAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM
|
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>
|
%type <item>
|
||||||
literal text_literal insert_ident order_ident
|
literal text_literal insert_ident order_ident
|
||||||
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
|
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_pri
|
||||||
predicate bit_expr bit_term bit_factor value_expr term factor
|
predicate bit_expr
|
||||||
table_wild simple_expr udf_expr
|
table_wild simple_expr udf_expr
|
||||||
expr_or_default set_expr_or_default interval_expr
|
expr_or_default set_expr_or_default interval_expr
|
||||||
param_marker geometry_function
|
param_marker geometry_function
|
||||||
@ -1171,7 +1173,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
NUM_literal
|
NUM_literal
|
||||||
|
|
||||||
%type <item_list>
|
%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
|
ident_list ident_list_arg opt_expr_list
|
||||||
|
|
||||||
%type <var_type>
|
%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
|
select_item_list select_item values_list no_braces
|
||||||
opt_limit_clause delete_limit_clause fields opt_values values
|
opt_limit_clause delete_limit_clause fields opt_values values
|
||||||
procedure_list procedure_list2 procedure_item
|
procedure_list procedure_list2 procedure_item
|
||||||
expr_list2 udf_expr_list3 handler
|
handler
|
||||||
opt_precision opt_ignore opt_column opt_restrict
|
opt_precision opt_ignore opt_column opt_restrict
|
||||||
grant revoke set lock unlock string_list field_options field_option
|
grant revoke set lock unlock string_list field_options field_option
|
||||||
field_opt_list opt_binary table_lock_list table_lock
|
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
|
; <-- on a line by itself, starts at col 9
|
||||||
|
|
||||||
Also, please do not use any <TAB>, but spaces.
|
Also, please do not use any <TAB>, but spaces.
|
||||||
Having a uniform indentation in this file helps
|
Having a uniform indentation in this file helps
|
||||||
code reviews, patches, merges, and make maintenance easier.
|
code reviews, patches, merges, and make maintenance easier.
|
||||||
Thanks.
|
Tip: grep [[:cntrl:]] sql_yacc.yy
|
||||||
|
Thanks.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
query:
|
query:
|
||||||
@ -5157,7 +5160,7 @@ opt_bin_charset:
|
|||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| charset charset_name { Lex->charset=$2; }
|
| charset charset_name { Lex->charset=$2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_primary:
|
opt_primary:
|
||||||
@ -5379,7 +5382,7 @@ alter:
|
|||||||
lex->create_info.row_type= ROW_TYPE_NOT_USED;
|
lex->create_info.row_type= ROW_TYPE_NOT_USED;
|
||||||
lex->alter_info.reset();
|
lex->alter_info.reset();
|
||||||
lex->no_write_to_binlog= 0;
|
lex->no_write_to_binlog= 0;
|
||||||
lex->create_info.storage_media= HA_SM_DEFAULT;
|
lex->create_info.storage_media= HA_SM_DEFAULT;
|
||||||
}
|
}
|
||||||
alter_commands
|
alter_commands
|
||||||
{}
|
{}
|
||||||
@ -6564,83 +6567,131 @@ optional_braces:
|
|||||||
;
|
;
|
||||||
|
|
||||||
/* all possible expressions */
|
/* all possible expressions */
|
||||||
expr:
|
expr:
|
||||||
bool_term { Select->expr_list.push_front(new List<Item>); }
|
expr or expr %prec OR_SYM
|
||||||
bool_or_expr
|
|
||||||
{
|
{
|
||||||
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);
|
item1= (Item_cond_or*) $1;
|
||||||
$$= new Item_cond_or(*list);
|
if (is_cond_or($3))
|
||||||
/* optimize construction of logical OR to reduce
|
{
|
||||||
amount of objects for complex expressions */
|
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
|
else
|
||||||
$$= $1;
|
|
||||||
delete list;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
List<Item> *list= Select->expr_list.pop();
|
|
||||||
if (list->elements)
|
|
||||||
{
|
{
|
||||||
list->push_front($1);
|
/* X OR Y */
|
||||||
$$= new Item_cond_and(*list);
|
$$ = new (YYTHD->mem_root) Item_cond_or($1, $3);
|
||||||
/* optimize construction of logical AND to reduce
|
}
|
||||||
amount of objects for complex expressions */
|
}
|
||||||
|
| 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
|
||||||
|
{
|
||||||
|
/* See comments in rule expr: expr or expr */
|
||||||
|
Item_cond_and *item1;
|
||||||
|
Item_cond_and *item3;
|
||||||
|
if (is_cond_and($1))
|
||||||
|
{
|
||||||
|
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
|
else
|
||||||
$$= $1;
|
{
|
||||||
delete list;
|
/* X AND Y */
|
||||||
|
$$ = new (YYTHD->mem_root) Item_cond_and($1, $3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
;
|
| NOT_SYM expr %prec NOT_SYM
|
||||||
|
{ $$= negate_expression(YYTHD, $2); }
|
||||||
bool_and_expr:
|
| bool_pri IS TRUE_SYM %prec IS
|
||||||
/* 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
|
|
||||||
{ $$= new (YYTHD->mem_root) Item_func_istrue($1); }
|
{ $$= 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); }
|
{ $$= 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); }
|
{ $$= 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); }
|
{ $$= new (YYTHD->mem_root) Item_func_isnotfalse($1); }
|
||||||
| bool_pri IS UNKNOWN_SYM { $$= new Item_func_isnull($1); }
|
| bool_pri IS UNKNOWN_SYM %prec IS
|
||||||
| bool_pri IS not UNKNOWN_SYM { $$= new Item_func_isnotnull($1); }
|
{ $$= new Item_func_isnull($1); }
|
||||||
|
| bool_pri IS not UNKNOWN_SYM %prec IS
|
||||||
|
{ $$= new Item_func_isnotnull($1); }
|
||||||
| bool_pri
|
| bool_pri
|
||||||
;
|
;
|
||||||
|
|
||||||
bool_pri:
|
bool_pri:
|
||||||
bool_pri IS NULL_SYM { $$= new Item_func_isnull($1); }
|
bool_pri IS NULL_SYM %prec IS
|
||||||
| bool_pri IS not NULL_SYM { $$= new Item_func_isnotnull($1); }
|
{ $$= new Item_func_isnull($1); }
|
||||||
| bool_pri EQUAL_SYM predicate { $$= new Item_func_equal($1,$3); }
|
| 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
|
| bool_pri comp_op predicate %prec EQ
|
||||||
{ $$= (*$2)(0)->create($1,$3); }
|
{ $$= (*$2)(0)->create($1,$3); }
|
||||||
| bool_pri comp_op all_or_any '(' subselect ')' %prec EQ
|
| bool_pri comp_op all_or_any '(' subselect ')' %prec EQ
|
||||||
{ $$= all_any_subquery_creator($1, $2, $3, $5); }
|
{ $$= all_any_subquery_creator($1, $2, $3, $5); }
|
||||||
| predicate
|
| predicate ;
|
||||||
;
|
;
|
||||||
|
|
||||||
predicate:
|
predicate:
|
||||||
@ -6700,44 +6751,34 @@ predicate:
|
|||||||
;
|
;
|
||||||
|
|
||||||
bit_expr:
|
bit_expr:
|
||||||
bit_expr '|' bit_term { $$= new Item_func_bit_or($1,$3); }
|
bit_expr '|' bit_expr %prec '|'
|
||||||
| bit_term
|
{ $$= new Item_func_bit_or($1,$3); }
|
||||||
;
|
| bit_expr '&' bit_expr %prec '&'
|
||||||
|
{ $$= new Item_func_bit_and($1,$3); }
|
||||||
bit_term:
|
| bit_expr SHIFT_LEFT bit_expr %prec SHIFT_LEFT
|
||||||
bit_term '&' bit_factor { $$= new Item_func_bit_and($1,$3); }
|
|
||||||
| bit_factor
|
|
||||||
;
|
|
||||||
|
|
||||||
bit_factor:
|
|
||||||
bit_factor SHIFT_LEFT value_expr
|
|
||||||
{ $$= new Item_func_shift_left($1,$3); }
|
{ $$= 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); }
|
{ $$= new Item_func_shift_right($1,$3); }
|
||||||
| value_expr
|
| bit_expr '+' bit_expr %prec '+'
|
||||||
;
|
{ $$= new Item_func_plus($1,$3); }
|
||||||
|
| bit_expr '-' bit_expr %prec '-'
|
||||||
value_expr:
|
{ $$= new Item_func_minus($1,$3); }
|
||||||
value_expr '+' term { $$= new Item_func_plus($1,$3); }
|
| bit_expr '+' interval_expr interval %prec '+'
|
||||||
| value_expr '-' term { $$= new Item_func_minus($1,$3); }
|
|
||||||
| value_expr '+' interval_expr interval
|
|
||||||
{ $$= new Item_date_add_interval($1,$3,$4,0); }
|
{ $$= 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); }
|
{ $$= new Item_date_add_interval($1,$3,$4,1); }
|
||||||
| term
|
| bit_expr '*' bit_expr %prec '*'
|
||||||
;
|
{ $$= new Item_func_mul($1,$3); }
|
||||||
|
| bit_expr '/' bit_expr %prec '/'
|
||||||
term:
|
{ $$= new Item_func_div($1,$3); }
|
||||||
term '*' factor { $$= new Item_func_mul($1,$3); }
|
| bit_expr '%' bit_expr %prec '%'
|
||||||
| term '/' factor { $$= new Item_func_div($1,$3); }
|
{ $$= new Item_func_mod($1,$3); }
|
||||||
| term '%' factor { $$= new Item_func_mod($1,$3); }
|
| bit_expr DIV_SYM bit_expr %prec DIV_SYM
|
||||||
| term DIV_SYM factor { $$= new Item_func_int_div($1,$3); }
|
{ $$= new Item_func_int_div($1,$3); }
|
||||||
| term MOD_SYM factor { $$= new Item_func_mod($1,$3); }
|
| bit_expr MOD_SYM bit_expr %prec MOD_SYM
|
||||||
| factor
|
{ $$= new Item_func_mod($1,$3); }
|
||||||
;
|
| bit_expr '^' bit_expr
|
||||||
|
{ $$= new Item_func_bit_xor($1,$3); }
|
||||||
factor:
|
|
||||||
factor '^' simple_expr { $$= new Item_func_bit_xor($1,$3); }
|
|
||||||
| simple_expr
|
| simple_expr
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -6776,7 +6817,8 @@ all_or_any:
|
|||||||
;
|
;
|
||||||
|
|
||||||
interval_expr:
|
interval_expr:
|
||||||
INTERVAL_SYM expr { $$=$2; }
|
INTERVAL_SYM expr %prec INTERVAL_SYM
|
||||||
|
{ $$=$2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
simple_expr:
|
simple_expr:
|
||||||
@ -6799,7 +6841,7 @@ simple_expr:
|
|||||||
| sum_expr
|
| sum_expr
|
||||||
| simple_expr OR_OR_SYM simple_expr
|
| simple_expr OR_OR_SYM simple_expr
|
||||||
{ $$= new (YYTHD->mem_root) Item_func_concat($1, $3); }
|
{ $$= new (YYTHD->mem_root) Item_func_concat($1, $3); }
|
||||||
| '+' simple_expr %prec NEG { $$= $2; }
|
| '+' simple_expr %prec NEG { $$= $2; }
|
||||||
| '-' simple_expr %prec NEG
|
| '-' simple_expr %prec NEG
|
||||||
{ $$= new (YYTHD->mem_root) Item_func_neg($2); }
|
{ $$= new (YYTHD->mem_root) Item_func_neg($2); }
|
||||||
| '~' simple_expr %prec NEG
|
| '~' simple_expr %prec NEG
|
||||||
@ -7210,7 +7252,7 @@ function_call_generic:
|
|||||||
$<udf>$= udf;
|
$<udf>$= udf;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
udf_expr_list ')'
|
opt_udf_expr_list ')'
|
||||||
{
|
{
|
||||||
THD *thd= YYTHD;
|
THD *thd= YYTHD;
|
||||||
Create_func *builder;
|
Create_func *builder;
|
||||||
@ -7307,27 +7349,23 @@ opt_query_expansion:
|
|||||||
| WITH QUERY_SYM EXPANSION_SYM { $$= FT_EXPAND; }
|
| WITH QUERY_SYM EXPANSION_SYM { $$= FT_EXPAND; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
opt_udf_expr_list:
|
||||||
|
/* empty */ { $$= NULL; }
|
||||||
|
| udf_expr_list { $$= $1; }
|
||||||
|
;
|
||||||
|
|
||||||
udf_expr_list:
|
udf_expr_list:
|
||||||
/* empty */ { $$= NULL; }
|
udf_expr
|
||||||
| udf_expr_list2 { $$= $1;}
|
{
|
||||||
;
|
$$= new (YYTHD->mem_root) List<Item>;
|
||||||
|
$$->push_back($1);
|
||||||
udf_expr_list2:
|
}
|
||||||
{ Select->expr_list.push_front(new List<Item>); }
|
| udf_expr_list ',' udf_expr
|
||||||
udf_expr_list3
|
{
|
||||||
{ $$= Select->expr_list.pop(); }
|
$1->push_back($3);
|
||||||
;
|
$$= $1;
|
||||||
|
}
|
||||||
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:
|
udf_expr:
|
||||||
remember_name expr remember_end select_alias
|
remember_name expr remember_end select_alias
|
||||||
@ -7525,13 +7563,17 @@ opt_expr_list:
|
|||||||
;
|
;
|
||||||
|
|
||||||
expr_list:
|
expr_list:
|
||||||
{ Select->expr_list.push_front(new List<Item>); }
|
expr
|
||||||
expr_list2
|
{
|
||||||
{ $$= Select->expr_list.pop(); };
|
$$= new (YYTHD->mem_root) List<Item>;
|
||||||
|
$$->push_back($1);
|
||||||
expr_list2:
|
}
|
||||||
expr { Select->expr_list.head()->push_back($1); }
|
| expr_list ',' expr
|
||||||
| expr_list2 ',' expr { Select->expr_list.head()->push_back($3); };
|
{
|
||||||
|
$1->push_back($3);
|
||||||
|
$$= $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
ident_list_arg:
|
ident_list_arg:
|
||||||
ident_list { $$= $1; }
|
ident_list { $$= $1; }
|
||||||
@ -7539,13 +7581,17 @@ ident_list_arg:
|
|||||||
;
|
;
|
||||||
|
|
||||||
ident_list:
|
ident_list:
|
||||||
{ Select->expr_list.push_front(new List<Item>); }
|
simple_ident
|
||||||
ident_list2
|
{
|
||||||
{ $$= Select->expr_list.pop(); };
|
$$= new (YYTHD->mem_root) List<Item>;
|
||||||
|
$$->push_back($1);
|
||||||
ident_list2:
|
}
|
||||||
simple_ident { Select->expr_list.head()->push_back($1); }
|
| ident_list ',' simple_ident
|
||||||
| ident_list2 ',' simple_ident { Select->expr_list.head()->push_back($3); };
|
{
|
||||||
|
$1->push_back($3);
|
||||||
|
$$= $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
opt_expr:
|
opt_expr:
|
||||||
/* empty */ { $$= NULL; }
|
/* empty */ { $$= NULL; }
|
||||||
|
@ -3169,7 +3169,7 @@ int ha_federated::external_lock(THD *thd, int lock_type)
|
|||||||
#ifdef XXX_SUPERCEDED_BY_WL2952
|
#ifdef XXX_SUPERCEDED_BY_WL2952
|
||||||
if (lock_type != F_UNLCK)
|
if (lock_type != F_UNLCK)
|
||||||
{
|
{
|
||||||
ha_federated *trx= (ha_federated *)thd->ha_data[ht->slot];
|
ha_federated *trx= (ha_federated *)thd_get_ha_data(thd, ht);
|
||||||
|
|
||||||
DBUG_PRINT("info",("federated not lock F_UNLCK"));
|
DBUG_PRINT("info",("federated not lock F_UNLCK"));
|
||||||
if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
|
if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
|
||||||
@ -3200,7 +3200,7 @@ int ha_federated::external_lock(THD *thd, int lock_type)
|
|||||||
DBUG_PRINT("info", ("error setting autocommit FALSE: %d", error));
|
DBUG_PRINT("info", ("error setting autocommit FALSE: %d", error));
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
thd->ha_data[ht->slot]= this;
|
thd_set_ha_data(thd, ht, this);
|
||||||
trans_register_ha(thd, TRUE, ht);
|
trans_register_ha(thd, TRUE, ht);
|
||||||
/*
|
/*
|
||||||
Send a lock table to the remote end.
|
Send a lock table to the remote end.
|
||||||
@ -3230,7 +3230,7 @@ int ha_federated::external_lock(THD *thd, int lock_type)
|
|||||||
static int federated_commit(handlerton *hton, THD *thd, bool all)
|
static int federated_commit(handlerton *hton, THD *thd, bool all)
|
||||||
{
|
{
|
||||||
int return_val= 0;
|
int return_val= 0;
|
||||||
ha_federated *trx= (ha_federated *)thd->ha_data[hton->slot];
|
ha_federated *trx= (ha_federated *) thd_get_ha_data(thd, hton);
|
||||||
DBUG_ENTER("federated_commit");
|
DBUG_ENTER("federated_commit");
|
||||||
|
|
||||||
if (all)
|
if (all)
|
||||||
@ -3245,7 +3245,7 @@ static int federated_commit(handlerton *hton, THD *thd, bool all)
|
|||||||
if (error && !return_val)
|
if (error && !return_val)
|
||||||
return_val= error;
|
return_val= error;
|
||||||
}
|
}
|
||||||
thd->ha_data[hton->slot]= NULL;
|
thd_set_ha_data(thd, hton, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_PRINT("info", ("error val: %d", return_val));
|
DBUG_PRINT("info", ("error val: %d", return_val));
|
||||||
@ -3256,7 +3256,7 @@ static int federated_commit(handlerton *hton, THD *thd, bool all)
|
|||||||
static int federated_rollback(handlerton *hton, THD *thd, bool all)
|
static int federated_rollback(handlerton *hton, THD *thd, bool all)
|
||||||
{
|
{
|
||||||
int return_val= 0;
|
int return_val= 0;
|
||||||
ha_federated *trx= (ha_federated *)thd->ha_data[hton->slot];
|
ha_federated *trx= (ha_federated *)thd_get_ha_data(thd, hton);
|
||||||
DBUG_ENTER("federated_rollback");
|
DBUG_ENTER("federated_rollback");
|
||||||
|
|
||||||
if (all)
|
if (all)
|
||||||
@ -3271,7 +3271,7 @@ static int federated_rollback(handlerton *hton, THD *thd, bool all)
|
|||||||
if (error && !return_val)
|
if (error && !return_val)
|
||||||
return_val= error;
|
return_val= error;
|
||||||
}
|
}
|
||||||
thd->ha_data[hton->slot]= NULL;
|
thd_set_ha_data(thd, hton, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_PRINT("info", ("error val: %d", return_val));
|
DBUG_PRINT("info", ("error val: %d", return_val));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user