Merge from mysql-5.5-runtime to mysql-5.5-bugteam.
This commit is contained in:
commit
fbfbc7ee9b
@ -220,7 +220,6 @@
|
|||||||
#cmakedefine HAVE_PTHREAD_KEY_DELETE 1
|
#cmakedefine HAVE_PTHREAD_KEY_DELETE 1
|
||||||
#cmakedefine HAVE_PTHREAD_KILL 1
|
#cmakedefine HAVE_PTHREAD_KILL 1
|
||||||
#cmakedefine HAVE_PTHREAD_RWLOCK_RDLOCK 1
|
#cmakedefine HAVE_PTHREAD_RWLOCK_RDLOCK 1
|
||||||
#cmakedefine HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP 1
|
|
||||||
#cmakedefine HAVE_PTHREAD_SETPRIO_NP 1
|
#cmakedefine HAVE_PTHREAD_SETPRIO_NP 1
|
||||||
#cmakedefine HAVE_PTHREAD_SETSCHEDPARAM 1
|
#cmakedefine HAVE_PTHREAD_SETSCHEDPARAM 1
|
||||||
#cmakedefine HAVE_PTHREAD_SIGMASK 1
|
#cmakedefine HAVE_PTHREAD_SIGMASK 1
|
||||||
|
@ -346,7 +346,6 @@ CHECK_FUNCTION_EXISTS (pthread_condattr_setclock HAVE_PTHREAD_CONDATTR_SETCLOCK)
|
|||||||
CHECK_FUNCTION_EXISTS (pthread_init HAVE_PTHREAD_INIT)
|
CHECK_FUNCTION_EXISTS (pthread_init HAVE_PTHREAD_INIT)
|
||||||
CHECK_FUNCTION_EXISTS (pthread_key_delete HAVE_PTHREAD_KEY_DELETE)
|
CHECK_FUNCTION_EXISTS (pthread_key_delete HAVE_PTHREAD_KEY_DELETE)
|
||||||
CHECK_FUNCTION_EXISTS (pthread_rwlock_rdlock HAVE_PTHREAD_RWLOCK_RDLOCK)
|
CHECK_FUNCTION_EXISTS (pthread_rwlock_rdlock HAVE_PTHREAD_RWLOCK_RDLOCK)
|
||||||
CHECK_FUNCTION_EXISTS (pthread_rwlockattr_setkind_np HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP)
|
|
||||||
CHECK_FUNCTION_EXISTS (pthread_sigmask HAVE_PTHREAD_SIGMASK)
|
CHECK_FUNCTION_EXISTS (pthread_sigmask HAVE_PTHREAD_SIGMASK)
|
||||||
CHECK_FUNCTION_EXISTS (pthread_threadmask HAVE_PTHREAD_THREADMASK)
|
CHECK_FUNCTION_EXISTS (pthread_threadmask HAVE_PTHREAD_THREADMASK)
|
||||||
CHECK_FUNCTION_EXISTS (pthread_yield_np HAVE_PTHREAD_YIELD_NP)
|
CHECK_FUNCTION_EXISTS (pthread_yield_np HAVE_PTHREAD_YIELD_NP)
|
||||||
|
@ -2169,7 +2169,7 @@ AC_CHECK_FUNCS(alarm bfill bmove bsearch bzero \
|
|||||||
mkstemp mlockall perror poll pread pthread_attr_create mmap mmap64 getpagesize \
|
mkstemp mlockall perror poll pread pthread_attr_create mmap mmap64 getpagesize \
|
||||||
pthread_attr_getstacksize pthread_attr_setstacksize pthread_condattr_create \
|
pthread_attr_getstacksize pthread_attr_setstacksize pthread_condattr_create \
|
||||||
pthread_getsequence_np pthread_key_delete pthread_rwlock_rdlock \
|
pthread_getsequence_np pthread_key_delete pthread_rwlock_rdlock \
|
||||||
pthread_rwlockattr_setkind_np pthread_sigmask \
|
pthread_sigmask \
|
||||||
readlink realpath rename rint rwlock_init setupterm \
|
readlink realpath rename rint rwlock_init setupterm \
|
||||||
shmget shmat shmdt shmctl sigaction sigemptyset sigaddset \
|
shmget shmat shmdt shmctl sigaction sigemptyset sigaddset \
|
||||||
sighold sigset sigthreadmask port_create sleep thr_yield \
|
sighold sigset sigthreadmask port_create sleep thr_yield \
|
||||||
|
10
dbug/dbug.c
10
dbug/dbug.c
@ -515,11 +515,16 @@ int DbugParse(CODE_STATE *cs, const char *control)
|
|||||||
stack->maxdepth= stack->next->maxdepth;
|
stack->maxdepth= stack->next->maxdepth;
|
||||||
stack->sub_level= stack->next->sub_level;
|
stack->sub_level= stack->next->sub_level;
|
||||||
strcpy(stack->name, stack->next->name);
|
strcpy(stack->name, stack->next->name);
|
||||||
stack->out_file= stack->next->out_file;
|
|
||||||
stack->prof_file= stack->next->prof_file;
|
stack->prof_file= stack->next->prof_file;
|
||||||
if (stack->next == &init_settings)
|
if (stack->next == &init_settings)
|
||||||
{
|
{
|
||||||
/* never share with the global parent - it can change under your feet */
|
/*
|
||||||
|
Never share with the global parent - it can change under your feet.
|
||||||
|
|
||||||
|
Reset out_file to stderr to prevent sharing of trace files between
|
||||||
|
global and session settings.
|
||||||
|
*/
|
||||||
|
stack->out_file= stderr;
|
||||||
stack->functions= ListCopy(init_settings.functions);
|
stack->functions= ListCopy(init_settings.functions);
|
||||||
stack->p_functions= ListCopy(init_settings.p_functions);
|
stack->p_functions= ListCopy(init_settings.p_functions);
|
||||||
stack->keywords= ListCopy(init_settings.keywords);
|
stack->keywords= ListCopy(init_settings.keywords);
|
||||||
@ -527,6 +532,7 @@ int DbugParse(CODE_STATE *cs, const char *control)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
stack->out_file= stack->next->out_file;
|
||||||
stack->functions= stack->next->functions;
|
stack->functions= stack->next->functions;
|
||||||
stack->p_functions= stack->next->p_functions;
|
stack->p_functions= stack->next->p_functions;
|
||||||
stack->keywords= stack->next->keywords;
|
stack->keywords= stack->next->keywords;
|
||||||
|
@ -594,7 +594,7 @@ int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp);
|
|||||||
/* Use our own version of read/write locks */
|
/* Use our own version of read/write locks */
|
||||||
#define NEED_MY_RW_LOCK 1
|
#define NEED_MY_RW_LOCK 1
|
||||||
#define rw_lock_t my_rw_lock_t
|
#define rw_lock_t my_rw_lock_t
|
||||||
#define my_rwlock_init(A,B) my_rw_init((A), 0)
|
#define my_rwlock_init(A,B) my_rw_init((A))
|
||||||
#define rw_rdlock(A) my_rw_rdlock((A))
|
#define rw_rdlock(A) my_rw_rdlock((A))
|
||||||
#define rw_wrlock(A) my_rw_wrlock((A))
|
#define rw_wrlock(A) my_rw_wrlock((A))
|
||||||
#define rw_tryrdlock(A) my_rw_tryrdlock((A))
|
#define rw_tryrdlock(A) my_rw_tryrdlock((A))
|
||||||
@ -606,49 +606,82 @@ int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp);
|
|||||||
#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */
|
#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Portable read-write locks which prefer readers.
|
Portable implementation of special type of read-write locks.
|
||||||
|
|
||||||
Required by some algorithms in order to provide correctness.
|
These locks have two properties which are unusual for rwlocks:
|
||||||
|
1) They "prefer readers" in the sense that they do not allow
|
||||||
|
situations in which rwlock is rd-locked and there is a
|
||||||
|
pending rd-lock which is blocked (e.g. due to pending
|
||||||
|
request for wr-lock).
|
||||||
|
This is a stronger guarantee than one which is provided for
|
||||||
|
PTHREAD_RWLOCK_PREFER_READER_NP rwlocks in Linux.
|
||||||
|
MDL subsystem deadlock detector relies on this property for
|
||||||
|
its correctness.
|
||||||
|
2) They are optimized for uncontended wr-lock/unlock case.
|
||||||
|
This is scenario in which they are most oftenly used
|
||||||
|
within MDL subsystem. Optimizing for it gives significant
|
||||||
|
performance improvements in some of tests involving many
|
||||||
|
connections.
|
||||||
|
|
||||||
|
Another important requirement imposed on this type of rwlock
|
||||||
|
by the MDL subsystem is that it should be OK to destroy rwlock
|
||||||
|
object which is in unlocked state even though some threads might
|
||||||
|
have not yet fully left unlock operation for it (of course there
|
||||||
|
is an external guarantee that no thread will try to lock rwlock
|
||||||
|
which is destroyed).
|
||||||
|
Putting it another way the unlock operation should not access
|
||||||
|
rwlock data after changing its state to unlocked.
|
||||||
|
|
||||||
|
TODO/FIXME: We should consider alleviating this requirement as
|
||||||
|
it blocks us from doing certain performance optimizations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP)
|
typedef struct st_rw_pr_lock_t {
|
||||||
/*
|
/**
|
||||||
On systems which have a way to specify that readers should
|
Lock which protects the structure.
|
||||||
be preferred through attribute mechanism (e.g. Linux) we use
|
Also held for the duration of wr-lock.
|
||||||
system implementation of read/write locks.
|
*/
|
||||||
*/
|
pthread_mutex_t lock;
|
||||||
#define rw_pr_lock_t pthread_rwlock_t
|
/**
|
||||||
|
Condition variable which is used to wake-up
|
||||||
|
writers waiting for readers to go away.
|
||||||
|
*/
|
||||||
|
pthread_cond_t no_active_readers;
|
||||||
|
/** Number of active readers. */
|
||||||
|
uint active_readers;
|
||||||
|
/** Number of writers waiting for readers to go away. */
|
||||||
|
uint writers_waiting_readers;
|
||||||
|
/** Indicates whether there is an active writer. */
|
||||||
|
my_bool active_writer;
|
||||||
|
#ifdef SAFE_MUTEX
|
||||||
|
/** Thread holding wr-lock (for debug purposes only). */
|
||||||
|
pthread_t writer_thread;
|
||||||
|
#endif
|
||||||
|
} rw_pr_lock_t;
|
||||||
|
|
||||||
extern int rw_pr_init(rw_pr_lock_t *);
|
extern int rw_pr_init(rw_pr_lock_t *);
|
||||||
#define rw_pr_rdlock(A) pthread_rwlock_rdlock(A)
|
extern int rw_pr_rdlock(rw_pr_lock_t *);
|
||||||
#define rw_pr_wrlock(A) pthread_rwlock_wrlock(A)
|
extern int rw_pr_wrlock(rw_pr_lock_t *);
|
||||||
#define rw_pr_tryrdlock(A) pthread_rwlock_tryrdlock(A)
|
extern int rw_pr_unlock(rw_pr_lock_t *);
|
||||||
#define rw_pr_trywrlock(A) pthread_rwlock_trywrlock(A)
|
extern int rw_pr_destroy(rw_pr_lock_t *);
|
||||||
#define rw_pr_unlock(A) pthread_rwlock_unlock(A)
|
#ifdef SAFE_MUTEX
|
||||||
#define rw_pr_destroy(A) pthread_rwlock_destroy(A)
|
#define rw_pr_lock_assert_write_owner(A) \
|
||||||
|
DBUG_ASSERT((A)->active_writer && pthread_equal(pthread_self(), \
|
||||||
|
(A)->writer_thread))
|
||||||
|
#define rw_pr_lock_assert_not_write_owner(A) \
|
||||||
|
DBUG_ASSERT(! (A)->active_writer || ! pthread_equal(pthread_self(), \
|
||||||
|
(A)->writer_thread))
|
||||||
|
#else
|
||||||
#define rw_pr_lock_assert_write_owner(A)
|
#define rw_pr_lock_assert_write_owner(A)
|
||||||
#define rw_pr_lock_assert_not_write_owner(A)
|
#define rw_pr_lock_assert_not_write_owner(A)
|
||||||
#else
|
#endif /* SAFE_MUTEX */
|
||||||
/* Otherwise we have to use our own implementation of read/write locks. */
|
|
||||||
#define NEED_MY_RW_LOCK 1
|
|
||||||
struct st_my_rw_lock_t;
|
|
||||||
#define rw_pr_lock_t my_rw_lock_t
|
|
||||||
extern int rw_pr_init(struct st_my_rw_lock_t *);
|
|
||||||
#define rw_pr_rdlock(A) my_rw_rdlock((A))
|
|
||||||
#define rw_pr_wrlock(A) my_rw_wrlock((A))
|
|
||||||
#define rw_pr_tryrdlock(A) my_rw_tryrdlock((A))
|
|
||||||
#define rw_pr_trywrlock(A) my_rw_trywrlock((A))
|
|
||||||
#define rw_pr_unlock(A) my_rw_unlock((A))
|
|
||||||
#define rw_pr_destroy(A) my_rw_destroy((A))
|
|
||||||
#define rw_pr_lock_assert_write_owner(A) my_rw_lock_assert_write_owner((A))
|
|
||||||
#define rw_pr_lock_assert_not_write_owner(A) my_rw_lock_assert_not_write_owner((A))
|
|
||||||
#endif /* defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP) */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef NEED_MY_RW_LOCK
|
#ifdef NEED_MY_RW_LOCK
|
||||||
/*
|
/*
|
||||||
On systems which don't support native read/write locks, or don't support
|
On systems which don't support native read/write locks we have
|
||||||
read/write locks which prefer readers we have to use own implementation.
|
to use own implementation.
|
||||||
*/
|
*/
|
||||||
typedef struct st_my_rw_lock_t {
|
typedef struct st_my_rw_lock_t {
|
||||||
pthread_mutex_t lock; /* lock for structure */
|
pthread_mutex_t lock; /* lock for structure */
|
||||||
@ -656,13 +689,12 @@ typedef struct st_my_rw_lock_t {
|
|||||||
pthread_cond_t writers; /* waiting writers */
|
pthread_cond_t writers; /* waiting writers */
|
||||||
int state; /* -1:writer,0:free,>0:readers */
|
int state; /* -1:writer,0:free,>0:readers */
|
||||||
int waiters; /* number of waiting writers */
|
int waiters; /* number of waiting writers */
|
||||||
my_bool prefer_readers;
|
|
||||||
#ifdef SAFE_MUTEX
|
#ifdef SAFE_MUTEX
|
||||||
pthread_t write_thread;
|
pthread_t write_thread;
|
||||||
#endif
|
#endif
|
||||||
} my_rw_lock_t;
|
} my_rw_lock_t;
|
||||||
|
|
||||||
extern int my_rw_init(my_rw_lock_t *, my_bool *);
|
extern int my_rw_init(my_rw_lock_t *);
|
||||||
extern int my_rw_destroy(my_rw_lock_t *);
|
extern int my_rw_destroy(my_rw_lock_t *);
|
||||||
extern int my_rw_rdlock(my_rw_lock_t *);
|
extern int my_rw_rdlock(my_rw_lock_t *);
|
||||||
extern int my_rw_wrlock(my_rw_lock_t *);
|
extern int my_rw_wrlock(my_rw_lock_t *);
|
||||||
|
@ -141,9 +141,7 @@ typedef struct st_mysql_rwlock mysql_rwlock_t;
|
|||||||
@c mysql_prlock_t is a drop-in replacement for @c rw_pr_lock_t.
|
@c mysql_prlock_t is a drop-in replacement for @c rw_pr_lock_t.
|
||||||
@sa mysql_prlock_init
|
@sa mysql_prlock_init
|
||||||
@sa mysql_prlock_rdlock
|
@sa mysql_prlock_rdlock
|
||||||
@sa mysql_prlock_tryrdlock
|
|
||||||
@sa mysql_prlock_wrlock
|
@sa mysql_prlock_wrlock
|
||||||
@sa mysql_prlock_trywrlock
|
|
||||||
@sa mysql_prlock_unlock
|
@sa mysql_prlock_unlock
|
||||||
@sa mysql_prlock_destroy
|
@sa mysql_prlock_destroy
|
||||||
*/
|
*/
|
||||||
@ -420,20 +418,6 @@ typedef struct st_mysql_cond mysql_cond_t;
|
|||||||
inline_mysql_rwlock_tryrdlock(RW)
|
inline_mysql_rwlock_tryrdlock(RW)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
@def mysql_prlock_tryrdlock(RW)
|
|
||||||
Instrumented rw_pr_tryrdlock.
|
|
||||||
@c mysql_prlock_tryrdlock is a drop-in replacement
|
|
||||||
for @c rw_pr_tryrdlock.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
|
||||||
#define mysql_prlock_tryrdlock(RW) \
|
|
||||||
inline_mysql_prlock_tryrdlock(RW, __FILE__, __LINE__)
|
|
||||||
#else
|
|
||||||
#define mysql_prlock_tryrdlock(RW) \
|
|
||||||
inline_mysql_prlock_tryrdlock(RW)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@def mysql_rwlock_trywrlock(RW)
|
@def mysql_rwlock_trywrlock(RW)
|
||||||
Instrumented rwlock_trywrlock.
|
Instrumented rwlock_trywrlock.
|
||||||
@ -448,20 +432,6 @@ typedef struct st_mysql_cond mysql_cond_t;
|
|||||||
inline_mysql_rwlock_trywrlock(RW)
|
inline_mysql_rwlock_trywrlock(RW)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
@def mysql_prlock_trywrlock(RW)
|
|
||||||
Instrumented rw_pr_trywrlock.
|
|
||||||
@c mysql_prlock_trywrlock is a drop-in replacement
|
|
||||||
for @c rw_pr_trywrlock.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
|
||||||
#define mysql_prlock_trywrlock(RW) \
|
|
||||||
inline_mysql_prlock_trywrlock(RW, __FILE__, __LINE__)
|
|
||||||
#else
|
|
||||||
#define mysql_prlock_trywrlock(RW) \
|
|
||||||
inline_mysql_prlock_trywrlock(RW)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@def mysql_rwlock_unlock(RW)
|
@def mysql_rwlock_unlock(RW)
|
||||||
Instrumented rwlock_unlock.
|
Instrumented rwlock_unlock.
|
||||||
@ -905,35 +875,6 @@ static inline int inline_mysql_rwlock_tryrdlock(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_MYSQL_PRLOCK_H
|
|
||||||
static inline int inline_mysql_prlock_tryrdlock(
|
|
||||||
mysql_prlock_t *that
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
|
||||||
, const char *src_file, uint src_line
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
|
||||||
struct PSI_rwlock_locker *locker= NULL;
|
|
||||||
PSI_rwlock_locker_state state;
|
|
||||||
if (likely(PSI_server && that->m_psi))
|
|
||||||
{
|
|
||||||
locker= PSI_server->get_thread_rwlock_locker(&state, that->m_psi,
|
|
||||||
PSI_RWLOCK_TRYREADLOCK);
|
|
||||||
if (likely(locker != NULL))
|
|
||||||
PSI_server->start_rwlock_rdwait(locker, src_file, src_line);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
result= rw_pr_tryrdlock(&that->m_prlock);
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
|
||||||
if (likely(locker != NULL))
|
|
||||||
PSI_server->end_rwlock_rdwait(locker, result);
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline int inline_mysql_rwlock_trywrlock(
|
static inline int inline_mysql_rwlock_trywrlock(
|
||||||
mysql_rwlock_t *that
|
mysql_rwlock_t *that
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
#ifdef HAVE_PSI_INTERFACE
|
||||||
@ -961,35 +902,6 @@ static inline int inline_mysql_rwlock_trywrlock(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_MYSQL_PRLOCK_H
|
|
||||||
static inline int inline_mysql_prlock_trywrlock(
|
|
||||||
mysql_prlock_t *that
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
|
||||||
, const char *src_file, uint src_line
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
|
||||||
struct PSI_rwlock_locker *locker= NULL;
|
|
||||||
PSI_rwlock_locker_state state;
|
|
||||||
if (likely(PSI_server && that->m_psi))
|
|
||||||
{
|
|
||||||
locker= PSI_server->get_thread_rwlock_locker(&state, that->m_psi,
|
|
||||||
PSI_RWLOCK_TRYWRITELOCK);
|
|
||||||
if (likely(locker != NULL))
|
|
||||||
PSI_server->start_rwlock_wrwait(locker, src_file, src_line);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
result= rw_pr_trywrlock(&that->m_prlock);
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
|
||||||
if (likely(locker != NULL))
|
|
||||||
PSI_server->end_rwlock_wrwait(locker, result);
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline int inline_mysql_rwlock_unlock(
|
static inline int inline_mysql_rwlock_unlock(
|
||||||
mysql_rwlock_t *that)
|
mysql_rwlock_t *that)
|
||||||
{
|
{
|
||||||
|
@ -1809,9 +1809,32 @@ CREATE TABLE t1(a INT);
|
|||||||
INSERT INTO t1 VALUES (1);
|
INSERT INTO t1 VALUES (1);
|
||||||
HANDLER t1 OPEN;
|
HANDLER t1 OPEN;
|
||||||
# This used to cause the assert
|
# This used to cause the assert
|
||||||
--error ER_NO_SUCH_TABLE
|
--error ER_NOT_SUPPORTED_YET
|
||||||
HANDLER t1 READ FIRST WHERE f1() = 1;
|
HANDLER t1 READ FIRST WHERE f1() = 1;
|
||||||
HANDLER t1 CLOSE;
|
HANDLER t1 CLOSE;
|
||||||
|
|
||||||
DROP FUNCTION f1;
|
DROP FUNCTION f1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#54920 Stored functions are allowed in HANDLER statements,
|
||||||
|
--echo # but broken.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP FUNCTION IF EXISTS f1;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
INSERT INTO t1 VALUES (1), (2);
|
||||||
|
CREATE FUNCTION f1() RETURNS INT RETURN 1;
|
||||||
|
HANDLER t1 OPEN;
|
||||||
|
|
||||||
|
--error ER_NOT_SUPPORTED_YET
|
||||||
|
HANDLER t1 READ FIRST WHERE f1() = 1;
|
||||||
|
|
||||||
|
HANDLER t1 CLOSE;
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -23,3 +23,19 @@ REPAIR TABLE t1;
|
|||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 repair status OK
|
test.t1 repair status OK
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# Bug#56422 CHECK TABLE run when the table is locked reports corruption
|
||||||
|
# along with timeout
|
||||||
|
#
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
CREATE TABLE t1(a INT);
|
||||||
|
LOCK TABLE t1 WRITE;
|
||||||
|
# Connection con1
|
||||||
|
SET lock_wait_timeout= 1;
|
||||||
|
CHECK TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check Error Lock wait timeout exceeded; try restarting transaction
|
||||||
|
test.t1 check status Operation failed
|
||||||
|
# Connection default
|
||||||
|
UNLOCK TABLES;
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -422,3 +422,31 @@ UNLOCK TABLES;
|
|||||||
# Connection con1
|
# Connection con1
|
||||||
# Connection default
|
# Connection default
|
||||||
DROP TABLE t1, t2, t3;
|
DROP TABLE t1, t2, t3;
|
||||||
|
#
|
||||||
|
# Test for bug #56251 "Deadlock with INSERT DELAYED and MERGE tables".
|
||||||
|
#
|
||||||
|
drop table if exists t1, t2, tm;
|
||||||
|
create table t1(a int);
|
||||||
|
create table t2(a int);
|
||||||
|
create table tm(a int) engine=merge union=(t1, t2);
|
||||||
|
begin;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
# Connection 'con1'.
|
||||||
|
# Sending:
|
||||||
|
alter table t1 comment 'test';
|
||||||
|
# Connection 'default'.
|
||||||
|
# Wait until ALTER TABLE blocks and starts waiting
|
||||||
|
# for connection 'default'. It should wait with a
|
||||||
|
# pending SNW lock on 't1'.
|
||||||
|
# Attempt to perform delayed insert into 'tm' should not lead
|
||||||
|
# to a deadlock. Instead error ER_DELAYED_NOT_SUPPORTED should
|
||||||
|
# be emitted.
|
||||||
|
insert delayed into tm values (1);
|
||||||
|
ERROR HY000: DELAYED option not supported for table 'tm'
|
||||||
|
# Unblock ALTER TABLE.
|
||||||
|
commit;
|
||||||
|
# Connection 'con1'.
|
||||||
|
# Reaping ALTER TABLE:
|
||||||
|
# Connection 'default'.
|
||||||
|
drop tables tm, t1, t2;
|
||||||
|
@ -373,3 +373,53 @@ commit;
|
|||||||
# --> connection con2
|
# --> connection con2
|
||||||
# --> connection default
|
# --> connection default
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# Test for bug #55273 "FLUSH TABLE tm WITH READ LOCK for Merge table
|
||||||
|
# causes assert failure".
|
||||||
|
#
|
||||||
|
drop table if exists t1, t2, tm;
|
||||||
|
create table t1 (i int);
|
||||||
|
create table t2 (i int);
|
||||||
|
create table tm (i int) engine=merge union=(t1, t2);
|
||||||
|
insert into t1 values (1), (2);
|
||||||
|
insert into t2 values (3), (4);
|
||||||
|
# The below statement should succeed and lock merge
|
||||||
|
# table for read. Only merge table gets flushed and
|
||||||
|
# not underlying tables.
|
||||||
|
flush tables tm with read lock;
|
||||||
|
select * from tm;
|
||||||
|
i
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
# Check that underlying tables are locked.
|
||||||
|
select * from t1;
|
||||||
|
i
|
||||||
|
1
|
||||||
|
2
|
||||||
|
select * from t2;
|
||||||
|
i
|
||||||
|
3
|
||||||
|
4
|
||||||
|
unlock tables;
|
||||||
|
# This statement should succeed as well and flush
|
||||||
|
# all tables in the list.
|
||||||
|
flush tables tm, t1, t2 with read lock;
|
||||||
|
select * from tm;
|
||||||
|
i
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
# Naturally, underlying tables should be locked in this case too.
|
||||||
|
select * from t1;
|
||||||
|
i
|
||||||
|
1
|
||||||
|
2
|
||||||
|
select * from t2;
|
||||||
|
i
|
||||||
|
3
|
||||||
|
4
|
||||||
|
unlock tables;
|
||||||
|
drop tables tm, t1, t2;
|
||||||
|
@ -1726,7 +1726,22 @@ CREATE TABLE t1(a INT);
|
|||||||
INSERT INTO t1 VALUES (1);
|
INSERT INTO t1 VALUES (1);
|
||||||
HANDLER t1 OPEN;
|
HANDLER t1 OPEN;
|
||||||
HANDLER t1 READ FIRST WHERE f1() = 1;
|
HANDLER t1 READ FIRST WHERE f1() = 1;
|
||||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
|
||||||
|
HANDLER t1 CLOSE;
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# Bug#54920 Stored functions are allowed in HANDLER statements,
|
||||||
|
# but broken.
|
||||||
|
#
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP FUNCTION IF EXISTS f1;
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
INSERT INTO t1 VALUES (1), (2);
|
||||||
|
CREATE FUNCTION f1() RETURNS INT RETURN 1;
|
||||||
|
HANDLER t1 OPEN;
|
||||||
|
HANDLER t1 READ FIRST WHERE f1() = 1;
|
||||||
|
ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
|
||||||
HANDLER t1 CLOSE;
|
HANDLER t1 CLOSE;
|
||||||
DROP FUNCTION f1;
|
DROP FUNCTION f1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
@ -1722,7 +1722,22 @@ CREATE TABLE t1(a INT);
|
|||||||
INSERT INTO t1 VALUES (1);
|
INSERT INTO t1 VALUES (1);
|
||||||
HANDLER t1 OPEN;
|
HANDLER t1 OPEN;
|
||||||
HANDLER t1 READ FIRST WHERE f1() = 1;
|
HANDLER t1 READ FIRST WHERE f1() = 1;
|
||||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
|
||||||
|
HANDLER t1 CLOSE;
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# Bug#54920 Stored functions are allowed in HANDLER statements,
|
||||||
|
# but broken.
|
||||||
|
#
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP FUNCTION IF EXISTS f1;
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
INSERT INTO t1 VALUES (1), (2);
|
||||||
|
CREATE FUNCTION f1() RETURNS INT RETURN 1;
|
||||||
|
HANDLER t1 OPEN;
|
||||||
|
HANDLER t1 READ FIRST WHERE f1() = 1;
|
||||||
|
ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
|
||||||
HANDLER t1 CLOSE;
|
HANDLER t1 CLOSE;
|
||||||
DROP FUNCTION f1;
|
DROP FUNCTION f1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
@ -17,9 +17,7 @@ mysql.columns_priv OK
|
|||||||
mysql.db OK
|
mysql.db OK
|
||||||
mysql.event OK
|
mysql.event OK
|
||||||
mysql.func OK
|
mysql.func OK
|
||||||
mysql.general_log
|
mysql.general_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.help_category OK
|
mysql.help_category OK
|
||||||
mysql.help_keyword OK
|
mysql.help_keyword OK
|
||||||
mysql.help_relation OK
|
mysql.help_relation OK
|
||||||
@ -31,9 +29,7 @@ mysql.proc OK
|
|||||||
mysql.procs_priv OK
|
mysql.procs_priv OK
|
||||||
mysql.renamed_general_log OK
|
mysql.renamed_general_log OK
|
||||||
mysql.servers OK
|
mysql.servers OK
|
||||||
mysql.slow_log
|
mysql.slow_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.tables_priv OK
|
mysql.tables_priv OK
|
||||||
mysql.time_zone OK
|
mysql.time_zone OK
|
||||||
mysql.time_zone_leap_second OK
|
mysql.time_zone_leap_second OK
|
||||||
|
@ -55,3 +55,11 @@ DROP USER user_1@localhost;
|
|||||||
DROP USER USER_1@localhost;
|
DROP USER USER_1@localhost;
|
||||||
DROP DATABASE db1;
|
DROP DATABASE db1;
|
||||||
use test;
|
use test;
|
||||||
|
#
|
||||||
|
# Extra test coverage for Bug#56595 RENAME TABLE causes assert on OS X
|
||||||
|
#
|
||||||
|
CREATE TABLE t1(a INT);
|
||||||
|
CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET new.a= 1;
|
||||||
|
RENAME TABLE t1 TO T1;
|
||||||
|
ALTER TABLE T1 RENAME t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -2913,3 +2913,41 @@ UNLOCK TABLES;
|
|||||||
# Connection default
|
# Connection default
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
DROP DATABASE db1;
|
DROP DATABASE db1;
|
||||||
|
#
|
||||||
|
# Bug#56292 Deadlock with ALTER TABLE and MERGE tables
|
||||||
|
#
|
||||||
|
DROP TABLE IF EXISTS t1, t2, m1;
|
||||||
|
CREATE TABLE t1(a INT) engine=MyISAM;
|
||||||
|
CREATE TABLE t2(a INT) engine=MyISAM;
|
||||||
|
CREATE TABLE m1(a INT) engine=MERGE UNION=(t1, t2);
|
||||||
|
INSERT INTO t1 VALUES (1), (2);
|
||||||
|
INSERT INTO t2 VALUES (3), (4);
|
||||||
|
# Connection con1
|
||||||
|
SET DEBUG_SYNC= 'mdl_upgrade_shared_lock_to_exclusive SIGNAL upgrade WAIT_FOR continue';
|
||||||
|
# Sending:
|
||||||
|
ALTER TABLE m1 engine=MERGE UNION=(t2, t1);
|
||||||
|
# Connection con2
|
||||||
|
# Waiting for ALTER TABLE to try lock upgrade
|
||||||
|
SET DEBUG_SYNC= 'now WAIT_FOR upgrade';
|
||||||
|
# Sending:
|
||||||
|
DELETE FROM t2 WHERE a = 3;
|
||||||
|
# Connection default
|
||||||
|
# Check that DELETE is waiting on a metadata lock and not a table lock.
|
||||||
|
# Now that DELETE blocks on a metadata lock, we should be able to do
|
||||||
|
# SELECT * FROM m1 here. SELECT used to be blocked by a DELETE table
|
||||||
|
# lock request.
|
||||||
|
SELECT * FROM m1;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
# Resuming ALTER TABLE
|
||||||
|
SET DEBUG_SYNC= 'now SIGNAL continue';
|
||||||
|
# Connection con1
|
||||||
|
# Reaping: ALTER TABLE m1 engine=MERGE UNION=(t2, t1)
|
||||||
|
# Connection con2
|
||||||
|
# Reaping: DELETE FROM t2 WHERE a = 3
|
||||||
|
# Connection default
|
||||||
|
DROP TABLE m1, t1, t2;
|
||||||
|
SET DEBUG_SYNC= 'RESET';
|
||||||
|
@ -2358,6 +2358,48 @@ t2 WHERE b SOUNDS LIKE e AND d = 1;
|
|||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
DROP TABLE t2, t1;
|
DROP TABLE t2, t1;
|
||||||
|
#
|
||||||
|
# Bug#46339 - crash on REPAIR TABLE merge table USE_FRM
|
||||||
|
#
|
||||||
|
DROP TABLE IF EXISTS m1, t1;
|
||||||
|
CREATE TABLE t1 (c1 INT) ENGINE=MYISAM;
|
||||||
|
CREATE TABLE m1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1) INSERT_METHOD=LAST;
|
||||||
|
LOCK TABLE m1 READ;
|
||||||
|
REPAIR TABLE m1 USE_FRM;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.m1 repair Error Table 'm1' was locked with a READ lock and can't be updated
|
||||||
|
test.m1 repair status Operation failed
|
||||||
|
UNLOCK TABLES;
|
||||||
|
REPAIR TABLE m1 USE_FRM;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.m1 repair note The storage engine for the table doesn't support repair
|
||||||
|
DROP TABLE m1,t1;
|
||||||
|
CREATE TABLE m1 (f1 BIGINT) ENGINE=MRG_MyISAM UNION(t1);
|
||||||
|
REPAIR TABLE m1 USE_FRM;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.m1 repair Warning Can't open table
|
||||||
|
test.m1 repair error Corrupt
|
||||||
|
CREATE TABLE t1 (f1 BIGINT) ENGINE = MyISAM;
|
||||||
|
REPAIR TABLE m1 USE_FRM;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.m1 repair note The storage engine for the table doesn't support repair
|
||||||
|
REPAIR TABLE m1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.m1 repair note The storage engine for the table doesn't support repair
|
||||||
|
DROP TABLE m1, t1;
|
||||||
|
CREATE TEMPORARY TABLE m1 (f1 BIGINT) ENGINE=MRG_MyISAM UNION(t1);
|
||||||
|
REPAIR TABLE m1 USE_FRM;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.m1 repair Error Table 'test.m1' doesn't exist
|
||||||
|
test.m1 repair error Corrupt
|
||||||
|
CREATE TEMPORARY TABLE t1 (f1 BIGINT) ENGINE=MyISAM;
|
||||||
|
REPAIR TABLE m1 USE_FRM;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
m1 repair error Cannot repair temporary table from .frm file
|
||||||
|
REPAIR TABLE m1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.m1 repair note The storage engine for the table doesn't support repair
|
||||||
|
DROP TABLE m1, t1;
|
||||||
End of 5.1 tests
|
End of 5.1 tests
|
||||||
#
|
#
|
||||||
# An additional test case for Bug#27430 Crash in subquery code
|
# An additional test case for Bug#27430 Crash in subquery code
|
||||||
@ -2677,7 +2719,7 @@ OPTIMIZE TABLE t1;
|
|||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 optimize Error Table 'test.t_not_exists' doesn't exist
|
test.t1 optimize Error Table 'test.t_not_exists' doesn't exist
|
||||||
test.t1 optimize Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
test.t1 optimize Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||||
test.t1 optimize note The storage engine for the table doesn't support optimize
|
test.t1 optimize error Corrupt
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
# Bug#36171 - CREATE TEMPORARY TABLE and MERGE engine
|
# Bug#36171 - CREATE TEMPORARY TABLE and MERGE engine
|
||||||
@ -3444,13 +3486,12 @@ ALTER TABLE m1 ADD INDEX (c1);
|
|||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
DROP TABLE m1, t1;
|
DROP TABLE m1, t1;
|
||||||
#
|
#
|
||||||
# If children are to be altered, they need an explicit lock.
|
# Locking the merge table will implicitly lock children.
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 (c1 INT);
|
CREATE TABLE t1 (c1 INT);
|
||||||
CREATE TABLE m1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1);
|
CREATE TABLE m1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1);
|
||||||
LOCK TABLE m1 WRITE;
|
LOCK TABLE m1 WRITE;
|
||||||
ALTER TABLE t1 ADD INDEX (c1);
|
ALTER TABLE t1 ADD INDEX (c1);
|
||||||
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
|
|
||||||
LOCK TABLE m1 WRITE, t1 WRITE;
|
LOCK TABLE m1 WRITE, t1 WRITE;
|
||||||
ALTER TABLE t1 ADD INDEX (c1);
|
ALTER TABLE t1 ADD INDEX (c1);
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
@ -3576,4 +3617,48 @@ ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'm1
|
|||||||
drop view v1;
|
drop view v1;
|
||||||
drop temporary table tmp;
|
drop temporary table tmp;
|
||||||
drop table t1, t2, t3, m1, m2;
|
drop table t1, t2, t3, m1, m2;
|
||||||
|
#
|
||||||
|
# Bug#56494 Segfault in upgrade_shared_lock_to_exclusive() for
|
||||||
|
# REPAIR of merge table
|
||||||
|
#
|
||||||
|
DROP TABLE IF EXISTS t1, t2, t_not_exists;
|
||||||
|
CREATE TABLE t1(a INT);
|
||||||
|
ALTER TABLE t1 engine= MERGE UNION (t_not_exists);
|
||||||
|
ANALYZE TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 analyze Error Table 'test.t_not_exists' doesn't exist
|
||||||
|
test.t1 analyze Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||||
|
test.t1 analyze error Corrupt
|
||||||
|
CHECK TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check Error Table 'test.t_not_exists' doesn't exist
|
||||||
|
test.t1 check Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||||
|
test.t1 check error Corrupt
|
||||||
|
CHECKSUM TABLE t1;
|
||||||
|
Table Checksum
|
||||||
|
test.t1 NULL
|
||||||
|
Warnings:
|
||||||
|
Error 1146 Table 'test.t_not_exists' doesn't exist
|
||||||
|
Error 1168 Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||||
|
OPTIMIZE TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 optimize Error Table 'test.t_not_exists' doesn't exist
|
||||||
|
test.t1 optimize Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||||
|
test.t1 optimize error Corrupt
|
||||||
|
REPAIR TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 repair Error Table 'test.t_not_exists' doesn't exist
|
||||||
|
test.t1 repair Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
|
||||||
|
test.t1 repair error Corrupt
|
||||||
|
REPAIR TABLE t1 USE_FRM;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 repair Warning Can't open table
|
||||||
|
test.t1 repair error Corrupt
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1(a INT);
|
||||||
|
CREATE TABLE t2(a INT) engine= MERGE UNION (t1);
|
||||||
|
REPAIR TABLE t2 USE_FRM;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t2 repair note The storage engine for the table doesn't support repair
|
||||||
|
DROP TABLE t1, t2;
|
||||||
End of 6.0 tests
|
End of 6.0 tests
|
||||||
|
@ -46,14 +46,12 @@ insert into t1 select * from t1;
|
|||||||
flush tables;
|
flush tables;
|
||||||
optimize table t1;
|
optimize table t1;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 optimize error Table 'test.t1' is read only
|
test.t1 optimize Error Table 't1' is read only
|
||||||
Warnings:
|
test.t1 optimize status Operation failed
|
||||||
Error 1036 Table 't1' is read only
|
|
||||||
repair table t1;
|
repair table t1;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 repair error Table 'test.t1' is read only
|
test.t1 repair Error Table 't1' is read only
|
||||||
Warnings:
|
test.t1 repair status Operation failed
|
||||||
Error 1036 Table 't1' is read only
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
#
|
#
|
||||||
# BUG#41541 - Valgrind warnings on packed MyISAM table
|
# BUG#41541 - Valgrind warnings on packed MyISAM table
|
||||||
|
@ -5,9 +5,7 @@ mysql.columns_priv OK
|
|||||||
mysql.db OK
|
mysql.db OK
|
||||||
mysql.event OK
|
mysql.event OK
|
||||||
mysql.func OK
|
mysql.func OK
|
||||||
mysql.general_log
|
mysql.general_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.help_category OK
|
mysql.help_category OK
|
||||||
mysql.help_keyword OK
|
mysql.help_keyword OK
|
||||||
mysql.help_relation OK
|
mysql.help_relation OK
|
||||||
@ -18,9 +16,7 @@ mysql.plugin OK
|
|||||||
mysql.proc OK
|
mysql.proc OK
|
||||||
mysql.procs_priv OK
|
mysql.procs_priv OK
|
||||||
mysql.servers OK
|
mysql.servers OK
|
||||||
mysql.slow_log
|
mysql.slow_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.tables_priv OK
|
mysql.tables_priv OK
|
||||||
mysql.time_zone OK
|
mysql.time_zone OK
|
||||||
mysql.time_zone_leap_second OK
|
mysql.time_zone_leap_second OK
|
||||||
@ -37,9 +33,7 @@ mysql.columns_priv OK
|
|||||||
mysql.db OK
|
mysql.db OK
|
||||||
mysql.event OK
|
mysql.event OK
|
||||||
mysql.func OK
|
mysql.func OK
|
||||||
mysql.general_log
|
mysql.general_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.help_category OK
|
mysql.help_category OK
|
||||||
mysql.help_keyword OK
|
mysql.help_keyword OK
|
||||||
mysql.help_relation OK
|
mysql.help_relation OK
|
||||||
@ -50,9 +44,7 @@ mysql.plugin OK
|
|||||||
mysql.proc OK
|
mysql.proc OK
|
||||||
mysql.procs_priv OK
|
mysql.procs_priv OK
|
||||||
mysql.servers OK
|
mysql.servers OK
|
||||||
mysql.slow_log
|
mysql.slow_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.tables_priv OK
|
mysql.tables_priv OK
|
||||||
mysql.time_zone OK
|
mysql.time_zone OK
|
||||||
mysql.time_zone_leap_second OK
|
mysql.time_zone_leap_second OK
|
||||||
@ -69,9 +61,7 @@ mysql.columns_priv OK
|
|||||||
mysql.db OK
|
mysql.db OK
|
||||||
mysql.event OK
|
mysql.event OK
|
||||||
mysql.func OK
|
mysql.func OK
|
||||||
mysql.general_log
|
mysql.general_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.help_category OK
|
mysql.help_category OK
|
||||||
mysql.help_keyword OK
|
mysql.help_keyword OK
|
||||||
mysql.help_relation OK
|
mysql.help_relation OK
|
||||||
@ -82,9 +72,7 @@ mysql.plugin OK
|
|||||||
mysql.proc OK
|
mysql.proc OK
|
||||||
mysql.procs_priv OK
|
mysql.procs_priv OK
|
||||||
mysql.servers OK
|
mysql.servers OK
|
||||||
mysql.slow_log
|
mysql.slow_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.tables_priv OK
|
mysql.tables_priv OK
|
||||||
mysql.time_zone OK
|
mysql.time_zone OK
|
||||||
mysql.time_zone_leap_second OK
|
mysql.time_zone_leap_second OK
|
||||||
@ -103,9 +91,7 @@ mysql.columns_priv OK
|
|||||||
mysql.db OK
|
mysql.db OK
|
||||||
mysql.event OK
|
mysql.event OK
|
||||||
mysql.func OK
|
mysql.func OK
|
||||||
mysql.general_log
|
mysql.general_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.help_category OK
|
mysql.help_category OK
|
||||||
mysql.help_keyword OK
|
mysql.help_keyword OK
|
||||||
mysql.help_relation OK
|
mysql.help_relation OK
|
||||||
@ -116,9 +102,7 @@ mysql.plugin OK
|
|||||||
mysql.proc OK
|
mysql.proc OK
|
||||||
mysql.procs_priv OK
|
mysql.procs_priv OK
|
||||||
mysql.servers OK
|
mysql.servers OK
|
||||||
mysql.slow_log
|
mysql.slow_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.tables_priv OK
|
mysql.tables_priv OK
|
||||||
mysql.time_zone OK
|
mysql.time_zone OK
|
||||||
mysql.time_zone_leap_second OK
|
mysql.time_zone_leap_second OK
|
||||||
@ -141,9 +125,7 @@ mysql.columns_priv OK
|
|||||||
mysql.db OK
|
mysql.db OK
|
||||||
mysql.event OK
|
mysql.event OK
|
||||||
mysql.func OK
|
mysql.func OK
|
||||||
mysql.general_log
|
mysql.general_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.help_category OK
|
mysql.help_category OK
|
||||||
mysql.help_keyword OK
|
mysql.help_keyword OK
|
||||||
mysql.help_relation OK
|
mysql.help_relation OK
|
||||||
@ -154,9 +136,7 @@ mysql.plugin OK
|
|||||||
mysql.proc OK
|
mysql.proc OK
|
||||||
mysql.procs_priv OK
|
mysql.procs_priv OK
|
||||||
mysql.servers OK
|
mysql.servers OK
|
||||||
mysql.slow_log
|
mysql.slow_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.tables_priv OK
|
mysql.tables_priv OK
|
||||||
mysql.time_zone OK
|
mysql.time_zone OK
|
||||||
mysql.time_zone_leap_second OK
|
mysql.time_zone_leap_second OK
|
||||||
@ -182,9 +162,7 @@ mysql.columns_priv OK
|
|||||||
mysql.db OK
|
mysql.db OK
|
||||||
mysql.event OK
|
mysql.event OK
|
||||||
mysql.func OK
|
mysql.func OK
|
||||||
mysql.general_log
|
mysql.general_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.help_category OK
|
mysql.help_category OK
|
||||||
mysql.help_keyword OK
|
mysql.help_keyword OK
|
||||||
mysql.help_relation OK
|
mysql.help_relation OK
|
||||||
@ -195,9 +173,7 @@ mysql.plugin OK
|
|||||||
mysql.proc OK
|
mysql.proc OK
|
||||||
mysql.procs_priv OK
|
mysql.procs_priv OK
|
||||||
mysql.servers OK
|
mysql.servers OK
|
||||||
mysql.slow_log
|
mysql.slow_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.tables_priv OK
|
mysql.tables_priv OK
|
||||||
mysql.time_zone OK
|
mysql.time_zone OK
|
||||||
mysql.time_zone_leap_second OK
|
mysql.time_zone_leap_second OK
|
||||||
|
@ -7,9 +7,7 @@ mysql.columns_priv OK
|
|||||||
mysql.db OK
|
mysql.db OK
|
||||||
mysql.event OK
|
mysql.event OK
|
||||||
mysql.func OK
|
mysql.func OK
|
||||||
mysql.general_log
|
mysql.general_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.help_category OK
|
mysql.help_category OK
|
||||||
mysql.help_keyword OK
|
mysql.help_keyword OK
|
||||||
mysql.help_relation OK
|
mysql.help_relation OK
|
||||||
@ -20,9 +18,7 @@ mysql.plugin OK
|
|||||||
mysql.proc OK
|
mysql.proc OK
|
||||||
mysql.procs_priv OK
|
mysql.procs_priv OK
|
||||||
mysql.servers OK
|
mysql.servers OK
|
||||||
mysql.slow_log
|
mysql.slow_log OK
|
||||||
Error : You can't use locks with log tables.
|
|
||||||
status : OK
|
|
||||||
mysql.tables_priv OK
|
mysql.tables_priv OK
|
||||||
mysql.time_zone OK
|
mysql.time_zone OK
|
||||||
mysql.time_zone_leap_second OK
|
mysql.time_zone_leap_second OK
|
||||||
|
@ -32,3 +32,47 @@ SELECT @@global.debug;
|
|||||||
|
|
||||||
SET GLOBAL debug=@old_debug;
|
SET GLOBAL debug=@old_debug;
|
||||||
End of 5.1 tests
|
End of 5.1 tests
|
||||||
|
#
|
||||||
|
# Bug#46165 server crash in dbug
|
||||||
|
#
|
||||||
|
SET @old_globaldebug = @@global.debug;
|
||||||
|
SET @old_sessiondebug= @@session.debug;
|
||||||
|
# Test 1 - Bug test case, single connection
|
||||||
|
SET GLOBAL debug= '+O,../../log/bug46165.1.trace';
|
||||||
|
SET SESSION debug= '-d:-t:-i';
|
||||||
|
SET GLOBAL debug= '';
|
||||||
|
SET SESSION debug= '';
|
||||||
|
# Test 2 - Bug test case, two connections
|
||||||
|
# Connection default
|
||||||
|
SET GLOBAL debug= '+O,../../log/bug46165.2.trace';
|
||||||
|
SET SESSION debug= '-d:-t:-i';
|
||||||
|
# Connection con1
|
||||||
|
SET GLOBAL debug= '';
|
||||||
|
# Connection default
|
||||||
|
SET SESSION debug= '';
|
||||||
|
# Connection con1
|
||||||
|
# Connection default
|
||||||
|
SET GLOBAL debug= '';
|
||||||
|
# Test 3 - Active session trace file on disconnect
|
||||||
|
# Connection con1
|
||||||
|
SET GLOBAL debug= '+O,../../log/bug46165.3.trace';
|
||||||
|
SET SESSION debug= '-d:-t:-i';
|
||||||
|
SET GLOBAL debug= '';
|
||||||
|
# Test 4 - Active session trace file on two connections
|
||||||
|
# Connection default
|
||||||
|
SET GLOBAL debug= '+O,../../log/bug46165.4.trace';
|
||||||
|
SET SESSION debug= '-d:-t:-i';
|
||||||
|
# Connection con1
|
||||||
|
SET SESSION debug= '-d:-t:-i';
|
||||||
|
SET GLOBAL debug= '';
|
||||||
|
SET SESSION debug= '';
|
||||||
|
# Connection default
|
||||||
|
SET SESSION debug= '';
|
||||||
|
# Connection con1
|
||||||
|
# Connection default
|
||||||
|
# Test 5 - Different trace files
|
||||||
|
SET SESSION debug= '+O,../../log/bug46165.5.trace';
|
||||||
|
SET SESSION debug= '+O,../../log/bug46165.6.trace';
|
||||||
|
SET SESSION debug= '-O';
|
||||||
|
SET GLOBAL debug= @old_globaldebug;
|
||||||
|
SET SESSION debug= @old_sessiondebug;
|
||||||
|
@ -131,3 +131,14 @@ XA START 'xid1';
|
|||||||
XA END 'xid1';
|
XA END 'xid1';
|
||||||
XA ROLLBACK 'xid1';
|
XA ROLLBACK 'xid1';
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# Bug#56448 Assertion failed: ! is_set() with second xa end
|
||||||
|
#
|
||||||
|
XA START 'x';
|
||||||
|
XA END 'x';
|
||||||
|
XA END 'x';
|
||||||
|
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the IDLE state
|
||||||
|
XA PREPARE 'x';
|
||||||
|
XA PREPARE 'x';
|
||||||
|
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state
|
||||||
|
XA ROLLBACK 'x';
|
||||||
|
@ -242,7 +242,7 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
|||||||
CHECK TABLE t1;
|
CHECK TABLE t1;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 check Error Lock wait timeout exceeded; try restarting transaction
|
test.t1 check Error Lock wait timeout exceeded; try restarting transaction
|
||||||
test.t1 check error Corrupt
|
test.t1 check status Operation failed
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
CREATE TABLE t2 ( i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, f INT )
|
CREATE TABLE t2 ( i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, f INT )
|
||||||
|
@ -13,7 +13,7 @@ wait/synch/mutex/sql/LOCK_active_mi YES YES
|
|||||||
wait/synch/mutex/sql/LOCK_audit_mask YES YES
|
wait/synch/mutex/sql/LOCK_audit_mask YES YES
|
||||||
wait/synch/mutex/sql/LOCK_connection_count YES YES
|
wait/synch/mutex/sql/LOCK_connection_count YES YES
|
||||||
wait/synch/mutex/sql/LOCK_crypt YES YES
|
wait/synch/mutex/sql/LOCK_crypt YES YES
|
||||||
wait/synch/mutex/sql/LOCK_dd_owns_lock_open YES YES
|
wait/synch/mutex/sql/LOCK_delayed_create YES YES
|
||||||
select * from performance_schema.SETUP_INSTRUMENTS
|
select * from performance_schema.SETUP_INSTRUMENTS
|
||||||
where name like 'Wait/Synch/Rwlock/sql/%'
|
where name like 'Wait/Synch/Rwlock/sql/%'
|
||||||
and name not in ('wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock')
|
and name not in ('wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock')
|
||||||
|
@ -53,5 +53,29 @@ REPAIR TABLE t1;
|
|||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#56422 CHECK TABLE run when the table is locked reports corruption
|
||||||
|
--echo # along with timeout
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE TABLE t1(a INT);
|
||||||
|
LOCK TABLE t1 WRITE;
|
||||||
|
|
||||||
|
--echo # Connection con1
|
||||||
|
connect(con1, localhost, root);
|
||||||
|
SET lock_wait_timeout= 1;
|
||||||
|
CHECK TABLE t1;
|
||||||
|
|
||||||
|
--echo # Connection default
|
||||||
|
connection default;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
DROP TABLE t1;
|
||||||
|
disconnect con1;
|
||||||
|
|
||||||
|
|
||||||
# Wait till we reached the initial number of concurrent sessions
|
# Wait till we reached the initial number of concurrent sessions
|
||||||
--source include/wait_until_count_sessions.inc
|
--source include/wait_until_count_sessions.inc
|
||||||
|
@ -552,3 +552,52 @@ disconnect con1;
|
|||||||
connection default;
|
connection default;
|
||||||
DROP TABLE t1, t2, t3;
|
DROP TABLE t1, t2, t3;
|
||||||
--enable_ps_protocol
|
--enable_ps_protocol
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Test for bug #56251 "Deadlock with INSERT DELAYED and MERGE tables".
|
||||||
|
--echo #
|
||||||
|
connect (con1,localhost,root,,);
|
||||||
|
connection default;
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t1, t2, tm;
|
||||||
|
--enable_warnings
|
||||||
|
create table t1(a int);
|
||||||
|
create table t2(a int);
|
||||||
|
create table tm(a int) engine=merge union=(t1, t2);
|
||||||
|
begin;
|
||||||
|
select * from t1;
|
||||||
|
|
||||||
|
--echo # Connection 'con1'.
|
||||||
|
connection con1;
|
||||||
|
--echo # Sending:
|
||||||
|
--send alter table t1 comment 'test'
|
||||||
|
|
||||||
|
--echo # Connection 'default'.
|
||||||
|
connection default;
|
||||||
|
--echo # Wait until ALTER TABLE blocks and starts waiting
|
||||||
|
--echo # for connection 'default'. It should wait with a
|
||||||
|
--echo # pending SNW lock on 't1'.
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = "Waiting for table metadata lock" and
|
||||||
|
info = "alter table t1 comment 'test'";
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
--echo # Attempt to perform delayed insert into 'tm' should not lead
|
||||||
|
--echo # to a deadlock. Instead error ER_DELAYED_NOT_SUPPORTED should
|
||||||
|
--echo # be emitted.
|
||||||
|
--error ER_DELAYED_NOT_SUPPORTED
|
||||||
|
insert delayed into tm values (1);
|
||||||
|
--echo # Unblock ALTER TABLE.
|
||||||
|
commit;
|
||||||
|
|
||||||
|
--echo # Connection 'con1'.
|
||||||
|
connection con1;
|
||||||
|
--echo # Reaping ALTER TABLE:
|
||||||
|
--reap
|
||||||
|
|
||||||
|
disconnect con1;
|
||||||
|
--source include/wait_until_disconnected.inc
|
||||||
|
--echo # Connection 'default'.
|
||||||
|
connection default;
|
||||||
|
drop tables tm, t1, t2;
|
||||||
|
@ -546,3 +546,34 @@ disconnect con2;
|
|||||||
connection default;
|
connection default;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Test for bug #55273 "FLUSH TABLE tm WITH READ LOCK for Merge table
|
||||||
|
--echo # causes assert failure".
|
||||||
|
--echo #
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t1, t2, tm;
|
||||||
|
--enable_warnings
|
||||||
|
create table t1 (i int);
|
||||||
|
create table t2 (i int);
|
||||||
|
create table tm (i int) engine=merge union=(t1, t2);
|
||||||
|
insert into t1 values (1), (2);
|
||||||
|
insert into t2 values (3), (4);
|
||||||
|
--echo # The below statement should succeed and lock merge
|
||||||
|
--echo # table for read. Only merge table gets flushed and
|
||||||
|
--echo # not underlying tables.
|
||||||
|
flush tables tm with read lock;
|
||||||
|
select * from tm;
|
||||||
|
--echo # Check that underlying tables are locked.
|
||||||
|
select * from t1;
|
||||||
|
select * from t2;
|
||||||
|
unlock tables;
|
||||||
|
--echo # This statement should succeed as well and flush
|
||||||
|
--echo # all tables in the list.
|
||||||
|
flush tables tm, t1, t2 with read lock;
|
||||||
|
select * from tm;
|
||||||
|
--echo # Naturally, underlying tables should be locked in this case too.
|
||||||
|
select * from t1;
|
||||||
|
select * from t2;
|
||||||
|
unlock tables;
|
||||||
|
drop tables tm, t1, t2;
|
||||||
|
@ -91,3 +91,14 @@ DROP DATABASE db1;
|
|||||||
use test;
|
use test;
|
||||||
|
|
||||||
# End of 5.0 tests
|
# End of 5.0 tests
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Extra test coverage for Bug#56595 RENAME TABLE causes assert on OS X
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1(a INT);
|
||||||
|
CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET new.a= 1;
|
||||||
|
RENAME TABLE t1 TO T1;
|
||||||
|
ALTER TABLE T1 RENAME t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -4532,6 +4532,68 @@ disconnect con2;
|
|||||||
disconnect con3;
|
disconnect con3;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#56292 Deadlock with ALTER TABLE and MERGE tables
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS t1, t2, m1;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE TABLE t1(a INT) engine=MyISAM;
|
||||||
|
CREATE TABLE t2(a INT) engine=MyISAM;
|
||||||
|
CREATE TABLE m1(a INT) engine=MERGE UNION=(t1, t2);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (1), (2);
|
||||||
|
INSERT INTO t2 VALUES (3), (4);
|
||||||
|
|
||||||
|
connect(con1, localhost, root);
|
||||||
|
connect(con2, localhost, root);
|
||||||
|
|
||||||
|
--echo # Connection con1
|
||||||
|
connection con1;
|
||||||
|
SET DEBUG_SYNC= 'mdl_upgrade_shared_lock_to_exclusive SIGNAL upgrade WAIT_FOR continue';
|
||||||
|
--echo # Sending:
|
||||||
|
--send ALTER TABLE m1 engine=MERGE UNION=(t2, t1)
|
||||||
|
|
||||||
|
--echo # Connection con2
|
||||||
|
connection con2;
|
||||||
|
--echo # Waiting for ALTER TABLE to try lock upgrade
|
||||||
|
SET DEBUG_SYNC= 'now WAIT_FOR upgrade';
|
||||||
|
--echo # Sending:
|
||||||
|
--send DELETE FROM t2 WHERE a = 3
|
||||||
|
|
||||||
|
--echo # Connection default
|
||||||
|
connection default;
|
||||||
|
--echo # Check that DELETE is waiting on a metadata lock and not a table lock.
|
||||||
|
let $wait_condition=
|
||||||
|
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||||
|
WHERE state = "Waiting for table metadata lock" AND
|
||||||
|
info = "DELETE FROM t2 WHERE a = 3";
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
--echo # Now that DELETE blocks on a metadata lock, we should be able to do
|
||||||
|
--echo # SELECT * FROM m1 here. SELECT used to be blocked by a DELETE table
|
||||||
|
--echo # lock request.
|
||||||
|
SELECT * FROM m1;
|
||||||
|
--echo # Resuming ALTER TABLE
|
||||||
|
SET DEBUG_SYNC= 'now SIGNAL continue';
|
||||||
|
|
||||||
|
--echo # Connection con1
|
||||||
|
connection con1;
|
||||||
|
--echo # Reaping: ALTER TABLE m1 engine=MERGE UNION=(t2, t1)
|
||||||
|
--reap
|
||||||
|
--echo # Connection con2
|
||||||
|
connection con2;
|
||||||
|
--echo # Reaping: DELETE FROM t2 WHERE a = 3
|
||||||
|
--reap
|
||||||
|
--echo # Connection default
|
||||||
|
connection default;
|
||||||
|
DROP TABLE m1, t1, t2;
|
||||||
|
SET DEBUG_SYNC= 'RESET';
|
||||||
|
disconnect con1;
|
||||||
|
disconnect con2;
|
||||||
|
|
||||||
|
|
||||||
# Check that all connections opened by test cases in this file are really
|
# Check that all connections opened by test cases in this file are really
|
||||||
# gone so execution of other tests won't be affected by their presence.
|
# gone so execution of other tests won't be affected by their presence.
|
||||||
--source include/wait_until_count_sessions.inc
|
--source include/wait_until_count_sessions.inc
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
# Test of MERGE TABLES
|
# Test of MERGE TABLES
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# Save the initial number of concurrent sessions.
|
||||||
|
--source include/count_sessions.inc
|
||||||
|
|
||||||
# MERGE tables require MyISAM tables
|
# MERGE tables require MyISAM tables
|
||||||
let $default=`select @@global.storage_engine`;
|
let $default=`select @@global.storage_engine`;
|
||||||
set global storage_engine=myisam;
|
set global storage_engine=myisam;
|
||||||
@ -1731,6 +1734,84 @@ t2 WHERE b SOUNDS LIKE e AND d = 1;
|
|||||||
|
|
||||||
DROP TABLE t2, t1;
|
DROP TABLE t2, t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#46339 - crash on REPAIR TABLE merge table USE_FRM
|
||||||
|
--echo #
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS m1, t1;
|
||||||
|
--enable_warnings
|
||||||
|
#
|
||||||
|
# Test derived from a proposal of Shane Bester.
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (c1 INT) ENGINE=MYISAM;
|
||||||
|
CREATE TABLE m1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1) INSERT_METHOD=LAST;
|
||||||
|
#
|
||||||
|
# REPAIR ... USE_FRM with LOCK TABLES.
|
||||||
|
#
|
||||||
|
LOCK TABLE m1 READ;
|
||||||
|
REPAIR TABLE m1 USE_FRM;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
#
|
||||||
|
# REPAIR ... USE_FRM without LOCK TABLES.
|
||||||
|
#
|
||||||
|
# This statement crashed the server (Bug#46339).
|
||||||
|
#
|
||||||
|
REPAIR TABLE m1 USE_FRM;
|
||||||
|
#
|
||||||
|
DROP TABLE m1,t1;
|
||||||
|
#
|
||||||
|
# Test derived from a proposal of Matthias Leich.
|
||||||
|
#
|
||||||
|
# Base table is missing.
|
||||||
|
#
|
||||||
|
CREATE TABLE m1 (f1 BIGINT) ENGINE=MRG_MyISAM UNION(t1);
|
||||||
|
#
|
||||||
|
# This statement crashed the server (Bug#46339).
|
||||||
|
#
|
||||||
|
REPAIR TABLE m1 USE_FRM;
|
||||||
|
#
|
||||||
|
# Create base table.
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (f1 BIGINT) ENGINE = MyISAM;
|
||||||
|
#
|
||||||
|
# This statement crashed the server (Bug#46339).
|
||||||
|
#
|
||||||
|
REPAIR TABLE m1 USE_FRM;
|
||||||
|
#
|
||||||
|
# Normal repair as reference.
|
||||||
|
#
|
||||||
|
REPAIR TABLE m1;
|
||||||
|
#
|
||||||
|
# Cleanup.
|
||||||
|
#
|
||||||
|
DROP TABLE m1, t1;
|
||||||
|
#
|
||||||
|
# Same with temporary tables.
|
||||||
|
#
|
||||||
|
# Base table is missing.
|
||||||
|
#
|
||||||
|
CREATE TEMPORARY TABLE m1 (f1 BIGINT) ENGINE=MRG_MyISAM UNION(t1);
|
||||||
|
#
|
||||||
|
# This statement crashed the server (Bug#46339).
|
||||||
|
#
|
||||||
|
REPAIR TABLE m1 USE_FRM;
|
||||||
|
#
|
||||||
|
# Create base table.
|
||||||
|
#
|
||||||
|
CREATE TEMPORARY TABLE t1 (f1 BIGINT) ENGINE=MyISAM;
|
||||||
|
#
|
||||||
|
# This statement crashed the server (Bug#46339).
|
||||||
|
#
|
||||||
|
REPAIR TABLE m1 USE_FRM;
|
||||||
|
#
|
||||||
|
# Normal repair as reference.
|
||||||
|
#
|
||||||
|
REPAIR TABLE m1;
|
||||||
|
#
|
||||||
|
# Cleanup.
|
||||||
|
#
|
||||||
|
DROP TABLE m1, t1;
|
||||||
|
|
||||||
--echo End of 5.1 tests
|
--echo End of 5.1 tests
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
@ -2519,12 +2600,11 @@ UNLOCK TABLES;
|
|||||||
DROP TABLE m1, t1;
|
DROP TABLE m1, t1;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # If children are to be altered, they need an explicit lock.
|
--echo # Locking the merge table will implicitly lock children.
|
||||||
--echo #
|
--echo #
|
||||||
CREATE TABLE t1 (c1 INT);
|
CREATE TABLE t1 (c1 INT);
|
||||||
CREATE TABLE m1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1);
|
CREATE TABLE m1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1);
|
||||||
LOCK TABLE m1 WRITE;
|
LOCK TABLE m1 WRITE;
|
||||||
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
|
||||||
ALTER TABLE t1 ADD INDEX (c1);
|
ALTER TABLE t1 ADD INDEX (c1);
|
||||||
LOCK TABLE m1 WRITE, t1 WRITE;
|
LOCK TABLE m1 WRITE, t1 WRITE;
|
||||||
ALTER TABLE t1 ADD INDEX (c1);
|
ALTER TABLE t1 ADD INDEX (c1);
|
||||||
@ -2665,6 +2745,37 @@ drop view v1;
|
|||||||
drop temporary table tmp;
|
drop temporary table tmp;
|
||||||
drop table t1, t2, t3, m1, m2;
|
drop table t1, t2, t3, m1, m2;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#56494 Segfault in upgrade_shared_lock_to_exclusive() for
|
||||||
|
--echo # REPAIR of merge table
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS t1, t2, t_not_exists;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE TABLE t1(a INT);
|
||||||
|
ALTER TABLE t1 engine= MERGE UNION (t_not_exists);
|
||||||
|
# This caused the segfault
|
||||||
|
ANALYZE TABLE t1;
|
||||||
|
CHECK TABLE t1;
|
||||||
|
CHECKSUM TABLE t1;
|
||||||
|
OPTIMIZE TABLE t1;
|
||||||
|
REPAIR TABLE t1;
|
||||||
|
|
||||||
|
# This caused an assert
|
||||||
|
REPAIR TABLE t1 USE_FRM;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1(a INT);
|
||||||
|
CREATE TABLE t2(a INT) engine= MERGE UNION (t1);
|
||||||
|
# This caused an assert
|
||||||
|
REPAIR TABLE t2 USE_FRM;
|
||||||
|
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
|
||||||
--echo End of 6.0 tests
|
--echo End of 6.0 tests
|
||||||
|
|
||||||
--disable_result_log
|
--disable_result_log
|
||||||
@ -2672,3 +2783,7 @@ drop table t1, t2, t3, m1, m2;
|
|||||||
eval set global storage_engine=$default;
|
eval set global storage_engine=$default;
|
||||||
--enable_result_log
|
--enable_result_log
|
||||||
--enable_query_log
|
--enable_query_log
|
||||||
|
|
||||||
|
# Check that all connections opened by test cases in this file are really
|
||||||
|
# gone so execution of other tests won't be affected by their presence.
|
||||||
|
--source include/wait_until_count_sessions.inc
|
||||||
|
@ -36,3 +36,78 @@ SELECT @@global.debug;
|
|||||||
SET GLOBAL debug=@old_debug;
|
SET GLOBAL debug=@old_debug;
|
||||||
|
|
||||||
--echo End of 5.1 tests
|
--echo End of 5.1 tests
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#46165 server crash in dbug
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET @old_globaldebug = @@global.debug;
|
||||||
|
SET @old_sessiondebug= @@session.debug;
|
||||||
|
|
||||||
|
--echo # Test 1 - Bug test case, single connection
|
||||||
|
SET GLOBAL debug= '+O,../../log/bug46165.1.trace';
|
||||||
|
SET SESSION debug= '-d:-t:-i';
|
||||||
|
|
||||||
|
SET GLOBAL debug= '';
|
||||||
|
SET SESSION debug= '';
|
||||||
|
|
||||||
|
--echo # Test 2 - Bug test case, two connections
|
||||||
|
--echo # Connection default
|
||||||
|
connection default;
|
||||||
|
SET GLOBAL debug= '+O,../../log/bug46165.2.trace';
|
||||||
|
SET SESSION debug= '-d:-t:-i';
|
||||||
|
|
||||||
|
--echo # Connection con1
|
||||||
|
connect (con1, localhost, root);
|
||||||
|
SET GLOBAL debug= '';
|
||||||
|
|
||||||
|
--echo # Connection default
|
||||||
|
connection default;
|
||||||
|
SET SESSION debug= '';
|
||||||
|
--echo # Connection con1
|
||||||
|
connection con1;
|
||||||
|
disconnect con1;
|
||||||
|
--source include/wait_until_disconnected.inc
|
||||||
|
--echo # Connection default
|
||||||
|
connection default;
|
||||||
|
SET GLOBAL debug= '';
|
||||||
|
|
||||||
|
--echo # Test 3 - Active session trace file on disconnect
|
||||||
|
--echo # Connection con1
|
||||||
|
connect (con1, localhost, root);
|
||||||
|
SET GLOBAL debug= '+O,../../log/bug46165.3.trace';
|
||||||
|
SET SESSION debug= '-d:-t:-i';
|
||||||
|
SET GLOBAL debug= '';
|
||||||
|
disconnect con1;
|
||||||
|
--source include/wait_until_disconnected.inc
|
||||||
|
|
||||||
|
--echo # Test 4 - Active session trace file on two connections
|
||||||
|
--echo # Connection default
|
||||||
|
connection default;
|
||||||
|
SET GLOBAL debug= '+O,../../log/bug46165.4.trace';
|
||||||
|
SET SESSION debug= '-d:-t:-i';
|
||||||
|
|
||||||
|
--echo # Connection con1
|
||||||
|
connect (con1, localhost, root);
|
||||||
|
SET SESSION debug= '-d:-t:-i';
|
||||||
|
SET GLOBAL debug= '';
|
||||||
|
SET SESSION debug= '';
|
||||||
|
|
||||||
|
--echo # Connection default
|
||||||
|
connection default;
|
||||||
|
SET SESSION debug= '';
|
||||||
|
--echo # Connection con1
|
||||||
|
connection con1;
|
||||||
|
disconnect con1;
|
||||||
|
--source include/wait_until_disconnected.inc
|
||||||
|
--echo # Connection default
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
--echo # Test 5 - Different trace files
|
||||||
|
SET SESSION debug= '+O,../../log/bug46165.5.trace';
|
||||||
|
SET SESSION debug= '+O,../../log/bug46165.6.trace';
|
||||||
|
SET SESSION debug= '-O';
|
||||||
|
|
||||||
|
SET GLOBAL debug= @old_globaldebug;
|
||||||
|
SET SESSION debug= @old_sessiondebug;
|
||||||
|
@ -228,6 +228,23 @@ XA ROLLBACK 'xid1';
|
|||||||
disconnect con1;
|
disconnect con1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#56448 Assertion failed: ! is_set() with second xa end
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
XA START 'x';
|
||||||
|
XA END 'x';
|
||||||
|
# Second XA END caused an assertion.
|
||||||
|
--error ER_XAER_RMFAIL
|
||||||
|
XA END 'x';
|
||||||
|
XA PREPARE 'x';
|
||||||
|
# Second XA PREPARE also caused an assertion.
|
||||||
|
--error ER_XAER_RMFAIL
|
||||||
|
XA PREPARE 'x';
|
||||||
|
XA ROLLBACK 'x';
|
||||||
|
|
||||||
|
|
||||||
# Wait till all disconnects are completed
|
# Wait till all disconnects are completed
|
||||||
--source include/wait_until_count_sessions.inc
|
--source include/wait_until_count_sessions.inc
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@
|
|||||||
* Mountain View, California 94043
|
* Mountain View, California 94043
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr)
|
int my_rw_init(my_rw_lock_t *rwp)
|
||||||
{
|
{
|
||||||
pthread_condattr_t cond_attr;
|
pthread_condattr_t cond_attr;
|
||||||
|
|
||||||
@ -74,8 +74,6 @@ int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr)
|
|||||||
#ifdef SAFE_MUTEX
|
#ifdef SAFE_MUTEX
|
||||||
rwp->write_thread = 0;
|
rwp->write_thread = 0;
|
||||||
#endif
|
#endif
|
||||||
/* If attribute argument is NULL use default value - prefer writers. */
|
|
||||||
rwp->prefer_readers= prefer_readers_attr ? *prefer_readers_attr : FALSE;
|
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
@ -96,8 +94,7 @@ int my_rw_rdlock(my_rw_lock_t *rwp)
|
|||||||
pthread_mutex_lock(&rwp->lock);
|
pthread_mutex_lock(&rwp->lock);
|
||||||
|
|
||||||
/* active or queued writers */
|
/* active or queued writers */
|
||||||
while (( rwp->state < 0 ) ||
|
while (( rwp->state < 0 ) || rwp->waiters)
|
||||||
(rwp->waiters && ! rwp->prefer_readers))
|
|
||||||
pthread_cond_wait( &rwp->readers, &rwp->lock);
|
pthread_cond_wait( &rwp->readers, &rwp->lock);
|
||||||
|
|
||||||
rwp->state++;
|
rwp->state++;
|
||||||
@ -109,8 +106,7 @@ int my_rw_tryrdlock(my_rw_lock_t *rwp)
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
pthread_mutex_lock(&rwp->lock);
|
pthread_mutex_lock(&rwp->lock);
|
||||||
if ((rwp->state < 0 ) ||
|
if ((rwp->state < 0 ) || rwp->waiters)
|
||||||
(rwp->waiters && ! rwp->prefer_readers))
|
|
||||||
res= EBUSY; /* Can't get lock */
|
res= EBUSY; /* Can't get lock */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -192,30 +188,127 @@ int my_rw_unlock(my_rw_lock_t *rwp)
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* defined(NEED_MY_RW_LOCK) */
|
||||||
|
|
||||||
int rw_pr_init(struct st_my_rw_lock_t *rwlock)
|
|
||||||
{
|
|
||||||
my_bool prefer_readers_attr= TRUE;
|
|
||||||
return my_rw_init(rwlock, &prefer_readers_attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/*
|
|
||||||
We are on system which has native read/write locks which support
|
|
||||||
preferring of readers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int rw_pr_init(rw_pr_lock_t *rwlock)
|
int rw_pr_init(rw_pr_lock_t *rwlock)
|
||||||
{
|
{
|
||||||
pthread_rwlockattr_t rwlock_attr;
|
pthread_mutex_init(&rwlock->lock, NULL);
|
||||||
|
pthread_cond_init(&rwlock->no_active_readers, NULL);
|
||||||
pthread_rwlockattr_init(&rwlock_attr);
|
rwlock->active_readers= 0;
|
||||||
pthread_rwlockattr_setkind_np(&rwlock_attr, PTHREAD_RWLOCK_PREFER_READER_NP);
|
rwlock->writers_waiting_readers= 0;
|
||||||
pthread_rwlock_init(rwlock, NULL);
|
rwlock->active_writer= FALSE;
|
||||||
pthread_rwlockattr_destroy(&rwlock_attr);
|
#ifdef SAFE_MUTEX
|
||||||
|
rwlock->writer_thread= 0;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined(NEED_MY_RW_LOCK) */
|
|
||||||
|
int rw_pr_destroy(rw_pr_lock_t *rwlock)
|
||||||
|
{
|
||||||
|
pthread_cond_destroy(&rwlock->no_active_readers);
|
||||||
|
pthread_mutex_destroy(&rwlock->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int rw_pr_rdlock(rw_pr_lock_t *rwlock)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&rwlock->lock);
|
||||||
|
/*
|
||||||
|
The fact that we were able to acquire 'lock' mutex means
|
||||||
|
that there are no active writers and we can acquire rd-lock.
|
||||||
|
Increment active readers counter to prevent requests for
|
||||||
|
wr-lock from succeeding and unlock mutex.
|
||||||
|
*/
|
||||||
|
rwlock->active_readers++;
|
||||||
|
pthread_mutex_unlock(&rwlock->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int rw_pr_wrlock(rw_pr_lock_t *rwlock)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&rwlock->lock);
|
||||||
|
|
||||||
|
if (rwlock->active_readers != 0)
|
||||||
|
{
|
||||||
|
/* There are active readers. We have to wait until they are gone. */
|
||||||
|
rwlock->writers_waiting_readers++;
|
||||||
|
|
||||||
|
while (rwlock->active_readers != 0)
|
||||||
|
pthread_cond_wait(&rwlock->no_active_readers, &rwlock->lock);
|
||||||
|
|
||||||
|
rwlock->writers_waiting_readers--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
We own 'lock' mutex so there is no active writers.
|
||||||
|
Also there are no active readers.
|
||||||
|
This means that we can grant wr-lock.
|
||||||
|
Not releasing 'lock' mutex until unlock will block
|
||||||
|
both requests for rd and wr-locks.
|
||||||
|
Set 'active_writer' flag to simplify unlock.
|
||||||
|
|
||||||
|
Thanks to the fact wr-lock/unlock in the absence of
|
||||||
|
contention from readers is essentially mutex lock/unlock
|
||||||
|
with a few simple checks make this rwlock implementation
|
||||||
|
wr-lock optimized.
|
||||||
|
*/
|
||||||
|
rwlock->active_writer= TRUE;
|
||||||
|
#ifdef SAFE_MUTEX
|
||||||
|
rwlock->writer_thread= pthread_self();
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int rw_pr_unlock(rw_pr_lock_t *rwlock)
|
||||||
|
{
|
||||||
|
if (rwlock->active_writer)
|
||||||
|
{
|
||||||
|
/* We are unlocking wr-lock. */
|
||||||
|
#ifdef SAFE_MUTEX
|
||||||
|
rwlock->writer_thread= 0;
|
||||||
|
#endif
|
||||||
|
rwlock->active_writer= FALSE;
|
||||||
|
if (rwlock->writers_waiting_readers)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Avoid expensive cond signal in case when there is no contention
|
||||||
|
or it is wr-only.
|
||||||
|
|
||||||
|
Note that from view point of performance it would be better to
|
||||||
|
signal on the condition variable after unlocking mutex (as it
|
||||||
|
reduces number of contex switches).
|
||||||
|
|
||||||
|
Unfortunately this would mean that such rwlock can't be safely
|
||||||
|
used by MDL subsystem, which relies on the fact that it is OK
|
||||||
|
to destroy rwlock once it is in unlocked state.
|
||||||
|
*/
|
||||||
|
pthread_cond_signal(&rwlock->no_active_readers);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&rwlock->lock);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We are unlocking rd-lock. */
|
||||||
|
pthread_mutex_lock(&rwlock->lock);
|
||||||
|
rwlock->active_readers--;
|
||||||
|
if (rwlock->active_readers == 0 &&
|
||||||
|
rwlock->writers_waiting_readers)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
If we are last reader and there are waiting
|
||||||
|
writers wake them up.
|
||||||
|
*/
|
||||||
|
pthread_cond_signal(&rwlock->no_active_readers);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&rwlock->lock);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* defined(THREAD) */
|
#endif /* defined(THREAD) */
|
||||||
|
@ -485,10 +485,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
ret= TRUE; // OOM
|
ret= TRUE; // OOM
|
||||||
else if ((ret= db_repository->load_named_event(thd, dbname, name,
|
else if ((ret= db_repository->load_named_event(thd, dbname, name,
|
||||||
new_element)))
|
new_element)))
|
||||||
{
|
|
||||||
DBUG_ASSERT(ret == OP_LOAD_ERROR);
|
|
||||||
delete new_element;
|
delete new_element;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
13
sql/events.h
13
sql/events.h
@ -44,19 +44,6 @@ class THD;
|
|||||||
typedef class Item COND;
|
typedef class Item COND;
|
||||||
typedef struct charset_info_st CHARSET_INFO;
|
typedef struct charset_info_st CHARSET_INFO;
|
||||||
|
|
||||||
/* Return codes */
|
|
||||||
enum enum_events_error_code
|
|
||||||
{
|
|
||||||
OP_OK= 0,
|
|
||||||
OP_NOT_RUNNING,
|
|
||||||
OP_CANT_KILL,
|
|
||||||
OP_CANT_INIT,
|
|
||||||
OP_DISABLED_EVENT,
|
|
||||||
OP_LOAD_ERROR,
|
|
||||||
OP_ALREADY_EXISTS
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
|
sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
|
||||||
|
|
||||||
|
34
sql/mdl.cc
34
sql/mdl.cc
@ -124,6 +124,7 @@ public:
|
|||||||
Deadlock_detection_visitor(MDL_context *start_node_arg)
|
Deadlock_detection_visitor(MDL_context *start_node_arg)
|
||||||
: m_start_node(start_node_arg),
|
: m_start_node(start_node_arg),
|
||||||
m_victim(NULL),
|
m_victim(NULL),
|
||||||
|
m_current_search_depth(0),
|
||||||
m_found_deadlock(FALSE)
|
m_found_deadlock(FALSE)
|
||||||
{}
|
{}
|
||||||
virtual bool enter_node(MDL_context *node);
|
virtual bool enter_node(MDL_context *node);
|
||||||
@ -132,8 +133,6 @@ public:
|
|||||||
virtual bool inspect_edge(MDL_context *dest);
|
virtual bool inspect_edge(MDL_context *dest);
|
||||||
|
|
||||||
MDL_context *get_victim() const { return m_victim; }
|
MDL_context *get_victim() const { return m_victim; }
|
||||||
|
|
||||||
void abort_traversal(MDL_context *node);
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
Change the deadlock victim to a new one if it has lower deadlock
|
Change the deadlock victim to a new one if it has lower deadlock
|
||||||
@ -148,6 +147,13 @@ private:
|
|||||||
MDL_context *m_start_node;
|
MDL_context *m_start_node;
|
||||||
/** If a deadlock is found, the context that identifies the victim. */
|
/** If a deadlock is found, the context that identifies the victim. */
|
||||||
MDL_context *m_victim;
|
MDL_context *m_victim;
|
||||||
|
/** Set to the 0 at start. Increased whenever
|
||||||
|
we descend into another MDL context (aka traverse to the next
|
||||||
|
wait-for graph node). When MAX_SEARCH_DEPTH is reached, we
|
||||||
|
assume that a deadlock is found, even if we have not found a
|
||||||
|
loop.
|
||||||
|
*/
|
||||||
|
uint m_current_search_depth;
|
||||||
/** TRUE if we found a deadlock. */
|
/** TRUE if we found a deadlock. */
|
||||||
bool m_found_deadlock;
|
bool m_found_deadlock;
|
||||||
/**
|
/**
|
||||||
@ -181,7 +187,7 @@ private:
|
|||||||
|
|
||||||
bool Deadlock_detection_visitor::enter_node(MDL_context *node)
|
bool Deadlock_detection_visitor::enter_node(MDL_context *node)
|
||||||
{
|
{
|
||||||
m_found_deadlock= m_current_search_depth >= MAX_SEARCH_DEPTH;
|
m_found_deadlock= ++m_current_search_depth >= MAX_SEARCH_DEPTH;
|
||||||
if (m_found_deadlock)
|
if (m_found_deadlock)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(! m_victim);
|
DBUG_ASSERT(! m_victim);
|
||||||
@ -201,6 +207,7 @@ bool Deadlock_detection_visitor::enter_node(MDL_context *node)
|
|||||||
|
|
||||||
void Deadlock_detection_visitor::leave_node(MDL_context *node)
|
void Deadlock_detection_visitor::leave_node(MDL_context *node)
|
||||||
{
|
{
|
||||||
|
--m_current_search_depth;
|
||||||
if (m_found_deadlock)
|
if (m_found_deadlock)
|
||||||
opt_change_victim_to(node);
|
opt_change_victim_to(node);
|
||||||
}
|
}
|
||||||
@ -244,21 +251,6 @@ Deadlock_detection_visitor::opt_change_victim_to(MDL_context *new_victim)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Abort traversal of a wait-for graph and report a deadlock.
|
|
||||||
|
|
||||||
@param node Node which we were about to visit when abort
|
|
||||||
was initiated.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void Deadlock_detection_visitor::abort_traversal(MDL_context *node)
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(! m_victim);
|
|
||||||
m_found_deadlock= TRUE;
|
|
||||||
opt_change_victim_to(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get a bit corresponding to enum_mdl_type value in a granted/waiting bitmaps
|
Get a bit corresponding to enum_mdl_type value in a granted/waiting bitmaps
|
||||||
and compatibility matrices.
|
and compatibility matrices.
|
||||||
@ -2064,13 +2056,8 @@ bool MDL_lock::visit_subgraph(MDL_ticket *waiting_ticket,
|
|||||||
are visiting it but this is OK: in the worst case we might do some
|
are visiting it but this is OK: in the worst case we might do some
|
||||||
extra work and one more context might be chosen as a victim.
|
extra work and one more context might be chosen as a victim.
|
||||||
*/
|
*/
|
||||||
++gvisitor->m_current_search_depth;
|
|
||||||
|
|
||||||
if (gvisitor->enter_node(src_ctx))
|
if (gvisitor->enter_node(src_ctx))
|
||||||
{
|
|
||||||
--gvisitor->m_current_search_depth;
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We do a breadth-first search first -- that is, inspect all
|
We do a breadth-first search first -- that is, inspect all
|
||||||
@ -2127,7 +2114,6 @@ bool MDL_lock::visit_subgraph(MDL_ticket *waiting_ticket,
|
|||||||
|
|
||||||
end_leave_node:
|
end_leave_node:
|
||||||
gvisitor->leave_node(src_ctx);
|
gvisitor->leave_node(src_ctx);
|
||||||
--gvisitor->m_current_search_depth;
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
mysql_prlock_unlock(&m_rwlock);
|
mysql_prlock_unlock(&m_rwlock);
|
||||||
|
16
sql/mdl.h
16
sql/mdl.h
@ -385,10 +385,7 @@ public:
|
|||||||
|
|
||||||
virtual bool inspect_edge(MDL_context *dest) = 0;
|
virtual bool inspect_edge(MDL_context *dest) = 0;
|
||||||
virtual ~MDL_wait_for_graph_visitor();
|
virtual ~MDL_wait_for_graph_visitor();
|
||||||
MDL_wait_for_graph_visitor() :m_lock_open_count(0),
|
MDL_wait_for_graph_visitor() :m_lock_open_count(0) {}
|
||||||
m_current_search_depth(0)
|
|
||||||
{ }
|
|
||||||
virtual void abort_traversal(MDL_context *node) = 0;
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
XXX, hack: During deadlock search, we may need to
|
XXX, hack: During deadlock search, we may need to
|
||||||
@ -399,17 +396,6 @@ public:
|
|||||||
LOCK_open since it has significant performance impacts.
|
LOCK_open since it has significant performance impacts.
|
||||||
*/
|
*/
|
||||||
uint m_lock_open_count;
|
uint m_lock_open_count;
|
||||||
/**
|
|
||||||
Set to the 0 at start. Increased whenever
|
|
||||||
we descend into another MDL context (aka traverse to the next
|
|
||||||
wait-for graph node). When MAX_SEARCH_DEPTH is reached, we
|
|
||||||
assume that a deadlock is found, even if we have not found a
|
|
||||||
loop.
|
|
||||||
|
|
||||||
XXX: This member belongs to this class only temporarily until
|
|
||||||
bug #56405 is fixed.
|
|
||||||
*/
|
|
||||||
uint m_current_search_depth;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4035,7 +4035,8 @@ end:
|
|||||||
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
||||||
bool any_combination_will_do, uint number, bool no_errors)
|
bool any_combination_will_do, uint number, bool no_errors)
|
||||||
{
|
{
|
||||||
TABLE_LIST *table, *first_not_own_table= thd->lex->first_not_own_table();
|
TABLE_LIST *tl;
|
||||||
|
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
|
||||||
Security_context *sctx= thd->security_ctx;
|
Security_context *sctx= thd->security_ctx;
|
||||||
uint i;
|
uint i;
|
||||||
ulong orig_want_access= want_access;
|
ulong orig_want_access= want_access;
|
||||||
@ -4052,34 +4053,32 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
|||||||
the given table list refers to the list for prelocking (contains tables
|
the given table list refers to the list for prelocking (contains tables
|
||||||
of other queries). For simple queries first_not_own_table is 0.
|
of other queries). For simple queries first_not_own_table is 0.
|
||||||
*/
|
*/
|
||||||
for (i= 0, table= tables;
|
for (i= 0, tl= tables;
|
||||||
i < number && table != first_not_own_table;
|
i < number && tl != first_not_own_table;
|
||||||
table= table->next_global, i++)
|
tl= tl->next_global, i++)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Save a copy of the privileges without the SHOW_VIEW_ACL attribute.
|
Save a copy of the privileges without the SHOW_VIEW_ACL attribute.
|
||||||
It will be checked during making view.
|
It will be checked during making view.
|
||||||
*/
|
*/
|
||||||
table->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
|
tl->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
|
||||||
}
|
}
|
||||||
|
|
||||||
mysql_rwlock_rdlock(&LOCK_grant);
|
mysql_rwlock_rdlock(&LOCK_grant);
|
||||||
for (table= tables;
|
for (tl= tables;
|
||||||
table && number-- && table != first_not_own_table;
|
tl && number-- && tl != first_not_own_table;
|
||||||
table= table->next_global)
|
tl= tl->next_global)
|
||||||
{
|
{
|
||||||
GRANT_TABLE *grant_table;
|
sctx = test(tl->security_ctx) ? tl->security_ctx : thd->security_ctx;
|
||||||
sctx = test(table->security_ctx) ?
|
|
||||||
table->security_ctx : thd->security_ctx;
|
|
||||||
|
|
||||||
const ACL_internal_table_access *access;
|
const ACL_internal_table_access *access=
|
||||||
access= get_cached_table_access(&table->grant.m_internal,
|
get_cached_table_access(&tl->grant.m_internal,
|
||||||
table->get_db_name(),
|
tl->get_db_name(),
|
||||||
table->get_table_name());
|
tl->get_table_name());
|
||||||
|
|
||||||
if (access)
|
if (access)
|
||||||
{
|
{
|
||||||
switch(access->check(orig_want_access, &table->grant.privilege))
|
switch(access->check(orig_want_access, &tl->grant.privilege))
|
||||||
{
|
{
|
||||||
case ACL_INTERNAL_ACCESS_GRANTED:
|
case ACL_INTERNAL_ACCESS_GRANTED:
|
||||||
/*
|
/*
|
||||||
@ -4103,29 +4102,33 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
|||||||
if (!want_access)
|
if (!want_access)
|
||||||
continue; // ok
|
continue; // ok
|
||||||
|
|
||||||
if (!(~table->grant.privilege & want_access) ||
|
if (!(~tl->grant.privilege & want_access) ||
|
||||||
table->is_anonymous_derived_table() || table->schema_table)
|
tl->is_anonymous_derived_table() || tl->schema_table)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
It is subquery in the FROM clause. VIEW set table->derived after
|
It is subquery in the FROM clause. VIEW set tl->derived after
|
||||||
table opening, but this function always called before table opening.
|
table opening, but this function always called before table opening.
|
||||||
*/
|
*/
|
||||||
if (!table->referencing_view)
|
if (!tl->referencing_view)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If it's a temporary table created for a subquery in the FROM
|
If it's a temporary table created for a subquery in the FROM
|
||||||
clause, or an INFORMATION_SCHEMA table, drop the request for
|
clause, or an INFORMATION_SCHEMA table, drop the request for
|
||||||
a privilege.
|
a privilege.
|
||||||
*/
|
*/
|
||||||
table->grant.want_privilege= 0;
|
tl->grant.want_privilege= 0;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!(grant_table= table_hash_search(sctx->host, sctx->ip,
|
GRANT_TABLE *grant_table= table_hash_search(sctx->host, sctx->ip,
|
||||||
table->get_db_name(), sctx->priv_user,
|
tl->get_db_name(),
|
||||||
table->get_table_name(), FALSE)))
|
sctx->priv_user,
|
||||||
|
tl->get_table_name(),
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
if (!grant_table)
|
||||||
{
|
{
|
||||||
want_access &= ~table->grant.privilege;
|
want_access &= ~tl->grant.privilege;
|
||||||
goto err; // No grants
|
goto err; // No grants
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4136,18 +4139,17 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
|||||||
if (any_combination_will_do)
|
if (any_combination_will_do)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
table->grant.grant_table=grant_table; // Remember for column test
|
tl->grant.grant_table= grant_table; // Remember for column test
|
||||||
table->grant.version=grant_version;
|
tl->grant.version= grant_version;
|
||||||
table->grant.privilege|= grant_table->privs;
|
tl->grant.privilege|= grant_table->privs;
|
||||||
table->grant.want_privilege= ((want_access & COL_ACLS)
|
tl->grant.want_privilege= ((want_access & COL_ACLS) & ~tl->grant.privilege);
|
||||||
& ~table->grant.privilege);
|
|
||||||
|
|
||||||
if (!(~table->grant.privilege & want_access))
|
if (!(~tl->grant.privilege & want_access))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (want_access & ~(grant_table->cols | table->grant.privilege))
|
if (want_access & ~(grant_table->cols | tl->grant.privilege))
|
||||||
{
|
{
|
||||||
want_access &= ~(grant_table->cols | table->grant.privilege);
|
want_access &= ~(grant_table->cols | tl->grant.privilege);
|
||||||
goto err; // impossible
|
goto err; // impossible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4164,7 +4166,7 @@ err:
|
|||||||
command,
|
command,
|
||||||
sctx->priv_user,
|
sctx->priv_user,
|
||||||
sctx->host_or_ip,
|
sctx->host_or_ip,
|
||||||
table ? table->get_table_name() : "unknown");
|
tl ? tl->get_table_name() : "unknown");
|
||||||
}
|
}
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
@ -111,9 +111,6 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
|
|||||||
table= &tmp_table;
|
table= &tmp_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A MERGE table must not come here. */
|
|
||||||
DBUG_ASSERT(table->file->ht->db_type != DB_TYPE_MRG_MYISAM);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
REPAIR TABLE ... USE_FRM for temporary tables makes little sense.
|
REPAIR TABLE ... USE_FRM for temporary tables makes little sense.
|
||||||
*/
|
*/
|
||||||
@ -151,6 +148,9 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
|
|||||||
if (!ext[0] || !ext[1])
|
if (!ext[0] || !ext[1])
|
||||||
goto end; // No data file
|
goto end; // No data file
|
||||||
|
|
||||||
|
/* A MERGE table must not come here. */
|
||||||
|
DBUG_ASSERT(table->file->ht->db_type != DB_TYPE_MRG_MYISAM);
|
||||||
|
|
||||||
// Name of data file
|
// Name of data file
|
||||||
strxmov(from, table->s->normalized_path.str, ext[1], NullS);
|
strxmov(from, table->s->normalized_path.str, ext[1], NullS);
|
||||||
if (!mysql_file_stat(key_file_misc, from, &stat_info, MYF(0)))
|
if (!mysql_file_stat(key_file_misc, from, &stat_info, MYF(0)))
|
||||||
@ -231,6 +231,26 @@ end:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if a given error is something that could occur during
|
||||||
|
open_and_lock_tables() that does not indicate table corruption.
|
||||||
|
|
||||||
|
@param sql_errno Error number to check.
|
||||||
|
|
||||||
|
@retval TRUE Error does not indicate table corruption.
|
||||||
|
@retval FALSE Error could indicate table corruption.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline bool table_not_corrupt_error(uint sql_errno)
|
||||||
|
{
|
||||||
|
return (sql_errno == ER_NO_SUCH_TABLE ||
|
||||||
|
sql_errno == ER_FILE_NOT_FOUND ||
|
||||||
|
sql_errno == ER_LOCK_WAIT_TIMEOUT ||
|
||||||
|
sql_errno == ER_LOCK_DEADLOCK ||
|
||||||
|
sql_errno == ER_CANT_LOCK_LOG_TABLE ||
|
||||||
|
sql_errno == ER_OPEN_AS_READONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
RETURN VALUES
|
RETURN VALUES
|
||||||
@ -311,7 +331,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
|||||||
lex->query_tables= table;
|
lex->query_tables= table;
|
||||||
lex->query_tables_last= &table->next_global;
|
lex->query_tables_last= &table->next_global;
|
||||||
lex->query_tables_own_last= 0;
|
lex->query_tables_own_last= 0;
|
||||||
thd->no_warnings_for_error= no_warnings_for_error;
|
/*
|
||||||
|
Under locked tables, we know that the table can be opened,
|
||||||
|
so any errors opening the table are logical errors.
|
||||||
|
In these cases it makes sense to report them.
|
||||||
|
*/
|
||||||
|
if (!thd->locked_tables_mode)
|
||||||
|
thd->no_warnings_for_error= no_warnings_for_error;
|
||||||
if (view_operator_func == NULL)
|
if (view_operator_func == NULL)
|
||||||
table->required_type=FRMTYPE_TABLE;
|
table->required_type=FRMTYPE_TABLE;
|
||||||
|
|
||||||
@ -320,6 +346,14 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
|||||||
table->next_global= save_next_global;
|
table->next_global= save_next_global;
|
||||||
table->next_local= save_next_local;
|
table->next_local= save_next_local;
|
||||||
thd->open_options&= ~extra_open_options;
|
thd->open_options&= ~extra_open_options;
|
||||||
|
|
||||||
|
/*
|
||||||
|
If open_and_lock_tables() failed, close_thread_tables() will close
|
||||||
|
the table and table->table can therefore be invalid.
|
||||||
|
*/
|
||||||
|
if (open_error)
|
||||||
|
table->table= NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Under locked tables, we know that the table can be opened,
|
Under locked tables, we know that the table can be opened,
|
||||||
so any errors opening the table are logical errors.
|
so any errors opening the table are logical errors.
|
||||||
@ -418,9 +452,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
|||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM));
|
ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM));
|
||||||
if (thd->stmt_da->is_error() &&
|
if (thd->stmt_da->is_error() &&
|
||||||
(thd->stmt_da->sql_errno() == ER_NO_SUCH_TABLE ||
|
table_not_corrupt_error(thd->stmt_da->sql_errno()))
|
||||||
thd->stmt_da->sql_errno() == ER_FILE_NOT_FOUND))
|
|
||||||
/* A missing table is just issued as a failed command */
|
|
||||||
result_code= HA_ADMIN_FAILED;
|
result_code= HA_ADMIN_FAILED;
|
||||||
else
|
else
|
||||||
/* Default failure code is corrupt table */
|
/* Default failure code is corrupt table */
|
||||||
|
@ -13,8 +13,7 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "sql_parse.h" // check_access,
|
#include "sql_parse.h" // check_access
|
||||||
// check_merge_table_access
|
|
||||||
#include "sql_table.h" // mysql_alter_table,
|
#include "sql_table.h" // mysql_alter_table,
|
||||||
// mysql_exchange_partition
|
// mysql_exchange_partition
|
||||||
#include "sql_alter.h"
|
#include "sql_alter.h"
|
||||||
@ -60,11 +59,15 @@ bool Alter_table_statement::execute(THD *thd)
|
|||||||
check_access(thd, INSERT_ACL | CREATE_ACL, select_lex->db,
|
check_access(thd, INSERT_ACL | CREATE_ACL, select_lex->db,
|
||||||
&priv,
|
&priv,
|
||||||
NULL, /* Don't use first_tab->grant with sel_lex->db */
|
NULL, /* Don't use first_tab->grant with sel_lex->db */
|
||||||
0, 0) ||
|
0, 0))
|
||||||
check_merge_table_access(thd, first_table->db,
|
|
||||||
create_info.merge_list.first))
|
|
||||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||||
|
|
||||||
|
/* If it is a merge table, check privileges for merge children. */
|
||||||
|
if (create_info.merge_list.first &&
|
||||||
|
check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
|
||||||
|
create_info.merge_list.first, FALSE, UINT_MAX, FALSE))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE))
|
if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE))
|
||||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||||
|
|
||||||
|
168
sql/sql_base.cc
168
sql/sql_base.cc
@ -100,14 +100,11 @@ bool No_such_table_error_handler::safely_trapped_errors()
|
|||||||
TABLE_SHAREs, refresh_version and the table id counter.
|
TABLE_SHAREs, refresh_version and the table id counter.
|
||||||
*/
|
*/
|
||||||
mysql_mutex_t LOCK_open;
|
mysql_mutex_t LOCK_open;
|
||||||
mysql_mutex_t LOCK_dd_owns_lock_open;
|
|
||||||
uint dd_owns_lock_open= 0;
|
|
||||||
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
#ifdef HAVE_PSI_INTERFACE
|
||||||
static PSI_mutex_key key_LOCK_open, key_LOCK_dd_owns_lock_open;
|
static PSI_mutex_key key_LOCK_open;
|
||||||
static PSI_mutex_info all_tdc_mutexes[]= {
|
static PSI_mutex_info all_tdc_mutexes[]= {
|
||||||
{ &key_LOCK_open, "LOCK_open", PSI_FLAG_GLOBAL },
|
{ &key_LOCK_open, "LOCK_open", PSI_FLAG_GLOBAL }
|
||||||
{ &key_LOCK_dd_owns_lock_open, "LOCK_dd_owns_lock_open", PSI_FLAG_GLOBAL }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -250,7 +247,8 @@ static void check_unused(void)
|
|||||||
Length of key
|
Length of key
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint create_table_def_key(THD *thd, char *key, TABLE_LIST *table_list,
|
uint create_table_def_key(THD *thd, char *key,
|
||||||
|
const TABLE_LIST *table_list,
|
||||||
bool tmp_table)
|
bool tmp_table)
|
||||||
{
|
{
|
||||||
uint key_length= (uint) (strmov(strmov(key, table_list->db)+1,
|
uint key_length= (uint) (strmov(strmov(key, table_list->db)+1,
|
||||||
@ -301,8 +299,6 @@ bool table_def_init(void)
|
|||||||
init_tdc_psi_keys();
|
init_tdc_psi_keys();
|
||||||
#endif
|
#endif
|
||||||
mysql_mutex_init(key_LOCK_open, &LOCK_open, MY_MUTEX_INIT_FAST);
|
mysql_mutex_init(key_LOCK_open, &LOCK_open, MY_MUTEX_INIT_FAST);
|
||||||
mysql_mutex_init(key_LOCK_dd_owns_lock_open, &LOCK_dd_owns_lock_open,
|
|
||||||
MY_MUTEX_INIT_FAST);
|
|
||||||
oldest_unused_share= &end_of_unused_share;
|
oldest_unused_share= &end_of_unused_share;
|
||||||
end_of_unused_share.prev= &oldest_unused_share;
|
end_of_unused_share.prev= &oldest_unused_share;
|
||||||
|
|
||||||
@ -346,7 +342,6 @@ void table_def_free(void)
|
|||||||
table_def_inited= 0;
|
table_def_inited= 0;
|
||||||
/* Free table definitions. */
|
/* Free table definitions. */
|
||||||
my_hash_free(&table_def_cache);
|
my_hash_free(&table_def_cache);
|
||||||
mysql_mutex_destroy(&LOCK_dd_owns_lock_open);
|
|
||||||
mysql_mutex_destroy(&LOCK_open);
|
mysql_mutex_destroy(&LOCK_open);
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -1993,39 +1988,60 @@ void update_non_unique_table_error(TABLE_LIST *update,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Find temporary table specified by database and table names in the
|
||||||
|
THD::temporary_tables list.
|
||||||
|
|
||||||
|
@return TABLE instance if a temporary table has been found; NULL otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name)
|
TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name)
|
||||||
{
|
{
|
||||||
TABLE_LIST table_list;
|
TABLE_LIST tl;
|
||||||
|
|
||||||
table_list.db= (char*) db;
|
tl.db= (char*) db;
|
||||||
table_list.table_name= (char*) table_name;
|
tl.table_name= (char*) table_name;
|
||||||
return find_temporary_table(thd, &table_list);
|
|
||||||
|
return find_temporary_table(thd, &tl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list)
|
/**
|
||||||
{
|
Find a temporary table specified by TABLE_LIST instance in the
|
||||||
char key[MAX_DBKEY_LENGTH];
|
THD::temporary_tables list.
|
||||||
uint key_length;
|
|
||||||
TABLE *table;
|
|
||||||
DBUG_ENTER("find_temporary_table");
|
|
||||||
DBUG_PRINT("enter", ("table: '%s'.'%s'",
|
|
||||||
table_list->db, table_list->table_name));
|
|
||||||
|
|
||||||
key_length= create_table_def_key(thd, key, table_list, 1);
|
@return TABLE instance if a temporary table has been found; NULL otherwise.
|
||||||
for (table=thd->temporary_tables ; table ; table= table->next)
|
*/
|
||||||
|
|
||||||
|
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl)
|
||||||
|
{
|
||||||
|
char key[MAX_DBKEY_LENGTH];
|
||||||
|
uint key_length= create_table_def_key(thd, key, tl, 1);
|
||||||
|
|
||||||
|
return find_temporary_table(thd, key, key_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Find a temporary table specified by a key in the THD::temporary_tables list.
|
||||||
|
|
||||||
|
@return TABLE instance if a temporary table has been found; NULL otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
TABLE *find_temporary_table(THD *thd,
|
||||||
|
const char *table_key,
|
||||||
|
uint table_key_length)
|
||||||
|
{
|
||||||
|
for (TABLE *table= thd->temporary_tables; table; table= table->next)
|
||||||
{
|
{
|
||||||
if (table->s->table_cache_key.length == key_length &&
|
if (table->s->table_cache_key.length == table_key_length &&
|
||||||
!memcmp(table->s->table_cache_key.str, key, key_length))
|
!memcmp(table->s->table_cache_key.str, table_key, table_key_length))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info",
|
return table;
|
||||||
("Found table. server_id: %u pseudo_thread_id: %lu",
|
|
||||||
(uint) thd->server_id,
|
|
||||||
(ulong) thd->variables.pseudo_thread_id));
|
|
||||||
DBUG_RETURN(table);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DBUG_RETURN(0); // Not a temporary table
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3029,41 +3045,11 @@ retry_share:
|
|||||||
table->reginfo.lock_type=TL_READ; /* Assume read */
|
table->reginfo.lock_type=TL_READ; /* Assume read */
|
||||||
|
|
||||||
reset:
|
reset:
|
||||||
DBUG_ASSERT(table->s->ref_count > 0 || table->s->tmp_table != NO_TMP_TABLE);
|
|
||||||
|
|
||||||
if (thd->lex->need_correct_ident())
|
|
||||||
table->alias_name_used= my_strcasecmp(table_alias_charset,
|
|
||||||
table->s->table_name.str, alias);
|
|
||||||
/* Fix alias if table name changes */
|
|
||||||
if (strcmp(table->alias, alias))
|
|
||||||
{
|
|
||||||
uint length=(uint) strlen(alias)+1;
|
|
||||||
table->alias= (char*) my_realloc((char*) table->alias, length,
|
|
||||||
MYF(MY_WME));
|
|
||||||
memcpy((char*) table->alias, alias, length);
|
|
||||||
}
|
|
||||||
table->tablenr=thd->current_tablenr++;
|
|
||||||
table->used_fields=0;
|
|
||||||
table->const_table=0;
|
|
||||||
table->null_row= table->maybe_null= 0;
|
|
||||||
table->force_index= table->force_index_order= table->force_index_group= 0;
|
|
||||||
table->status=STATUS_NO_RECORD;
|
|
||||||
table->insert_values= 0;
|
|
||||||
table->fulltext_searched= 0;
|
|
||||||
table->file->ft_handler= 0;
|
|
||||||
table->reginfo.impossible_range= 0;
|
|
||||||
/* Catch wrong handling of the auto_increment_field_not_null. */
|
|
||||||
DBUG_ASSERT(!table->auto_increment_field_not_null);
|
|
||||||
table->auto_increment_field_not_null= FALSE;
|
|
||||||
if (table->timestamp_field)
|
|
||||||
table->timestamp_field_type= table->timestamp_field->get_auto_set_type();
|
|
||||||
table->pos_in_table_list= table_list;
|
|
||||||
table_list->updatable= 1; // It is not derived table nor non-updatable VIEW
|
table_list->updatable= 1; // It is not derived table nor non-updatable VIEW
|
||||||
table->clear_column_bitmaps();
|
|
||||||
table_list->table= table;
|
table_list->table= table;
|
||||||
DBUG_ASSERT(table->key_read == 0);
|
|
||||||
/* Tables may be reused in a sub statement. */
|
table->init(thd, table_list);
|
||||||
DBUG_ASSERT(! table->file->extra(HA_EXTRA_IS_ATTACHED_CHILDREN));
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
err_lock:
|
err_lock:
|
||||||
@ -4536,13 +4522,15 @@ lock_table_names(THD *thd,
|
|||||||
! (flags & MYSQL_OPEN_SKIP_TEMPORARY) &&
|
! (flags & MYSQL_OPEN_SKIP_TEMPORARY) &&
|
||||||
find_temporary_table(thd, table))))
|
find_temporary_table(thd, table))))
|
||||||
{
|
{
|
||||||
if (schema_set.insert(table))
|
if (! (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK) &&
|
||||||
|
schema_set.insert(table))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
mdl_requests.push_front(&table->mdl_request);
|
mdl_requests.push_front(&table->mdl_request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! mdl_requests.is_empty())
|
if (! (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK) &&
|
||||||
|
! mdl_requests.is_empty())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Scoped locks: Take intention exclusive locks on all involved
|
Scoped locks: Take intention exclusive locks on all involved
|
||||||
@ -5177,6 +5165,8 @@ static bool check_lock_and_start_stmt(THD *thd,
|
|||||||
@param[in] lock_type lock to use for table
|
@param[in] lock_type lock to use for table
|
||||||
@param[in] flags options to be used while opening and locking
|
@param[in] flags options to be used while opening and locking
|
||||||
table (see open_table(), mysql_lock_tables())
|
table (see open_table(), mysql_lock_tables())
|
||||||
|
@param[in] prelocking_strategy Strategy which specifies how prelocking
|
||||||
|
algorithm should work for this statement.
|
||||||
|
|
||||||
@return table
|
@return table
|
||||||
@retval != NULL OK, opened table returned
|
@retval != NULL OK, opened table returned
|
||||||
@ -5202,7 +5192,8 @@ static bool check_lock_and_start_stmt(THD *thd,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
|
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
|
||||||
thr_lock_type lock_type, uint flags)
|
thr_lock_type lock_type, uint flags,
|
||||||
|
Prelocking_strategy *prelocking_strategy)
|
||||||
{
|
{
|
||||||
TABLE_LIST *save_next_global;
|
TABLE_LIST *save_next_global;
|
||||||
DBUG_ENTER("open_n_lock_single_table");
|
DBUG_ENTER("open_n_lock_single_table");
|
||||||
@ -5218,7 +5209,8 @@ TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
|
|||||||
table_l->required_type= FRMTYPE_TABLE;
|
table_l->required_type= FRMTYPE_TABLE;
|
||||||
|
|
||||||
/* Open the table. */
|
/* Open the table. */
|
||||||
if (open_and_lock_tables(thd, table_l, FALSE, flags))
|
if (open_and_lock_tables(thd, table_l, FALSE, flags,
|
||||||
|
prelocking_strategy))
|
||||||
table_l->table= NULL; /* Just to be sure. */
|
table_l->table= NULL; /* Just to be sure. */
|
||||||
|
|
||||||
/* Restore list. */
|
/* Restore list. */
|
||||||
@ -5710,35 +5702,37 @@ void close_tables_for_reopen(THD *thd, TABLE_LIST **tables,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Open a single table without table caching and don't set it in open_list
|
Open a single table without table caching and don't add it to
|
||||||
|
THD::open_tables. Depending on the 'add_to_temporary_tables_list' value,
|
||||||
|
the opened TABLE instance will be addded to THD::temporary_tables list.
|
||||||
|
|
||||||
SYNPOSIS
|
@param thd Thread context.
|
||||||
open_temporary_table()
|
@param path Path (without .frm)
|
||||||
thd Thread object
|
@param db Database name.
|
||||||
path Path (without .frm)
|
@param table_name Table name.
|
||||||
db database
|
@param add_to_temporary_tables_list Specifies if the opened TABLE
|
||||||
table_name Table name
|
instance should be linked into
|
||||||
link_in_list 1 if table should be linked into thd->temporary_tables
|
THD::temporary_tables list.
|
||||||
|
|
||||||
NOTES:
|
@note This function is used:
|
||||||
Used by alter_table to open a temporary table and when creating
|
- by alter_table() to open a temporary table;
|
||||||
a temporary table with CREATE TEMPORARY ...
|
- when creating a temporary table with CREATE TEMPORARY TABLE.
|
||||||
|
|
||||||
RETURN
|
@return TABLE instance for opened table.
|
||||||
0 Error
|
@retval NULL on error.
|
||||||
# TABLE object
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
|
TABLE *open_table_uncached(THD *thd, const char *path, const char *db,
|
||||||
const char *table_name, bool link_in_list)
|
const char *table_name,
|
||||||
|
bool add_to_temporary_tables_list)
|
||||||
{
|
{
|
||||||
TABLE *tmp_table;
|
TABLE *tmp_table;
|
||||||
TABLE_SHARE *share;
|
TABLE_SHARE *share;
|
||||||
char cache_key[MAX_DBKEY_LENGTH], *saved_cache_key, *tmp_path;
|
char cache_key[MAX_DBKEY_LENGTH], *saved_cache_key, *tmp_path;
|
||||||
uint key_length;
|
uint key_length;
|
||||||
TABLE_LIST table_list;
|
TABLE_LIST table_list;
|
||||||
DBUG_ENTER("open_temporary_table");
|
DBUG_ENTER("open_table_uncached");
|
||||||
DBUG_PRINT("enter",
|
DBUG_PRINT("enter",
|
||||||
("table: '%s'.'%s' path: '%s' server_id: %u "
|
("table: '%s'.'%s' path: '%s' server_id: %u "
|
||||||
"pseudo_thread_id: %lu",
|
"pseudo_thread_id: %lu",
|
||||||
@ -5781,7 +5775,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
|
|||||||
share->tmp_table= (tmp_table->file->has_transactions() ?
|
share->tmp_table= (tmp_table->file->has_transactions() ?
|
||||||
TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE);
|
TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE);
|
||||||
|
|
||||||
if (link_in_list)
|
if (add_to_temporary_tables_list)
|
||||||
{
|
{
|
||||||
/* growing temp list at the head */
|
/* growing temp list at the head */
|
||||||
tmp_table->next= thd->temporary_tables;
|
tmp_table->next= thd->temporary_tables;
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#define SQL_BASE_INCLUDED
|
#define SQL_BASE_INCLUDED
|
||||||
|
|
||||||
#include "unireg.h" // REQUIRED: for other includes
|
#include "unireg.h" // REQUIRED: for other includes
|
||||||
#include "table.h" /* open_table_mode */
|
|
||||||
#include "sql_trigger.h" /* trg_event_type */
|
#include "sql_trigger.h" /* trg_event_type */
|
||||||
#include "sql_class.h" /* enum_mark_columns */
|
#include "sql_class.h" /* enum_mark_columns */
|
||||||
#include "mysqld.h" /* key_map */
|
#include "mysqld.h" /* key_map */
|
||||||
@ -71,8 +70,6 @@ enum enum_tdc_remove_table_type {TDC_RT_REMOVE_ALL, TDC_RT_REMOVE_NOT_OWN,
|
|||||||
|
|
||||||
bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
|
bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
|
||||||
extern mysql_mutex_t LOCK_open;
|
extern mysql_mutex_t LOCK_open;
|
||||||
extern mysql_mutex_t LOCK_dd_owns_lock_open;
|
|
||||||
extern uint dd_owns_lock_open;
|
|
||||||
bool table_cache_init(void);
|
bool table_cache_init(void);
|
||||||
void table_cache_free(void);
|
void table_cache_free(void);
|
||||||
bool table_def_init(void);
|
bool table_def_init(void);
|
||||||
@ -81,7 +78,8 @@ void table_def_start_shutdown(void);
|
|||||||
void assign_new_table_id(TABLE_SHARE *share);
|
void assign_new_table_id(TABLE_SHARE *share);
|
||||||
uint cached_open_tables(void);
|
uint cached_open_tables(void);
|
||||||
uint cached_table_definitions(void);
|
uint cached_table_definitions(void);
|
||||||
uint create_table_def_key(THD *thd, char *key, TABLE_LIST *table_list,
|
uint create_table_def_key(THD *thd, char *key,
|
||||||
|
const TABLE_LIST *table_list,
|
||||||
bool tmp_table);
|
bool tmp_table);
|
||||||
TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
|
TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
|
||||||
uint key_length, uint db_flags, int *error,
|
uint key_length, uint db_flags, int *error,
|
||||||
@ -124,6 +122,11 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
|
|||||||
(LONG_TIMEOUT = 1 year) rather than the user-supplied timeout value.
|
(LONG_TIMEOUT = 1 year) rather than the user-supplied timeout value.
|
||||||
*/
|
*/
|
||||||
#define MYSQL_LOCK_IGNORE_TIMEOUT 0x0800
|
#define MYSQL_LOCK_IGNORE_TIMEOUT 0x0800
|
||||||
|
/**
|
||||||
|
When acquiring "strong" (SNW, SNRW, X) metadata locks on tables to
|
||||||
|
be open do not acquire global and schema-scope IX locks.
|
||||||
|
*/
|
||||||
|
#define MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK 0x1000
|
||||||
|
|
||||||
/** Please refer to the internals manual. */
|
/** Please refer to the internals manual. */
|
||||||
#define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\
|
#define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\
|
||||||
@ -143,8 +146,9 @@ bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias,
|
|||||||
|
|
||||||
bool get_key_map_from_key_list(key_map *map, TABLE *table,
|
bool get_key_map_from_key_list(key_map *map, TABLE *table,
|
||||||
List<String> *index_list);
|
List<String> *index_list);
|
||||||
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
|
TABLE *open_table_uncached(THD *thd, const char *path, const char *db,
|
||||||
const char *table_name, bool link_in_list);
|
const char *table_name,
|
||||||
|
bool add_to_temporary_tables_list);
|
||||||
TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name);
|
TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name);
|
||||||
TABLE *find_write_locked_table(TABLE *list, const char *db,
|
TABLE *find_write_locked_table(TABLE *list, const char *db,
|
||||||
const char *table_name);
|
const char *table_name);
|
||||||
@ -161,7 +165,9 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
|
|||||||
const char *db_name,
|
const char *db_name,
|
||||||
const char *table_name);
|
const char *table_name);
|
||||||
TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name);
|
TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name);
|
||||||
TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list);
|
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
|
||||||
|
TABLE *find_temporary_table(THD *thd, const char *table_key,
|
||||||
|
uint table_key_length);
|
||||||
void close_thread_tables(THD *thd);
|
void close_thread_tables(THD *thd);
|
||||||
bool fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
|
bool fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
|
||||||
List<Item> &values,
|
List<Item> &values,
|
||||||
@ -240,7 +246,8 @@ bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
|
|||||||
int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived);
|
int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived);
|
||||||
/* simple open_and_lock_tables without derived handling for single table */
|
/* simple open_and_lock_tables without derived handling for single table */
|
||||||
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
|
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
|
||||||
thr_lock_type lock_type, uint flags);
|
thr_lock_type lock_type, uint flags,
|
||||||
|
Prelocking_strategy *prelocking_strategy);
|
||||||
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags);
|
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags);
|
||||||
bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
|
bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
|
||||||
int decide_logging_format(THD *thd, TABLE_LIST *tables);
|
int decide_logging_format(THD *thd, TABLE_LIST *tables);
|
||||||
@ -449,6 +456,16 @@ open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
|
||||||
|
thr_lock_type lock_type, uint flags)
|
||||||
|
{
|
||||||
|
DML_prelocking_strategy prelocking_strategy;
|
||||||
|
|
||||||
|
return open_n_lock_single_table(thd, table_l, lock_type, flags,
|
||||||
|
&prelocking_strategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* open_and_lock_tables with derived handling */
|
/* open_and_lock_tables with derived handling */
|
||||||
inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
|
inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
|
||||||
bool derived, uint flags)
|
bool derived, uint flags)
|
||||||
|
@ -634,14 +634,12 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list)
|
|||||||
static int
|
static int
|
||||||
create_insert_stmt_from_insert_delayed(THD *thd, String *buf)
|
create_insert_stmt_from_insert_delayed(THD *thd, String *buf)
|
||||||
{
|
{
|
||||||
/* Append the part of thd->query before "DELAYED" keyword */
|
/* Make a copy of thd->query() and then remove the "DELAYED" keyword */
|
||||||
if (buf->append(thd->query(),
|
if (buf->append(thd->query()) ||
|
||||||
thd->lex->keyword_delayed_begin - thd->query()))
|
buf->replace(thd->lex->keyword_delayed_begin_offset,
|
||||||
|
thd->lex->keyword_delayed_end_offset -
|
||||||
|
thd->lex->keyword_delayed_begin_offset, 0))
|
||||||
return 1;
|
return 1;
|
||||||
/* Append the part of thd->query after "DELAYED" keyword */
|
|
||||||
if (buf->append(thd->lex->keyword_delayed_begin + 7))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2495,6 +2493,65 @@ void kill_delayed_threads(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
A strategy for the prelocking algorithm which prevents the
|
||||||
|
delayed insert thread from opening tables with engines which
|
||||||
|
do not support delayed inserts.
|
||||||
|
|
||||||
|
Particularly it allows to abort open_tables() as soon as we
|
||||||
|
discover that we have opened a MERGE table, without acquiring
|
||||||
|
metadata locks on underlying tables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Delayed_prelocking_strategy : public Prelocking_strategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
|
||||||
|
Sroutine_hash_entry *rt, sp_head *sp,
|
||||||
|
bool *need_prelocking);
|
||||||
|
virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
|
||||||
|
TABLE_LIST *table_list, bool *need_prelocking);
|
||||||
|
virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx,
|
||||||
|
TABLE_LIST *table_list, bool *need_prelocking);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool Delayed_prelocking_strategy::
|
||||||
|
handle_table(THD *thd, Query_tables_list *prelocking_ctx,
|
||||||
|
TABLE_LIST *table_list, bool *need_prelocking)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(table_list->lock_type == TL_WRITE_DELAYED);
|
||||||
|
|
||||||
|
if (!(table_list->table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED))
|
||||||
|
{
|
||||||
|
my_error(ER_DELAYED_NOT_SUPPORTED, MYF(0), table_list->table_name);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Delayed_prelocking_strategy::
|
||||||
|
handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
|
||||||
|
Sroutine_hash_entry *rt, sp_head *sp,
|
||||||
|
bool *need_prelocking)
|
||||||
|
{
|
||||||
|
/* LEX used by the delayed insert thread has no routines. */
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Delayed_prelocking_strategy::
|
||||||
|
handle_view(THD *thd, Query_tables_list *prelocking_ctx,
|
||||||
|
TABLE_LIST *table_list, bool *need_prelocking)
|
||||||
|
{
|
||||||
|
/* We don't open views in the delayed insert thread. */
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Open and lock table for use by delayed thread and check that
|
Open and lock table for use by delayed thread and check that
|
||||||
this table is suitable for delayed inserts.
|
this table is suitable for delayed inserts.
|
||||||
@ -2505,21 +2562,21 @@ void kill_delayed_threads(void)
|
|||||||
|
|
||||||
bool Delayed_insert::open_and_lock_table()
|
bool Delayed_insert::open_and_lock_table()
|
||||||
{
|
{
|
||||||
|
Delayed_prelocking_strategy prelocking_strategy;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Use special prelocking strategy to get ER_DELAYED_NOT_SUPPORTED
|
||||||
|
error for tables with engines which don't support delayed inserts.
|
||||||
|
*/
|
||||||
if (!(table= open_n_lock_single_table(&thd, &table_list,
|
if (!(table= open_n_lock_single_table(&thd, &table_list,
|
||||||
TL_WRITE_DELAYED,
|
TL_WRITE_DELAYED,
|
||||||
MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK)))
|
MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK,
|
||||||
|
&prelocking_strategy)))
|
||||||
{
|
{
|
||||||
thd.fatal_error(); // Abort waiting inserts
|
thd.fatal_error(); // Abort waiting inserts
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (!(table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED))
|
|
||||||
{
|
|
||||||
/* To rollback InnoDB statement transaction. */
|
|
||||||
trans_rollback_stmt(&thd);
|
|
||||||
my_error(ER_DELAYED_NOT_SUPPORTED, MYF(ME_FATALERROR),
|
|
||||||
table_list.table_name);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
if (table->triggers)
|
if (table->triggers)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -2355,15 +2355,19 @@ struct LEX: public Query_tables_list
|
|||||||
This pointer is required to add possibly omitted DEFINER-clause to the
|
This pointer is required to add possibly omitted DEFINER-clause to the
|
||||||
DDL-statement before dumping it to the binlog.
|
DDL-statement before dumping it to the binlog.
|
||||||
|
|
||||||
keyword_delayed_begin points to the begin of the DELAYED keyword in
|
keyword_delayed_begin_offset is the offset to the beginning of the DELAYED
|
||||||
INSERT DELAYED statement.
|
keyword in INSERT DELAYED statement. keyword_delayed_end_offset is the
|
||||||
|
offset to the character right after the DELAYED keyword.
|
||||||
*/
|
*/
|
||||||
union {
|
union {
|
||||||
const char *stmt_definition_begin;
|
const char *stmt_definition_begin;
|
||||||
const char *keyword_delayed_begin;
|
uint keyword_delayed_begin_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *stmt_definition_end;
|
union {
|
||||||
|
const char *stmt_definition_end;
|
||||||
|
uint keyword_delayed_end_offset;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
During name resolution search only in the table list given by
|
During name resolution search only in the table list given by
|
||||||
|
@ -177,8 +177,7 @@ static bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables)
|
|||||||
for (TABLE_LIST *table= tables; table; table= table->next_global)
|
for (TABLE_LIST *table= tables; table; table= table->next_global)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(table->db && table->table_name);
|
DBUG_ASSERT(table->db && table->table_name);
|
||||||
if (table->updating &&
|
if (table->updating && !find_temporary_table(thd, table))
|
||||||
!find_temporary_table(thd, table->db, table->table_name))
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -402,6 +401,7 @@ void init_update_queries(void)
|
|||||||
sql_command_flags[SQLCOM_REPAIR]= CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_REPAIR]= CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
|
||||||
sql_command_flags[SQLCOM_OPTIMIZE]|= CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_OPTIMIZE]|= CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
|
||||||
sql_command_flags[SQLCOM_ANALYZE]= CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_ANALYZE]= CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
|
||||||
|
sql_command_flags[SQLCOM_CHECK]= CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
|
||||||
|
|
||||||
sql_command_flags[SQLCOM_CREATE_USER]|= CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_CREATE_USER]|= CF_AUTO_COMMIT_TRANS;
|
||||||
sql_command_flags[SQLCOM_DROP_USER]|= CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_DROP_USER]|= CF_AUTO_COMMIT_TRANS;
|
||||||
@ -415,7 +415,6 @@ void init_update_queries(void)
|
|||||||
|
|
||||||
sql_command_flags[SQLCOM_FLUSH]= CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_FLUSH]= CF_AUTO_COMMIT_TRANS;
|
||||||
sql_command_flags[SQLCOM_RESET]= CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_RESET]= CF_AUTO_COMMIT_TRANS;
|
||||||
sql_command_flags[SQLCOM_CHECK]= CF_AUTO_COMMIT_TRANS;
|
|
||||||
sql_command_flags[SQLCOM_CREATE_SERVER]= CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_CREATE_SERVER]= CF_AUTO_COMMIT_TRANS;
|
||||||
sql_command_flags[SQLCOM_ALTER_SERVER]= CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_ALTER_SERVER]= CF_AUTO_COMMIT_TRANS;
|
||||||
sql_command_flags[SQLCOM_DROP_SERVER]= CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_DROP_SERVER]= CF_AUTO_COMMIT_TRANS;
|
||||||
@ -643,45 +642,6 @@ end:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief Check access privs for a MERGE table and fix children lock types.
|
|
||||||
|
|
||||||
@param[in] thd thread handle
|
|
||||||
@param[in] db database name
|
|
||||||
@param[in,out] table_list list of child tables (merge_list)
|
|
||||||
lock_type and optionally db set per table
|
|
||||||
|
|
||||||
@return status
|
|
||||||
@retval 0 OK
|
|
||||||
@retval != 0 Error
|
|
||||||
|
|
||||||
@detail
|
|
||||||
This function is used for write access to MERGE tables only
|
|
||||||
(CREATE TABLE, ALTER TABLE ... UNION=(...)). Set TL_WRITE for
|
|
||||||
every child. Set 'db' for every child if not present.
|
|
||||||
*/
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
||||||
bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list)
|
|
||||||
{
|
|
||||||
int error= 0;
|
|
||||||
|
|
||||||
if (table_list)
|
|
||||||
{
|
|
||||||
/* Check that all tables use the current database */
|
|
||||||
TABLE_LIST *tlist;
|
|
||||||
|
|
||||||
for (tlist= table_list; tlist; tlist= tlist->next_local)
|
|
||||||
{
|
|
||||||
if (!tlist->db || !tlist->db[0])
|
|
||||||
tlist->db= db; /* purecov: inspected */
|
|
||||||
}
|
|
||||||
error= check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
|
|
||||||
table_list, FALSE, UINT_MAX, FALSE);
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* This works because items are allocated with sql_alloc() */
|
/* This works because items are allocated with sql_alloc() */
|
||||||
|
|
||||||
void free_items(Item *item)
|
void free_items(Item *item)
|
||||||
@ -6964,10 +6924,16 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
|||||||
if (check_access(thd, want_priv, create_table->db,
|
if (check_access(thd, want_priv, create_table->db,
|
||||||
&create_table->grant.privilege,
|
&create_table->grant.privilege,
|
||||||
&create_table->grant.m_internal,
|
&create_table->grant.m_internal,
|
||||||
0, 0) ||
|
0, 0))
|
||||||
check_merge_table_access(thd, create_table->db,
|
|
||||||
lex->create_info.merge_list.first))
|
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
/* If it is a merge table, check privileges for merge children. */
|
||||||
|
if (lex->create_info.merge_list.first &&
|
||||||
|
check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
|
||||||
|
lex->create_info.merge_list.first,
|
||||||
|
FALSE, UINT_MAX, FALSE))
|
||||||
|
goto err;
|
||||||
|
|
||||||
if (want_priv != CREATE_TMP_ACL &&
|
if (want_priv != CREATE_TMP_ACL &&
|
||||||
check_grant(thd, want_priv, create_table, FALSE, 1, FALSE))
|
check_grant(thd, want_priv, create_table, FALSE, 1, FALSE))
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -153,7 +153,6 @@ bool check_single_table_access(THD *thd, ulong privilege,
|
|||||||
bool check_routine_access(THD *thd,ulong want_access,char *db,char *name,
|
bool check_routine_access(THD *thd,ulong want_access,char *db,char *name,
|
||||||
bool is_proc, bool no_errors);
|
bool is_proc, bool no_errors);
|
||||||
bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table);
|
bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table);
|
||||||
bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list);
|
|
||||||
bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc);
|
bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc);
|
||||||
bool check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
|
bool check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
|
||||||
GRANT_INTERNAL_INFO *grant_internal_info,
|
GRANT_INTERNAL_INFO *grant_internal_info,
|
||||||
@ -176,8 +175,6 @@ inline bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table)
|
|||||||
table->grant.privilege= want_access;
|
table->grant.privilege= want_access;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
inline bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list)
|
|
||||||
{ return false; }
|
|
||||||
inline bool check_some_routine_access(THD *thd, const char *db,
|
inline bool check_some_routine_access(THD *thd, const char *db,
|
||||||
const char *name, bool is_proc)
|
const char *name, bool is_proc)
|
||||||
{ return false; }
|
{ return false; }
|
||||||
|
@ -328,7 +328,6 @@ bool reload_acl_and_cache(THD *thd, unsigned long options,
|
|||||||
-------------------------------------
|
-------------------------------------
|
||||||
- you can't flush WITH READ LOCK a non-existent table
|
- you can't flush WITH READ LOCK a non-existent table
|
||||||
- you can't flush WITH READ LOCK under LOCK TABLES
|
- you can't flush WITH READ LOCK under LOCK TABLES
|
||||||
- currently incompatible with the GRL (@todo: fix)
|
|
||||||
|
|
||||||
Effect on views and temporary tables.
|
Effect on views and temporary tables.
|
||||||
------------------------------------
|
------------------------------------
|
||||||
@ -338,6 +337,13 @@ bool reload_acl_and_cache(THD *thd, unsigned long options,
|
|||||||
if there is a base table, it's used, otherwise ER_NO_SUCH_TABLE
|
if there is a base table, it's used, otherwise ER_NO_SUCH_TABLE
|
||||||
is returned.
|
is returned.
|
||||||
|
|
||||||
|
Handling of MERGE tables
|
||||||
|
------------------------
|
||||||
|
For MERGE table this statement will open and lock child tables
|
||||||
|
for read (it is impossible to lock parent table without it).
|
||||||
|
Child tables won't be flushed unless they are explicitly present
|
||||||
|
in the statement's table list.
|
||||||
|
|
||||||
Implicit commit
|
Implicit commit
|
||||||
---------------
|
---------------
|
||||||
This statement causes an implicit commit before and
|
This statement causes an implicit commit before and
|
||||||
@ -354,7 +360,6 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
|
|||||||
{
|
{
|
||||||
Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
|
Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
|
||||||
TABLE_LIST *table_list;
|
TABLE_LIST *table_list;
|
||||||
MDL_request_list mdl_requests;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is called from SQLCOM_FLUSH, the transaction has
|
This is called from SQLCOM_FLUSH, the transaction has
|
||||||
@ -368,17 +373,13 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Acquire SNW locks on tables to be flushed. We can't use
|
Acquire SNW locks on tables to be flushed. Don't acquire global
|
||||||
lock_table_names() here as this call will also acquire global IX
|
IX and database-scope IX locks on the tables as this will make
|
||||||
and database-scope IX locks on the tables, and this will make
|
|
||||||
this statement incompatible with FLUSH TABLES WITH READ LOCK.
|
this statement incompatible with FLUSH TABLES WITH READ LOCK.
|
||||||
*/
|
*/
|
||||||
for (table_list= all_tables; table_list;
|
if (lock_table_names(thd, all_tables, NULL,
|
||||||
table_list= table_list->next_global)
|
thd->variables.lock_wait_timeout,
|
||||||
mdl_requests.push_front(&table_list->mdl_request);
|
MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK))
|
||||||
|
|
||||||
if (thd->mdl_context.acquire_locks(&mdl_requests,
|
|
||||||
thd->variables.lock_wait_timeout))
|
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
DEBUG_SYNC(thd,"flush_tables_with_read_lock_after_acquire_locks");
|
DEBUG_SYNC(thd,"flush_tables_with_read_lock_after_acquire_locks");
|
||||||
@ -390,21 +391,24 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
|
|||||||
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
|
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
|
||||||
table_list->db,
|
table_list->db,
|
||||||
table_list->table_name, FALSE);
|
table_list->table_name, FALSE);
|
||||||
|
/* Reset ticket to satisfy asserts in open_tables(). */
|
||||||
/* Skip views and temporary tables. */
|
table_list->mdl_request.ticket= NULL;
|
||||||
table_list->required_type= FRMTYPE_TABLE; /* Don't try to flush views. */
|
|
||||||
table_list->open_type= OT_BASE_ONLY; /* Ignore temporary tables. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Before opening and locking tables the below call also waits
|
Before opening and locking tables the below call also waits
|
||||||
for old shares to go away, so the fact that we don't pass
|
for old shares to go away, so the fact that we don't pass
|
||||||
MYSQL_LOCK_IGNORE_FLUSH flag to it is important.
|
MYSQL_LOCK_IGNORE_FLUSH flag to it is important.
|
||||||
|
Also we don't pass MYSQL_OPEN_HAS_MDL_LOCK flag as we want
|
||||||
|
to open underlying tables if merge table is flushed.
|
||||||
|
For underlying tables of the merge the below call has to
|
||||||
|
acquire SNW locks to ensure that they can be locked for
|
||||||
|
read without further waiting.
|
||||||
*/
|
*/
|
||||||
if (open_and_lock_tables(thd, all_tables, FALSE,
|
if (open_and_lock_tables(thd, all_tables, FALSE,
|
||||||
MYSQL_OPEN_HAS_MDL_LOCK,
|
MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK,
|
||||||
&lock_tables_prelocking_strategy) ||
|
&lock_tables_prelocking_strategy) ||
|
||||||
thd->locked_tables_list.init_locked_tables(thd))
|
thd->locked_tables_list.init_locked_tables(thd))
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -285,6 +285,7 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
|
|||||||
{
|
{
|
||||||
if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db,
|
if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db,
|
||||||
old_alias,
|
old_alias,
|
||||||
|
ren_table->table_name,
|
||||||
new_db,
|
new_db,
|
||||||
new_alias)))
|
new_alias)))
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "sql_rename.h" // do_rename
|
#include "sql_rename.h" // do_rename
|
||||||
#include "sql_parse.h" // test_if_data_home_dir
|
#include "sql_parse.h" // test_if_data_home_dir
|
||||||
#include "sql_cache.h" // query_cache_*
|
#include "sql_cache.h" // query_cache_*
|
||||||
#include "sql_base.h" // open_temporary_table, lock_table_names
|
#include "sql_base.h" // open_table_uncached, lock_table_names
|
||||||
#include "lock.h" // wait_if_global_read_lock
|
#include "lock.h" // wait_if_global_read_lock
|
||||||
// start_waiting_global_read_lock,
|
// start_waiting_global_read_lock,
|
||||||
// mysql_unlock_tables
|
// mysql_unlock_tables
|
||||||
@ -2008,7 +2008,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
|||||||
{
|
{
|
||||||
for (table= tables; table; table= table->next_local)
|
for (table= tables; table; table= table->next_local)
|
||||||
if (table->open_type != OT_BASE_ONLY &&
|
if (table->open_type != OT_BASE_ONLY &&
|
||||||
find_temporary_table(thd, table->db, table->table_name))
|
find_temporary_table(thd, table))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
A temporary table.
|
A temporary table.
|
||||||
@ -4225,9 +4225,14 @@ bool mysql_create_table_no_lock(THD *thd,
|
|||||||
|
|
||||||
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
||||||
{
|
{
|
||||||
TABLE *table= NULL;
|
/*
|
||||||
/* Open table and put in temporary table list */
|
Open a table (skipping table cache) and add it into
|
||||||
if (!(table= open_temporary_table(thd, path, db, table_name, 1)))
|
THD::temporary_tables list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
TABLE *table= open_table_uncached(thd, path, db, table_name, TRUE);
|
||||||
|
|
||||||
|
if (!table)
|
||||||
{
|
{
|
||||||
(void) rm_temporary_table(create_info->db_type, path);
|
(void) rm_temporary_table(create_info->db_type, path);
|
||||||
goto err;
|
goto err;
|
||||||
@ -5914,7 +5919,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
*fn_ext(new_name)=0;
|
*fn_ext(new_name)=0;
|
||||||
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
|
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
|
||||||
error= -1;
|
error= -1;
|
||||||
else if (Table_triggers_list::change_table_name(thd, db, table_name,
|
else if (Table_triggers_list::change_table_name(thd, db,
|
||||||
|
alias, table_name,
|
||||||
new_db, new_alias))
|
new_db, new_alias))
|
||||||
{
|
{
|
||||||
(void) mysql_rename_table(old_db_type, new_db, new_alias, db,
|
(void) mysql_rename_table(old_db_type, new_db, new_alias, db,
|
||||||
@ -6302,8 +6308,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
/* table is a normal table: Create temporary table in same directory */
|
/* table is a normal table: Create temporary table in same directory */
|
||||||
build_table_filename(path, sizeof(path) - 1, new_db, tmp_name, "",
|
build_table_filename(path, sizeof(path) - 1, new_db, tmp_name, "",
|
||||||
FN_IS_TMP);
|
FN_IS_TMP);
|
||||||
/* Open our intermediate table */
|
/* Open our intermediate table. */
|
||||||
new_table= open_temporary_table(thd, path, new_db, tmp_name, 1);
|
new_table= open_table_uncached(thd, path, new_db, tmp_name, TRUE);
|
||||||
}
|
}
|
||||||
if (!new_table)
|
if (!new_table)
|
||||||
goto err_new_table_cleanup;
|
goto err_new_table_cleanup;
|
||||||
@ -6551,7 +6557,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
(need_copy_table != ALTER_TABLE_METADATA_ONLY ||
|
(need_copy_table != ALTER_TABLE_METADATA_ONLY ||
|
||||||
mysql_rename_table(save_old_db_type, db, table_name, new_db,
|
mysql_rename_table(save_old_db_type, db, table_name, new_db,
|
||||||
new_alias, NO_FRM_RENAME)) &&
|
new_alias, NO_FRM_RENAME)) &&
|
||||||
Table_triggers_list::change_table_name(thd, db, table_name,
|
Table_triggers_list::change_table_name(thd, db, alias, table_name,
|
||||||
new_db, new_alias)))
|
new_db, new_alias)))
|
||||||
{
|
{
|
||||||
/* Try to get everything back. */
|
/* Try to get everything back. */
|
||||||
@ -6643,7 +6649,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
char path[FN_REFLEN];
|
char path[FN_REFLEN];
|
||||||
TABLE *t_table;
|
TABLE *t_table;
|
||||||
build_table_filename(path + 1, sizeof(path) - 1, new_db, table_name, "", 0);
|
build_table_filename(path + 1, sizeof(path) - 1, new_db, table_name, "", 0);
|
||||||
t_table= open_temporary_table(thd, path, new_db, tmp_name, 0);
|
t_table= open_table_uncached(thd, path, new_db, tmp_name, FALSE);
|
||||||
if (t_table)
|
if (t_table)
|
||||||
{
|
{
|
||||||
intern_close_table(t_table);
|
intern_close_table(t_table);
|
||||||
|
@ -458,7 +458,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
|||||||
DBUG_ASSERT(tables->next_global == 0);
|
DBUG_ASSERT(tables->next_global == 0);
|
||||||
|
|
||||||
/* We do not allow creation of triggers on temporary tables. */
|
/* We do not allow creation of triggers on temporary tables. */
|
||||||
if (create && find_temporary_table(thd, tables->db, tables->table_name))
|
if (create && find_temporary_table(thd, tables))
|
||||||
{
|
{
|
||||||
my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
|
my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
|
||||||
goto end;
|
goto end;
|
||||||
@ -1874,6 +1874,7 @@ Table_triggers_list::change_table_name_in_trignames(const char *old_db_name,
|
|||||||
|
|
||||||
@param[in,out] thd Thread context
|
@param[in,out] thd Thread context
|
||||||
@param[in] db Old database of subject table
|
@param[in] db Old database of subject table
|
||||||
|
@param[in] old_alias Old alias of subject table
|
||||||
@param[in] old_table Old name of subject table
|
@param[in] old_table Old name of subject table
|
||||||
@param[in] new_db New database for subject table
|
@param[in] new_db New database for subject table
|
||||||
@param[in] new_table New name of subject table
|
@param[in] new_table New name of subject table
|
||||||
@ -1890,6 +1891,7 @@ Table_triggers_list::change_table_name_in_trignames(const char *old_db_name,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
bool Table_triggers_list::change_table_name(THD *thd, const char *db,
|
bool Table_triggers_list::change_table_name(THD *thd, const char *db,
|
||||||
|
const char *old_alias,
|
||||||
const char *old_table,
|
const char *old_table,
|
||||||
const char *new_db,
|
const char *new_db,
|
||||||
const char *new_table)
|
const char *new_table)
|
||||||
@ -1911,7 +1913,7 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db,
|
|||||||
MDL_EXCLUSIVE));
|
MDL_EXCLUSIVE));
|
||||||
|
|
||||||
DBUG_ASSERT(my_strcasecmp(table_alias_charset, db, new_db) ||
|
DBUG_ASSERT(my_strcasecmp(table_alias_charset, db, new_db) ||
|
||||||
my_strcasecmp(table_alias_charset, old_table, new_table));
|
my_strcasecmp(table_alias_charset, old_alias, new_table));
|
||||||
|
|
||||||
if (Table_triggers_list::check_n_load(thd, db, old_table, &table, TRUE))
|
if (Table_triggers_list::check_n_load(thd, db, old_table, &table, TRUE))
|
||||||
{
|
{
|
||||||
@ -1920,7 +1922,7 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db,
|
|||||||
}
|
}
|
||||||
if (table.triggers)
|
if (table.triggers)
|
||||||
{
|
{
|
||||||
LEX_STRING old_table_name= { (char *) old_table, strlen(old_table) };
|
LEX_STRING old_table_name= { (char *) old_alias, strlen(old_alias) };
|
||||||
LEX_STRING new_table_name= { (char *) new_table, strlen(new_table) };
|
LEX_STRING new_table_name= { (char *) new_table, strlen(new_table) };
|
||||||
/*
|
/*
|
||||||
Since triggers should be in the same schema as their subject tables
|
Since triggers should be in the same schema as their subject tables
|
||||||
|
@ -157,6 +157,7 @@ public:
|
|||||||
TABLE *table, bool names_only);
|
TABLE *table, bool names_only);
|
||||||
static bool drop_all_triggers(THD *thd, char *db, char *table_name);
|
static bool drop_all_triggers(THD *thd, char *db, char *table_name);
|
||||||
static bool change_table_name(THD *thd, const char *db,
|
static bool change_table_name(THD *thd, const char *db,
|
||||||
|
const char *old_alias,
|
||||||
const char *old_table,
|
const char *old_table,
|
||||||
const char *new_db,
|
const char *new_db,
|
||||||
const char *new_table);
|
const char *new_table);
|
||||||
|
@ -208,8 +208,8 @@ static bool recreate_temporary_table(THD *thd, TABLE *table)
|
|||||||
ha_create_table(thd, share->normalized_path.str, share->db.str,
|
ha_create_table(thd, share->normalized_path.str, share->db.str,
|
||||||
share->table_name.str, &create_info, 1);
|
share->table_name.str, &create_info, 1);
|
||||||
|
|
||||||
if (open_temporary_table(thd, share->path.str, share->db.str,
|
if (open_table_uncached(thd, share->path.str, share->db.str,
|
||||||
share->table_name.str, 1))
|
share->table_name.str, TRUE))
|
||||||
{
|
{
|
||||||
error= FALSE;
|
error= FALSE;
|
||||||
thd->thread_specific_used= TRUE;
|
thd->thread_specific_used= TRUE;
|
||||||
|
@ -10447,7 +10447,10 @@ insert_lock_option:
|
|||||||
| LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
|
| LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
|
||||||
| DELAYED_SYM
|
| DELAYED_SYM
|
||||||
{
|
{
|
||||||
Lex->keyword_delayed_begin= YYLIP->get_tok_start();
|
Lex->keyword_delayed_begin_offset= (uint)(YYLIP->get_tok_start() -
|
||||||
|
YYTHD->query());
|
||||||
|
Lex->keyword_delayed_end_offset= Lex->keyword_delayed_begin_offset +
|
||||||
|
YYLIP->yyLength() + 1;
|
||||||
$$= TL_WRITE_DELAYED;
|
$$= TL_WRITE_DELAYED;
|
||||||
}
|
}
|
||||||
| HIGH_PRIORITY { $$= TL_WRITE; }
|
| HIGH_PRIORITY { $$= TL_WRITE; }
|
||||||
@ -10457,7 +10460,10 @@ replace_lock_option:
|
|||||||
opt_low_priority { $$= $1; }
|
opt_low_priority { $$= $1; }
|
||||||
| DELAYED_SYM
|
| DELAYED_SYM
|
||||||
{
|
{
|
||||||
Lex->keyword_delayed_begin= YYLIP->get_tok_start();
|
Lex->keyword_delayed_begin_offset= (uint)(YYLIP->get_tok_start() -
|
||||||
|
YYTHD->query());
|
||||||
|
Lex->keyword_delayed_end_offset= Lex->keyword_delayed_begin_offset +
|
||||||
|
YYLIP->yyLength() + 1;
|
||||||
$$= TL_WRITE_DELAYED;
|
$$= TL_WRITE_DELAYED;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -11278,7 +11284,11 @@ opt_with_read_lock:
|
|||||||
TABLE_LIST *tables= Lex->query_tables;
|
TABLE_LIST *tables= Lex->query_tables;
|
||||||
Lex->type|= REFRESH_READ_LOCK;
|
Lex->type|= REFRESH_READ_LOCK;
|
||||||
for (; tables; tables= tables->next_global)
|
for (; tables; tables= tables->next_global)
|
||||||
|
{
|
||||||
tables->mdl_request.set_type(MDL_SHARED_NO_WRITE);
|
tables->mdl_request.set_type(MDL_SHARED_NO_WRITE);
|
||||||
|
tables->required_type= FRMTYPE_TABLE; /* Don't try to flush views. */
|
||||||
|
tables->open_type= OT_BASE_ONLY; /* Ignore temporary tables. */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -13241,6 +13251,13 @@ handler:
|
|||||||
handler_read_or_scan where_clause opt_limit_clause
|
handler_read_or_scan where_clause opt_limit_clause
|
||||||
{
|
{
|
||||||
Lex->expr_allows_subselect= TRUE;
|
Lex->expr_allows_subselect= TRUE;
|
||||||
|
/* Stored functions are not supported for HANDLER READ. */
|
||||||
|
if (Lex->uses_stored_routines())
|
||||||
|
{
|
||||||
|
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
|
||||||
|
"stored functions in HANDLER ... READ");
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
92
sql/table.cc
92
sql/table.cc
@ -3085,30 +3085,7 @@ bool TABLE_SHARE::visit_subgraph(Wait_for_flush *wait_for_flush,
|
|||||||
holding a write-lock on MDL_lock::m_rwlock.
|
holding a write-lock on MDL_lock::m_rwlock.
|
||||||
*/
|
*/
|
||||||
if (gvisitor->m_lock_open_count++ == 0)
|
if (gvisitor->m_lock_open_count++ == 0)
|
||||||
{
|
|
||||||
/*
|
|
||||||
To circumvent bug #56405 "Deadlock in the MDL deadlock detector"
|
|
||||||
we don't try to lock LOCK_open mutex if some thread doing
|
|
||||||
deadlock detection already owns it and current search depth is
|
|
||||||
greater than 0. Instead we report a deadlock.
|
|
||||||
|
|
||||||
TODO/FIXME: The proper fix for this bug is to use rwlocks for
|
|
||||||
protection of table shares/instead of LOCK_open.
|
|
||||||
Unfortunately it requires more effort/has significant
|
|
||||||
performance effect.
|
|
||||||
*/
|
|
||||||
mysql_mutex_lock(&LOCK_dd_owns_lock_open);
|
|
||||||
if (gvisitor->m_current_search_depth > 0 && dd_owns_lock_open > 0)
|
|
||||||
{
|
|
||||||
mysql_mutex_unlock(&LOCK_dd_owns_lock_open);
|
|
||||||
--gvisitor->m_lock_open_count;
|
|
||||||
gvisitor->abort_traversal(src_ctx);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
++dd_owns_lock_open;
|
|
||||||
mysql_mutex_unlock(&LOCK_dd_owns_lock_open);
|
|
||||||
mysql_mutex_lock(&LOCK_open);
|
mysql_mutex_lock(&LOCK_open);
|
||||||
}
|
|
||||||
|
|
||||||
I_P_List_iterator <TABLE, TABLE_share> tables_it(used_tables);
|
I_P_List_iterator <TABLE, TABLE_share> tables_it(used_tables);
|
||||||
|
|
||||||
@ -3123,12 +3100,8 @@ bool TABLE_SHARE::visit_subgraph(Wait_for_flush *wait_for_flush,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
++gvisitor->m_current_search_depth;
|
|
||||||
if (gvisitor->enter_node(src_ctx))
|
if (gvisitor->enter_node(src_ctx))
|
||||||
{
|
|
||||||
--gvisitor->m_current_search_depth;
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
|
||||||
|
|
||||||
while ((table= tables_it++))
|
while ((table= tables_it++))
|
||||||
{
|
{
|
||||||
@ -3151,16 +3124,10 @@ bool TABLE_SHARE::visit_subgraph(Wait_for_flush *wait_for_flush,
|
|||||||
|
|
||||||
end_leave_node:
|
end_leave_node:
|
||||||
gvisitor->leave_node(src_ctx);
|
gvisitor->leave_node(src_ctx);
|
||||||
--gvisitor->m_current_search_depth;
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (gvisitor->m_lock_open_count-- == 1)
|
if (gvisitor->m_lock_open_count-- == 1)
|
||||||
{
|
|
||||||
mysql_mutex_unlock(&LOCK_open);
|
mysql_mutex_unlock(&LOCK_open);
|
||||||
mysql_mutex_lock(&LOCK_dd_owns_lock_open);
|
|
||||||
--dd_owns_lock_open;
|
|
||||||
mysql_mutex_unlock(&LOCK_dd_owns_lock_open);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -3256,6 +3223,65 @@ bool TABLE_SHARE::wait_for_old_version(THD *thd, struct timespec *abstime,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize TABLE instance (newly created, or coming either from table
|
||||||
|
cache or THD::temporary_tables list) and prepare it for further use
|
||||||
|
during statement execution. Set the 'alias' attribute from the specified
|
||||||
|
TABLE_LIST element. Remember the TABLE_LIST element in the
|
||||||
|
TABLE::pos_in_table_list member.
|
||||||
|
|
||||||
|
@param thd Thread context.
|
||||||
|
@param tl TABLE_LIST element.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void TABLE::init(THD *thd, TABLE_LIST *tl)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(s->ref_count > 0 || s->tmp_table != NO_TMP_TABLE);
|
||||||
|
|
||||||
|
if (thd->lex->need_correct_ident())
|
||||||
|
alias_name_used= my_strcasecmp(table_alias_charset,
|
||||||
|
s->table_name.str,
|
||||||
|
tl->alias);
|
||||||
|
/* Fix alias if table name changes. */
|
||||||
|
if (strcmp(alias, tl->alias))
|
||||||
|
{
|
||||||
|
uint length= (uint) strlen(tl->alias)+1;
|
||||||
|
alias= (char*) my_realloc((char*) alias, length, MYF(MY_WME));
|
||||||
|
memcpy((char*) alias, tl->alias, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
tablenr= thd->current_tablenr++;
|
||||||
|
used_fields= 0;
|
||||||
|
const_table= 0;
|
||||||
|
null_row= 0;
|
||||||
|
maybe_null= 0;
|
||||||
|
force_index= 0;
|
||||||
|
force_index_order= 0;
|
||||||
|
force_index_group= 0;
|
||||||
|
status= STATUS_NO_RECORD;
|
||||||
|
insert_values= 0;
|
||||||
|
fulltext_searched= 0;
|
||||||
|
file->ft_handler= 0;
|
||||||
|
reginfo.impossible_range= 0;
|
||||||
|
|
||||||
|
/* Catch wrong handling of the auto_increment_field_not_null. */
|
||||||
|
DBUG_ASSERT(!auto_increment_field_not_null);
|
||||||
|
auto_increment_field_not_null= FALSE;
|
||||||
|
|
||||||
|
if (timestamp_field)
|
||||||
|
timestamp_field_type= timestamp_field->get_auto_set_type();
|
||||||
|
|
||||||
|
pos_in_table_list= tl;
|
||||||
|
|
||||||
|
clear_column_bitmaps();
|
||||||
|
|
||||||
|
DBUG_ASSERT(key_read == 0);
|
||||||
|
|
||||||
|
/* Tables may be reused in a sub statement. */
|
||||||
|
DBUG_ASSERT(!file->extra(HA_EXTRA_IS_ATTACHED_CHILDREN));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create Item_field for each column in the table.
|
Create Item_field for each column in the table.
|
||||||
|
|
||||||
|
13
sql/table.h
13
sql/table.h
@ -83,18 +83,6 @@ enum enum_table_ref_type
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Opening modes for open_temporary_table and open_table_from_share
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum open_table_mode
|
|
||||||
{
|
|
||||||
OTM_OPEN= 0,
|
|
||||||
OTM_CREATE= 1,
|
|
||||||
OTM_ALTER= 2
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1096,6 +1084,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
MDL_ticket *mdl_ticket;
|
MDL_ticket *mdl_ticket;
|
||||||
|
|
||||||
|
void init(THD *thd, TABLE_LIST *tl);
|
||||||
bool fill_item_list(List<Item> *item_list) const;
|
bool fill_item_list(List<Item> *item_list) const;
|
||||||
void reset_item_list(List<Item> *item_list) const;
|
void reset_item_list(List<Item> *item_list) const;
|
||||||
void clear_column_bitmaps(void);
|
void clear_column_bitmaps(void);
|
||||||
|
@ -565,7 +565,8 @@ bool trans_xa_end(THD *thd)
|
|||||||
else if (!xa_trans_rolled_back(&thd->transaction.xid_state))
|
else if (!xa_trans_rolled_back(&thd->transaction.xid_state))
|
||||||
thd->transaction.xid_state.xa_state= XA_IDLE;
|
thd->transaction.xid_state.xa_state= XA_IDLE;
|
||||||
|
|
||||||
DBUG_RETURN(thd->transaction.xid_state.xa_state != XA_IDLE);
|
DBUG_RETURN(thd->is_error() ||
|
||||||
|
thd->transaction.xid_state.xa_state != XA_IDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -596,7 +597,8 @@ bool trans_xa_prepare(THD *thd)
|
|||||||
else
|
else
|
||||||
thd->transaction.xid_state.xa_state= XA_PREPARED;
|
thd->transaction.xid_state.xa_state= XA_PREPARED;
|
||||||
|
|
||||||
DBUG_RETURN(thd->transaction.xid_state.xa_state != XA_PREPARED);
|
DBUG_RETURN(thd->is_error() ||
|
||||||
|
thd->transaction.xid_state.xa_state != XA_PREPARED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -478,6 +478,8 @@ int ha_myisammrg::add_children_list(void)
|
|||||||
/* Set the expected table version, to not cause spurious re-prepare. */
|
/* Set the expected table version, to not cause spurious re-prepare. */
|
||||||
child_l->set_table_ref_id(mrg_child_def->get_child_table_ref_type(),
|
child_l->set_table_ref_id(mrg_child_def->get_child_table_ref_type(),
|
||||||
mrg_child_def->get_child_def_version());
|
mrg_child_def->get_child_def_version());
|
||||||
|
/* Use the same metadata lock type for children. */
|
||||||
|
child_l->mdl_request.set_type(parent_l->mdl_request.type);
|
||||||
/* Link TABLE_LIST object into the children list. */
|
/* Link TABLE_LIST object into the children list. */
|
||||||
if (this->children_last_l)
|
if (this->children_last_l)
|
||||||
child_l->prev_global= this->children_last_l;
|
child_l->prev_global= this->children_last_l;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user